(1) export 和 export default 的區(qū)別
- export ( import ) 可以有多個,export default ( 默認(rèn)導(dǎo)出 ) 只能有一個
- export導(dǎo)出后引用需要加 { } 冕杠,export default則不需要
(2) vuex
state.js
功能:狀態(tài)數(shù)據(jù)
const state={
singer:{}
}
export default state
mutation-types.js
功能:放置方法名微姊,或者對mutations做封裝
export const SET_SINGER = 'SET_SINGER'
mutations.js
功能:操作state數(shù)據(jù)
import * as types from './mutation-types'
const matutaions = {
[types.SET_SINGER] (state,singer){ // singer是傳入的參數(shù)
state.singer=singer
}
}
export default matutaions
getters.js
功能:獲取state里的數(shù)據(jù),對state數(shù)據(jù)做映射
export const singer = state => state.singer
actions.js
功能:放異步操作
function findIndex(list, song) {
return list.findIndex((item) => {
return item.id === song.id
})
}
index.js
功能: 入口文件
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import state from './state'
import mutations from './mutations'
import createLogger from 'vuex/dist/logger' // 打印motation的修改紀(jì)錄
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
// 調(diào)試工具分预,在dev環(huán)境開啟兢交,在production環(huán)境關(guān)閉
export default new Vuex.Store({
actions,
getters,
state,
mutations,
strict: debug,
plugins: debug ? [createLogger()] : []
})
存數(shù)據(jù) ( 到 vuex 的 state 中 )
singer.vue
import {mapMutations} from 'vuex' // 語法糖
methods: {
selectSinger(singer) { // 子組件派發(fā)的this.$emit('select',item),這個item就是singer
this.$router.push({
path: `/singer/${singer.id}`
})
this.setSinger(singer)
// 在...mapMutations中取得setSinger方法,singer數(shù)據(jù)作為參數(shù)傳給該方法,該方法改變state中的singer
},
_getSingerList() {
getSingerList().then((res) => {
if (res.code === ERR_OK) {
this.singers = this._normalizeSinger(res.data.list)
}
})
},
...mapMutations({
setSinger: 'SET_SINGER' // 映射成一個setSinger方法笼痹,對應(yīng)的是mutation-types.js中的常量
})
},
取數(shù)據(jù) ( 在 vuex 的 state 中 )
singer-detail.js
import {mapGetters} from 'vuex'
computed: {
...mapGetters([ // 擴(kuò)展到computed中配喳,是一個數(shù)組
'singer'
])
}
(3) router.beforeEach((to, from, next) => { })
導(dǎo)航鉤子:作用是攔截導(dǎo)航
http://blog.csdn.net/wenyun_kang/article/details/70987840
https://segmentfault.com/a/1190000011140870
(詳細(xì))http://www.reibang.com/p/2578cc444b70
(詳細(xì))http://www.reibang.com/p/9798e3e63998
(1) 全局的鉤子router.beforeEach((to, from, next) => { } )
(2) 路由元信息 meta 字段,標(biāo)記是否需要檢測導(dǎo)航
- 在router文件夾的index.js中
router/index.js
export default new Router({
routes: [
{
path: '/',
name: 'home',
redirect: '/recommend',
meta: { // 路由元信息字段凳干,表示是否需要檢測導(dǎo)航晴裹,true表示需要檢測
needLogin: true
}
},
{
path: '/login',
component: Login
},
{
path: '/recommend',
name: 'recommend',
component: Recommend
},
{
path: '/singer',
name: 'singer',
component: Singer,
meta: {
needLogin: true
},
children: [{
path: ':id',
component: SingerDetail,
meta: {
needLogin: true
}
}]
}
]
})
- 在main.js中
main.js
router.beforeEach((to, from, next) => {
if (to.meta.needLogin) { // 如果目標(biāo)頁面需要登陸
if (window.sessionStorage.data) { // 但是同時已經(jīng)登陸過了,有session
next() // 直接跳轉(zhuǎn)到目標(biāo)頁面
} else {
alert('請先登錄')
next('/login') // 否則跳轉(zhuǎn)到登陸頁面
}
} else {
next() // 如果不需要登陸救赐,直接跳轉(zhuǎn)到目標(biāo)頁面
}
})
- 在login.js中
login.js
methods: {
login() {
this.$http.post('https://www.easy-mock.com/mock/59d2fed09cabc90bb5e5c287/music/login', {
phone: `${this.userName}`,
password: `${this.passName}`
}).then((response) => {
console.log(response, 'response')
console.log(response.data, 'response.data')
if (response.data.data) { // 如果提交成功涧团,返回數(shù)據(jù)存在
let ses = window.sessionStorage
let data = JSON.stringify(response.data.data)
ses.setItem('data', data) // 設(shè)置session,需要以字符串方式存儲
this.$router.push('/') // 跳轉(zhuǎn)路由
} else {
console.log('有錯誤')
}
})
}
}
(4) v-bind:style='' '' 綁定樣式屬性
- v-bind:style 它是一個 JavaScript 對象
http://blog.csdn.net/qiphon3650/article/details/73716220
(1)
<div class="bg-image" v-bind:style="bgStyle"> // 一般綁定到樣式屬性上,計算屬性
computed: {
bgStyle() {
return {
'background-image': `url(${this.bgImage})`,
border: '1px solid red'
}
// return `background-image:url(${this.bgImage})`
}
}
-----------------------------------------------------------------------
(2)
// 這種方式不提倡经磅,不直觀
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
(5) 在不同寬度的設(shè)備上泌绣,讓圖片寬度為設(shè)備寬度,且高度和寬度相等
- 注意:這種布局不要在class="bg-image"的div中直接寫內(nèi)容(比如文字预厌,這樣不會在div中)阿迈,需要在里面再加子div,在子div中寫內(nèi)容,子div用絕對定位
<div class="bg-image" v-bind:style="bgStyle" ref="bgImage">
<!--<div class="bg-image" v-bind:style="{color:red}">1-->
<!--filter是一個加暗的浮層-->
<div class="filter"></div>
</div>
.bg-image
position: relative
width: 100%
height: 0
padding-top: 100%
transform-origin: top
background-size: cover
.filter
position: absolute
top: 0
left: 0
width: 100%
height: 100%
background: rgba(7, 17, 27, 0.4)
(6) promise 封裝axios請求
test2.js
import axios from 'axios'
// import Vue from 'vue'
// Vue.prototype.$http = axios
export function getSongs() {
return axios.get('/api/artist/album?id=6452&limit=30').then((response) => {
return Promise.resolve(response)
})
}
-----------------------------------------------------------------------
search.vue
import {getSongs} from 'api/test2.js'
export default {
created() {
this.getData()
},
methods: {
getData() {
getSongs().then((data) => {
console.log(data)
})
}
}
}
----------------------------------------------------------------
上面的/api是使用了代理轧叽,如下配置:
config/index.js
proxyTable:{
'/api': {
target: 'http://localhost:3000/',
changeOrigin: true,
pathRewrite: {
'^/api':''
}
}
}
訪問 ('/api/artist/album?id=6452&limit=30')
其實(shí)是:http://localhost:3000/api/artist/album?id=6452&limit=30
(7)
this.$router.push() 跳轉(zhuǎn)
this.$router.back() 返回
(1) this.$router.push
selectSinger(singer) { // 子組件派發(fā)的this.$emit('select',item),這個item就是singer
this.$router.push({
path: `/singer/${singer.id}`
})
this.setSinger(singer)
// 在...mapMutation中取得setSinger方法,singer數(shù)據(jù)作為參數(shù)傳給state
},
--------------------------------------------
(2) this.$router.back()
<div class="back" v-on:click="back">
<i class="icon-back"></i>
</div>
methods: {
back() {
this.$router.back()
}
},
(8) watch 觀察者
- watch方法響應(yīng)數(shù)據(jù)的變化苗沧,當(dāng)你想要在數(shù)據(jù)變化響應(yīng)時,執(zhí)行異步操作或開銷較大的操作炭晒,這是很有用的待逞。
- Vue.js 提供了一個方法 watch,它用于觀察Vue實(shí)例上的數(shù)據(jù)變動网严。對應(yīng)一個對象识樱,鍵是觀察表達(dá)式,值是對應(yīng)回調(diào)。值也可以是方法名牺荠,或者是對象,包含選項(xiàng)驴一。
https://q.cnblogs.com/q/91448/
http://blog.csdn.net/itkingone/article/details/69568498
http://blog.csdn.net/lemon_zhao/article/details/52191527
(官網(wǎng))https://cn.vuejs.org/v2/api/#vm-watch
(知乎)https://www.zhihu.com/question/39155535?sort=created
例一:
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 question 發(fā)生改變休雌,這個函數(shù)就會運(yùn)行
question: function (newQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.getAnswer()
}
},
methods: {
getAnswer() {........}
}
})
</script>
例二:
<span style="color:#006600;"><div id="app">
<input type="text" v-model:value="childrens.name" />
<input type="text" v-model:value="lastName" />
</div>
<script type="text/javascript">
var vm = new Vue( {
el: '#app',
data: {
childrens: {
name: '小強(qiáng)',
age: 20,
sex: '男'
},
tdArray:["1","2"],
lastName:"張三"
},
watch:{
childrens:{
handler:function(val,oldval){
console.log(val.name)
},
deep:true//對象內(nèi)部的屬性監(jiān)聽,也叫深度監(jiān)聽
},
'childrens.name':function(val,oldval){
console.log(val+"aaa")
},//鍵路徑必須加上引號
lastName:function(val,oldval){
console.log(this.lastName)
}
},//以V-model綁定數(shù)據(jù)時使用的數(shù)據(jù)變化監(jiān)測
} );
vm.$watch("lastName",function(val,oldval){
console.log(val)
})//主動調(diào)用$watch方法來進(jìn)行數(shù)據(jù)監(jiān)測</span>
</script>
</body>
例三:
var v_assetManage_controller = new Vue({
el: '.LSee-index',
data: {
trendQueryTimeCtr: {
startTime: '',
endTime: ''
}
},
ready: function() {
//
},
methods: {
queryTrendData: function(){
//do some here
}
},
watch: {
'trendQueryTimeCtr.startTime': 'queryTrendData',
'trendQueryTimeCtr.endTime': 'queryTrendData'
}
});
(8) vm.$watch( expOrFn, callback, [options] )
- 參數(shù):
{string | Function} expOrFn
{Function | Object} callback
{Object} [options]
{boolean} deep // 深度監(jiān)聽肝断,一般用于對象
{boolean} immediate
返回值:{Function} unwatch - 用法:
觀察 Vue 實(shí)例變化的一個表達(dá)式或計算屬性函數(shù)杈曲。回調(diào)函數(shù)得到的參數(shù)為新值和舊值胸懈。表達(dá)式只接受監(jiān)督的鍵路徑担扑。對于更復(fù)雜的表達(dá)式,用一個函數(shù)取代趣钱。 - 選項(xiàng):deep
為了發(fā)現(xiàn)對象內(nèi)部值的變化涌献,可以在選項(xiàng)參數(shù)中指定 deep: true 。注意監(jiān)聽數(shù)組的變動不需要這么做首有。
// 鍵路徑
vm.$watch('a.b.c', function (newVal, oldVal) {
// 做點(diǎn)什么
})
// 函數(shù)
vm.$watch(
function () {
return this.a + this.b
},
function (newVal, oldVal) {
// 做點(diǎn)什么
}
)
(9) better-scroll的封裝
probeType
類型:Number
默認(rèn)值:0
可選值:1燕垃、2、3
作用:有時候我們需要知道滾動的位置井联。
當(dāng) probeType 為 1 的時候卜壕,會非實(shí)時(屏幕滑動超過一定時間后)派發(fā)scroll 事件;
當(dāng) probeType 為 2 的時候烙常,會在屏幕滑動的過程中實(shí)時的派發(fā) scroll 事件轴捎;
當(dāng) probeType 為 3 的時候,不僅在屏幕滑動的過程中蚕脏,而且在 momentum 滾動動畫運(yùn)行過程中實(shí)時派發(fā) scroll 事件侦副。momentum
類型:Boolean
默認(rèn)值:true
作用:當(dāng)快速在屏幕上滑動一段距離的時候,會根據(jù)滑動的距離和時間計算出動量蝗锥,并生成滾動動畫跃洛。設(shè)置為 true 則開啟動畫。
翻譯:momentum是動量的意思refresh
參數(shù):無
返回值:無
作用:重新計算 better-scroll终议,當(dāng) DOM 結(jié)構(gòu)發(fā)生變化的時候務(wù)必要調(diào)用確保滾動的效果正常汇竭。
<template>
<div ref="wrapper">
<slot></slot>
</div>
</template>
<script type="text/ecmascript-6">
import BScroll from 'better-scroll'
export default {
props: {
/**
* probeType
* 1 滾動的時候會派發(fā)scroll事件,會截流穴张。
* 2 滾動的時候?qū)崟r派發(fā)scroll事件细燎,不會截流。
* 3 除了實(shí)時派發(fā)scroll事件皂甘,在swipe的情況下仍然能實(shí)時派發(fā)scroll事件
*/
probeType: { // 類型
type: Number,
default: 1
},
click: { // 是否能點(diǎn)擊
type: Boolean,
default: true
},
listenScroll: { // 是否派發(fā)滾動事件
type: Boolean,
default: false
},
data: { // 列表數(shù)據(jù)
type: Array,
default: null
},
pullup: { // 是否派發(fā)滾動到底部的事件玻驻,用于上拉加載
type: Boolean,
default: false
},
pulldown: { // 是否派發(fā)頂部下拉的事件,用于下拉刷新
type: Boolean,
default: false
},
beforeScroll: { // 是否派發(fā)列表滾動開始的事件
type: Boolean,
default: false
},
refreshDelay: { // 當(dāng)數(shù)據(jù)更新后,刷新scroll的延時璧瞬。
type: Number,
default: 20
},
scrollX: { // 橫向滾動
type: Boolean,
default: false
}
},
mounted() {
setTimeout(() => {
this._initScroll()
}, 20)
},
methods: {
_initScroll() {
if (!this.$refs.wrapper) {
return
}
this.scroll = new BScroll(this.$refs.wrapper, {
probeType: this.probeType,
click: this.click,
scrollX: this.scrollX
})
// 是否派發(fā)滾動事件
if (this.listenScroll) {
let me = this
this.scroll.on('scroll', (pos) => {
me.$emit('scroll', pos)
})
}
// 是否派發(fā)滾動到底部事件户辫,用于上拉加載
if (this.pullup) {
this.scroll.on('scrollEnd', () => {
if (this.scroll.y <= (this.scroll.maxScrollY + 50)) {
this.$emit('scrollToEnd')
}
})
}
// 是否派發(fā)頂部下拉事件,用于下拉刷新
if (this.pulldown) {
this.scroll.on('touchend', (pos) => {
// 下拉動作
if (pos.y > 50) {
this.$emit('pulldown')
}
})
}
// 是否派發(fā)列表滾動開始的事件
if (this.beforeScroll) {
this.scroll.on('beforeScrollStart', () => {
this.$emit('beforeScroll')
})
}
},
// 方法代理
disable() { // 作用:禁用 better-scroll嗤锉,DOM 事件(如 touchstart渔欢、touchmove、touchend)的回調(diào)函數(shù)不再響應(yīng)瘟忱。
this.scroll && this.scroll.disable()
},
enable() { // 作用:啟用 better-scroll
this.scroll && this.scroll.enable()
},
refresh() { // 作用:重新計算 better-scroll奥额,當(dāng) DOM 結(jié)構(gòu)發(fā)生變化的時候務(wù)必要調(diào)用確保滾動的效果正常。
this.scroll && this.scroll.refresh()
},
scrollTo() { // 作用:滾動到指定的位置
this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments)
},
scrollToElement() { // 作用:滾動到指定的目標(biāo)元素
this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments)
}
// _watchData() {
// setTimeout(() => {
// this.refresh()
// }, this.refreshDelay)
// }
},
watch: {
data() {
setTimeout(() => {
this.refresh()
}, this.refreshDelay)
}
// 'data': '_watchData' //觀察data的變化访诱,當(dāng)data變化是執(zhí)行_watchData函數(shù)垫挨,上面的是直接執(zhí)行
}
}
</script>
<style scoped lang="stylus" rel="stylesheet/stylus">
</style>
(10) 事件修飾符
.stop : 阻止冒泡
.prevent : 阻止默認(rèn)事件
.capture
.self : 指定元素觸發(fā)(不包括子元素)
.once : 事件只執(zhí)行一次,特別之處:還能用在組件事件上
ps: 給組件添加原生事件触菜,需要添加.naive
<!-- 阻止單擊事件冒泡 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯(lián) -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件偵聽器時使用事件捕獲模式 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只當(dāng)事件在該元素本身 (比如不是子元素) 觸發(fā)時觸發(fā)回調(diào) -->
<div v-on:click.self="doThat">...</div>
(10) v-on:click.once="" 事件只觸發(fā)一次
- 不像其它只能對原生的 DOM 事件起作用的修飾符九榔,.once 修飾符還能被用到自定義的組件事件上。
<!-- 點(diǎn)擊事件將只會觸發(fā)一次 -->
<a v-on:click.once="doThis"></a>
(11) .snyc修飾符
- sync : 同步
- async: 異步
- .sync實(shí)際上是語法糖
- <comp :foo.sync="bar"></comp>
https://www.cnblogs.com/penghuwan/p/7473375.html
<comp :foo.sync="bar"></comp>
會被擴(kuò)展為:
<comp :foo="bar" @update:foo="val => bar = val"></comp>
當(dāng)子組件需要更新 foo 的值時玫氢,它需要顯式地觸發(fā)一個更新事件:
this.$emit('update:foo', newValue)
// (1) 父組件給子組件comp 傳遞一個foo同步屬性帚屉,值是bar
// (2) 當(dāng)子組件想要改變foo屬性時,由于子組件不能修改父組件傳過來的任何數(shù)據(jù)漾峡,所以用.sync修飾符
// (3) 當(dāng)子組件想要改變foo屬性時攻旦,向父組件派發(fā)一個'update:foo'事件,newValue為傳遞的數(shù)據(jù)
// (4) 'update:foo'事件將foo的值改為從子組件傳過來的newValue值
rank-detail.vue
<sync class="sync" v-bind:bg.sync="bb" v-if="bb"></sync>
data() {
return {
bb: true
}
}
-----------------------------------------------------------------------------
sync.vue
<div class="sync" v-on:click="goto" v-if="bb">
這里是sync組件顯示內(nèi)容
</div>
<script type="text/ecmascript-6">
export default {
props: {
bb: {
type: Boolean,
default: true
}
},
methods: {
goto() {
this.$emit('update:bg', false)
}
}
}
</script>