一、自定義組件
1、創(chuàng)建組件vue

<!--公用button-->
<template>
<div class="btn">
<button type="button">{{btnText}}</button>
</div>
</template>
<script>
export default {
</script>
<style lang="less" scoped>
</style>
2、父級(jí)引入組件并定義運(yùn)用
html:
<btn :btn-text="btnText" @touchstart.native="toPay()"></btn>
js:
import btn from '../common/btn.vue';
export default {
components: {
btn
},
}
3、一個(gè)組件的v-for
在自定義組件里,你可以像任何普通元素一樣用 v-for 。
<my-component v-for="item in items" :key="item.id"></my-component>
2.2.0+ 的版本里,當(dāng)在組件中使用 v-for 時(shí),key 現(xiàn)在是必須的。
4、組件的prop
在 Vue 中,父子組件的關(guān)系可以總結(jié)為 prop 向下傳遞,事件向上傳遞。父組件通過(guò) prop 給子組件下發(fā)數(shù)據(jù),子組件通過(guò)事件給父組件發(fā)送消息
5、HTML 特性是不區(qū)分大小寫的。所以,當(dāng)使用的不是字符串模板時(shí),camelCase (駝峰式命名) 的 prop 需要轉(zhuǎn)換為相對(duì)應(yīng)的 kebab-case (短橫線分隔式命名):
Vue.component('child', {
// 在 JavaScript 中使用 camelCase
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>' //沒有寫在html的為字符串模板
})
<!-- 在 HTML 中使用 kebab-case -->
<child my-message="hello!"></child> //寫在html的為非字符串模板需要:相對(duì)應(yīng)的 kebab-case (短橫線分隔式命名)
如果你使用字符串模板,則沒有這些限制。
二、組件父?jìng)髯訑?shù)據(jù)
1、父級(jí)綁定要傳輸?shù)臄?shù)據(jù)
<btn :btn-text="btnText" @touchstart.native="toPay()"></btn>
2、子組件接收并引用(props驗(yàn)證type寫法)

3、如果你想把一個(gè)對(duì)象的所有屬性作為 prop 進(jìn)行傳遞,可以使用不帶任何參數(shù)的 v-bind (即用 v-bind 而不是 v-bind:prop-name)。例如,已知一個(gè) todo 對(duì)象:
todo: {
text: 'Learn Vue',
isComplete: false
}
<todo-item v-bind="todo"></todo-item>
將等價(jià)于:
<todo-item
v-bind:text="todo.text"
v-bind:is-complete="todo.isComplete"
></todo-item>
三、組件子傳父數(shù)據(jù)( 自定義事件)
1、
// 子組件通過(guò)$emit發(fā)射數(shù)據(jù)
methods: {
popHide() {
this.$emit('popHide', false);
},
},
// 父級(jí)通過(guò)v-on:popHide接收數(shù)據(jù)
<gained v-show="isPopShow" :currentData = "currentData" v-on:popHide="popHide" v-if="gained"></gained>
3、非父子組件的通信
var bus = new Vue()
// 觸發(fā)組件 A 中的事件
bus.$emit('id-selected', 1)
// 在組件 B 創(chuàng)建的鉤子中監(jiān)聽事件
bus.$on('id-selected', function (id) {
// ...
})
四、父組件通過(guò)prop傳遞數(shù)據(jù)給子組件,子組件觸發(fā)事件給父組件。但父組件想在子組件上監(jiān)聽自己的click的話,需要加上native修飾符,故寫法就像下面這樣。( 給組件綁定原生事件)
<btn :btn-text="btnText" v-on:click.native="setPhone"></btn>
如果將click的native去掉,思路如下:
子組件監(jiān)聽父組件給的click事件,
子組件內(nèi)部處理click事件然后向外發(fā)送click事件:$emit("click".fn)
改造后的代碼如下(親測(cè)可用):
<template>
<button class="disable-hover button ion-button" @click="_click"
:class="[modeClass,typeClass,shapeClass,sizeClass,colorClass,roleClass,strongClass]">
<span class="button-inner">
<slot></slot>
</span>
<div class="button-effect"></div>
</button>
</template>
<script type="text/babel">
export default{
....
....
methods: {
_click: function () {
this.$emit('click', function () {
alert('inner')
})
}
}
}
</script>
父組件中這樣使用:
<ion-button @click="primary()" color="primary">primary</ion-button>
五,filters用法
<p>本期學(xué)習(xí)計(jì)劃開啟日期為{{time | dateTransform}}</p>
filters: {
dateTransform(time) {
let reg =/(\d{4})\-(\d{2})\-(\d{2})/;
return time.replace(reg, "$1年$2月$3日");
}
},
六,獲取dom方法
//html
<div ref='outBox' class="out-box">
//js中獲取
let box = this.$refs.box;
let outBox = this.$refs.outBox;
七、設(shè)置全局變量
main.js中寫入
Vue.prototype.globalBadges = []; // 徽章全局變量用于儲(chǔ)存臨時(shí)徽章彈出
需要用到的地方:
this.globalBadges
如果需要的數(shù)據(jù)量很大得用vuex來(lái)處理數(shù)據(jù)了;
八、keep-alive的運(yùn)用;
1.基本用法
vue2.0提供了一個(gè)keep-alive組件
用來(lái)緩存組件,避免多次加載相應(yīng)的組件,減少性能消耗
<keep-alive>
<component>
<!-- 組件將被緩存 -->
</component>
</keep-alive>
有時(shí)候 可能需要緩存整個(gè)站點(diǎn)的所有頁(yè)面,而頁(yè)面一般一進(jìn)去都要觸發(fā)請(qǐng)求的
在使用keep-alive的情況下
<keep-alive><router-view></router-view></keep-alive>
將首次觸發(fā)請(qǐng)求寫在created鉤子函數(shù)中,就能實(shí)現(xiàn)緩存,
比如列表頁(yè),去了詳情頁(yè) 回來(lái),還是在原來(lái)的頁(yè)面
2.緩存部分頁(yè)面或者組件
(1)使用router. meta屬性
// 這是目前用的比較多的方式
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
router設(shè)置
routes: [
{ path: '/', redirect: '/index', component: Index, meta: { keepAlive: true }},
{
path: '/common',
component: TestParent,
children: [
{ path: '/test2', component: Test2, meta: { keepAlive: true } }
]
}
// 表示index和test2都使用keep-alive
(2).使用新增屬性inlcude/exclude
2.1.0后提供了include/exclude兩個(gè)屬性 可以針對(duì)性緩存相應(yīng)的組件
<!-- comma-delimited string -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- regex (use v-bind) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
//其中a,b是組件的name
注意:這種方法都是預(yù)先知道組件的名稱的
(2)動(dòng)態(tài)判斷
<keep-alive :include="includedComponents">
<router-view></router-view>
</keep-alive>
includedComponents動(dòng)態(tài)設(shè)置即可
九、關(guān)于v-bind、v-on、v-model
v-bind
縮寫:
:預(yù)期:
any (with argument) | Object (without argument)參數(shù):
attrOrProp (optional)-
修飾符:
-
.prop- 被用于綁定 DOM 屬性。 -
.camel- (2.1.0+) 將 kebab-case 特性名轉(zhuǎn)換為 camelCase. -
.sync(2.3.0+) 語(yǔ)法糖,會(huì)擴(kuò)展成一個(gè)更新父組件綁定值的 v-on 偵聽器。
-
用法:
動(dòng)態(tài)地綁定一個(gè)或多個(gè)特性,或一個(gè)組件 prop 到表達(dá)式。
在綁定class或style特性時(shí),支持其它類型的值,如數(shù)組或?qū)ο?。可以通過(guò)下面的教程鏈接查看詳情。
在綁定 prop 時(shí),prop 必須在子組件中聲明??梢杂眯揎椃付ú煌慕壎愋?。
沒有參數(shù)時(shí),可以綁定到一個(gè)包含鍵值對(duì)的對(duì)象。注意此時(shí)class和style綁定不支持?jǐn)?shù)組和對(duì)象。
v-on
縮寫:
@預(yù)期:
Function | Inline Statement | Object參數(shù):
event-
修飾符:
-
.stop- 調(diào)用 event.stopPropagation()。 -
.prevent- 調(diào)用 event.preventDefault()。 -
.capture- 添加事件偵聽器時(shí)使用 capture 模式。 -
.self- 只當(dāng)事件是從偵聽器綁定的元素本身觸發(fā)時(shí)才觸發(fā)回調(diào)。 -
.{keyCode | keyAlias}- 只當(dāng)事件是從特定鍵觸發(fā)時(shí)才觸發(fā)回調(diào)。 -
.native- 監(jiān)聽組件根元素的原生事件。 -
.once- 只觸發(fā)一次回調(diào)。 -
.left- (2.2.0) 只當(dāng)點(diǎn)擊鼠標(biāo)左鍵時(shí)觸發(fā)。 -
.right- (2.2.0) 只當(dāng)點(diǎn)擊鼠標(biāo)右鍵時(shí)觸發(fā)。 -
.middle- (2.2.0) 只當(dāng)點(diǎn)擊鼠標(biāo)中鍵時(shí)觸發(fā)。 -
.passive- (2.3.0) 以 { passive: true } 模式添加偵聽器
-
用法:
綁定事件監(jiān)聽器。事件類型由參數(shù)指定。表達(dá)式可以是一個(gè)方法的名字或一個(gè)內(nèi)聯(lián)語(yǔ)句,如果沒有修飾符也可以省略。
從2.4.0開始,v-on同樣支持不帶參數(shù)綁定一個(gè)事件/監(jiān)聽器鍵值對(duì)的對(duì)象。注意當(dāng)使用對(duì)象語(yǔ)法時(shí),是不支持任何修飾器的。
用在普通元素上時(shí),只能監(jiān)聽 原生 DOM 事件。用在自定義元素組件上時(shí),也可以監(jiān)聽子組件觸發(fā)的自定義事件。
在監(jiān)聽原生 DOM 事件時(shí),方法以事件為唯一的參數(shù)。如果使用內(nèi)聯(lián)語(yǔ)句,語(yǔ)句可以訪問(wèn)一個(gè)$event屬性:v-on:click="handle('ok', $event)"。
v-model
也可以綁定數(shù)據(jù),但是他是用在表單控件上的,用于實(shí)現(xiàn)雙向數(shù)據(jù)綁定,所以如果你用在除了表單控件以外的標(biāo)簽是沒有任何效果的。
v-model 會(huì)忽略所有表單元素的 value、checked、selected 特性的初始值而總是將 Vue 實(shí)例的數(shù)據(jù)作為數(shù)據(jù)來(lái)源。你應(yīng)該通過(guò) JavaScript 在組件的 data 選項(xiàng)中聲明初始值。
.lazy
在默認(rèn)情況下,v-model 在每次 input 事件觸發(fā)后將輸入框的值與數(shù)據(jù)進(jìn)行同步 (除了上述輸入法組合文字時(shí))。你可以添加 lazy 修飾符,從而轉(zhuǎn)變?yōu)槭褂?change 事件進(jìn)行同步:
<!-- 在“change”時(shí)而非“input”時(shí)更新 -->
<input v-model.lazy="msg" >
.number
如果想自動(dòng)將用戶的輸入值轉(zhuǎn)為數(shù)值類型,可以給 v-model 添加 number 修飾符:
<input v-model.number="age" type="number">
這通常很有用,因?yàn)榧词乖?type="number" 時(shí),HTML 輸入元素的值也總會(huì)返回字符串。
.trim
如果要自動(dòng)過(guò)濾用戶輸入的首尾空白字符,可以給 v-model 添加 trim 修飾符:
<input v-model.trim="msg">
十、計(jì)算屬性和監(jiān)聽器
<template>
<div>
<input type="text" name="" v-model="myVal"><br/>
{{ myValueWithoutNum }}<br/>
{{ getMyValueWithoutNum() }}<br/>
<input type="text" name="" v-model="myVal1"><br/>
</div>
</template>
<script>
export default {
data () {
return {
myVal: '',
myVal1:''
}
},
computed: { //計(jì)算屬性
myValueWithoutNum () {
return this.myVal.replace(/\d/g, '')
}
},
methods: {// 方法
getMyValueWithoutNum () {
return this.myVal.replace(/\d/g, '')
}
},
watch: { //監(jiān)聽器
myVal1 (val, oldval) {
console.log(val, oldval)
}
}
}
</script>
相關(guān)文檔請(qǐng)看:https://cn.vuejs.org/v2/guide/computed.html
十一、數(shù)組更新檢測(cè)——變異方法
變異方法
Vue 包含一組觀察數(shù)組的變異方法,所以它們也將會(huì)觸發(fā)視圖更新。這些方法如下:
push()pop()shift()unshift()splice()sort()reverse()
你打開控制臺(tái),然后用前面例子的 items 數(shù)組調(diào)用變異方法:example1.items.push({ message: 'Baz' }) 。
替換數(shù)組
變異方法 (mutation method),顧名思義,會(huì)改變被這些方法調(diào)用的原始數(shù)組。相比之下,也有非變異 (non-mutating method) 方法,例如:filter(), concat() 和 slice() 。這些不會(huì)改變?cè)紨?shù)組,但總是返回一個(gè)新數(shù)組。當(dāng)使用非變異方法時(shí),可以用新數(shù)組替換舊數(shù)組:
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
你可能認(rèn)為這將導(dǎo)致 Vue 丟棄現(xiàn)有 DOM 并重新渲染整個(gè)列表。幸運(yùn)的是,事實(shí)并非如此。Vue 為了使得 DOM 元素得到最大范圍的重用而實(shí)現(xiàn)了一些智能的、啟發(fā)式的方法,所以用一個(gè)含有相同元素的數(shù)組去替換原來(lái)的數(shù)組是非常高效的操作。
注意事項(xiàng)
由于 JavaScript 的限制,Vue 不能檢測(cè)以下變動(dòng)的數(shù)組:
- 當(dāng)你利用索引直接設(shè)置一個(gè)項(xiàng)時(shí),例如:
vm.items[indexOfItem] = newValue - 當(dāng)你修改數(shù)組的長(zhǎng)度時(shí),例如:
vm.items.length = newLength
為了解決第一類問(wèn)題,以下兩種方式都可以實(shí)現(xiàn)和 vm.items[indexOfItem] = newValue 相同的效果,同時(shí)也將觸發(fā)狀態(tài)更新:
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice
example1.items.splice(indexOfItem, 1, newValue)
為了解決第二類問(wèn)題,你可以使用 splice:
example1.items.splice(newLength)
舉例:
<template>
<div>
<ul id="example-1">
<li v-for="item in items">
{{ item }}
</li>
</ul>
</div>
</template>
<script>
export default {
data () {
return {
items: [
'11111',
'22222',
'33333'
]
}
},
mounted(){
//this.items[0] = 'aaaaa'; 這種賦值方法視圖不更新數(shù)據(jù)
this.items.splice(0, 1, 'aaaaa') // 視圖更新數(shù)據(jù)
},
}
</script>
十二、 使用插槽分發(fā)內(nèi)容
十三、this.$nextTick
官方文檔解釋如下:
在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個(gè)方法,獲取更新后的 DOM。
我理解的官方文檔的這句話的側(cè)重點(diǎn)在最后那半句獲取更新后的DOM,獲取更新后的DOM言外之意就是什么操作需要用到了更新后的DOM而不能使用之前的DOM或者使用更新前的DOM或出問(wèn)題,所以就衍生出了這個(gè)獲取更新后的DOM的Vue方法。所以放在Vue.nextTick()回調(diào)函數(shù)中的執(zhí)行的應(yīng)該是會(huì)對(duì)DOM進(jìn)行操作的 js代碼,比如Swiper擴(kuò)展包的
var swiper = new Swiper('.swiper-container', {
pagination: '.swiper-pagination',
nextButton: '.swiper-button-next',
prevButton: '.swiper-button-prev',
paginationClickable: true,
spaceBetween: 30,
centeredSlides: true,
autoplay: 2500,
autoplayDisableOnInteraction: false
});
什么時(shí)候需要用的Vue.nextTick()
1、你在Vue生命周期的created()鉤子函數(shù)進(jìn)行的DOM操作一定要放在Vue.nextTick()的回調(diào)函數(shù)中。原因是什么呢,原因是在created()鉤子函數(shù)執(zhí)行的時(shí)候DOM 其實(shí)并未進(jìn)行任何渲染,而此時(shí)進(jìn)行DOM操作無(wú)異于徒勞,所以此處一定要將DOM操作的js代碼放進(jìn)Vue.nextTick()的回調(diào)函數(shù)中。與之對(duì)應(yīng)的就是mounted鉤子函數(shù),因?yàn)樵撱^子函數(shù)執(zhí)行時(shí)所有的DOM掛載和渲染都已完成,此時(shí)在該鉤子函數(shù)中進(jìn)行任何DOM操作都不會(huì)有問(wèn)題 。
2、在數(shù)據(jù)變化后要執(zhí)行的某個(gè)操作,而這個(gè)操作需要使用隨數(shù)據(jù)改變而改變的DOM結(jié)構(gòu)的時(shí)候,這個(gè)操作都應(yīng)該放進(jìn)Vue.nextTick()的回調(diào)函數(shù)中。
原因是,Vue是異步執(zhí)行dom更新的,一旦觀察到數(shù)據(jù)變化,Vue就會(huì)開啟一個(gè)隊(duì)列,然后把在同一個(gè)事件循環(huán) (event loop) 當(dāng)中觀察到數(shù)據(jù)變化的 watcher 推送進(jìn)這個(gè)隊(duì)列。如果這個(gè)watcher被觸發(fā)多次,只會(huì)被推送到隊(duì)列一次。這種緩沖行為可以有效的去掉重復(fù)數(shù)據(jù)造成的不必要的計(jì)算和DOm操作。而在下一個(gè)事件循環(huán)時(shí),Vue會(huì)清空隊(duì)列,并進(jìn)行必要的DOM更新。
當(dāng)你設(shè)置 vm.someData = 'new value',DOM 并不會(huì)馬上更新,而是在異步隊(duì)列被清除,也就是下一個(gè)事件循環(huán)開始時(shí)執(zhí)行更新時(shí)才會(huì)進(jìn)行必要的DOM更新。如果此時(shí)你想要根據(jù)更新的 DOM 狀態(tài)去做某些事情,就會(huì)出現(xiàn)問(wèn)題。。為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM ,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback) 。這樣回調(diào)函數(shù)在 DOM 更新完成后就會(huì)調(diào)用。
十四、生命周期函數(shù)的運(yùn)用

beforecreate : 舉個(gè)栗子:可以在這加個(gè)loading事件
created :在這結(jié)束loading,還做一些初始化,實(shí)現(xiàn)函數(shù)自執(zhí)行
mounted : 在這發(fā)起后端請(qǐng)求,拿回?cái)?shù)據(jù),配合路由鉤子做一些事情
beforeDestory: 你確認(rèn)刪除XX嗎? destoryed :當(dāng)前組件已被刪除,清空相關(guān)內(nèi)容
十五、 非父子組件的通信
有時(shí)候,非父子關(guān)系的兩個(gè)組件之間也需要通信。在簡(jiǎn)單的場(chǎng)景下,可以使用一個(gè)空的 Vue 實(shí)例作為事件總線:
var bus = new Vue()
// 觸發(fā)組件 A 中的事件
bus.$emit('id-selected', 1)
// 在組件 B 創(chuàng)建的鉤子中監(jiān)聽事件
bus.$on('id-selected', function (id) {
// ...
})
在復(fù)雜的情況下,我們應(yīng)該考慮使用專門的狀態(tài)管理模式。
一篇有關(guān)Vue2.0子同級(jí)組件之間數(shù)據(jù)交互文章:http://blog.csdn.net/wang_meiwei/article/details/75948844