此篇文章是我基于研究vue文檔三遍的基礎上,覺得還有點難理解或者難記的知識點總結
列表渲染
1.渲染組件必須加key,并且屬性是手動傳遞給組件的<my-componentv-for="(item, index) in items"v-bind:item="item"v-bind:index="index"v-bind:key="item.id"></my-component> 2.v-for和v-if用在同一個節點上面,會先執行v-for然后再執行v-if 3.使用v-for最好加上key值,因為vue本身是基于就地更換的原則,也就是你在1-100之間再插入一個數值比如5,那么原來的5和后面的數據都會依次加一,這樣的效率是非常低的,如果你傳遞了key做唯一的標識,那么插入的5就插在4后面了,后面的數據就不變了,只是位置挪了下
事件對象
- 要使用事件對象,必須在調用的時候傳遞$event,不能是其他的名字
常用的事件修飾符
.stop 阻止冒泡 .prevent 阻止默認行為 .capture 使用事件捕獲 .self 自身觸發 .once 觸發一次
按鍵修飾符
.enter .tab .delete .esc .space .up .down .left .right 自定義修飾符 Vue.config.keyCodes.f1 = 12
鼠標按鍵修飾符
.left .right .middle
表單
表單修飾符 .lazy v-model默認是監聽oninput事件的加上這個修飾符,就是監聽onchange事件 <input v-model.lazy="msg" > .number 將用戶輸入值轉換成數字 .trim 自動將用戶輸入的首尾空格去掉
組件通信
1.父組件傳遞信息給子組件子組件要想得到父組件的數據,只需要在子組件內部通過props顯示的聲明自己想要什么屬性,是不是有點意思,就像女的問男的要東西一樣,我要lv包包。聲明之后父組件將數據傳遞給子組件就ok了,如下Vue.component('child',{props: ['message','myMessage'],template: '<span>{{ message }}</span>'})在父組件中使用 <child message="hello!" :my-message="parentMsg"></child> 即可注意:在子組件中不能修改父組件傳遞過來的數據,只能做備份來修改,并且引用類型要深拷貝 2.在父組件中通過傳遞非props屬性,將自動添加到子組件根元素上面,如下<bs-date-input data-3d-date-picker="true"></bs-date-input>如果子組件上面已經存在了同名屬性,一般都是直接替換的,但是class和style是和子組件的class和style合并的 3.子組件通知父組件在子組件中觸發某個事件同時v-on:click="childfunciton",可以通過在childfunction內部添加this.$emit('somefunction')通知觸發父組件中的事件,在父組件中通過v-on:somefunction="parentfunction"接受到通知,然后觸發父組件中的parentfunction事件,也就是說在父組件中,將v-on用在子組件標簽上面并不是給子組件綁定事件而是監聽子組件內部的消息,但是如果確實想綁定一個事件給子組件可以通過添加.native修飾符,如下<my-component v-on:click.native="doTheThing"></my-component>這個事件將直接綁定到子組件的根元素 4.子組件父組件數據雙向綁定在父組件中的子組件標簽上綁定屬性使用.sync修飾符,即可完成數據雙向綁定,如下<child :foo.sync="bar"></child>在parent組件內部定義bar屬性,即可將bar值實時的通過foo傳遞給子組件在子組件內部通過this.$emit('update:foo','hahahha');可以在任意時刻修改父組件中的bar值,此函數內部其實執行的是 bar => bar = val,實際上就是直接給bar賦值,但是只能采用這種方式 5.其實上面說的組件通信還是基礎的,下面來看一個高級點的<input v-model="something">v-model其實,就是下面的簡寫形式<input v-bind:value="something" v-on:input="something = $event.target.value">同樣v-model也可以用在組件身上,就是如下的樣子了<custom-input :value="something" @input="value => { something = value }"></custom-input>所以知道這上面兩點就可以實現自定義組件v-model功能了下面是child.vue的代碼<div><input type="text" :value="value" @input="updateValue($event.target.value)">{{value}}</div>export default {props: ['value'],methods: {updateValue(value){this.$emit('input',value)}},}下面是father.vue的代碼<child v-model="price"></child>data () {return {price: ''}}在子組件中的input中輸入數據,可以動態的反應到父組件中,實現雙向綁定由于默認是value和input如果想改變這個默認的,可以在子組件中,使用model如下在子組件中聲明model: {prop: 'checked',event: 'change'},props: {checked: Boolean,value: String}所以使用<my-checkbox v-model="foo" value="some value"></my-checkbox>其實就是下面的簡寫<my-checkbox :checked="foo" @change="val => { foo = val }" value="some value"></my-checkbox> 6.非父子組件之間的通信非父子組件之間的通信就要使用$on了首先要有一個空的vue實例var bus = new Vue();如果你使用vue的webpack項目的話,這個東西你要單獨的加在一個js文件中以store.js為例,添加如下代碼import Vue from 'vue'window.bus = new Vue();并且還要在main.js中通過import './store.js'導入,這時就可以在vue項目全局使用bus了如果在一個組件中需要傳遞消息,就使用bus.$emit('fn', 1)傳遞數據在要接受數據的組件中使用,bus.$on('fn',function(value){...})即可 講到這兒,vue最核心的部分也就將完了,弄懂這塊兒東西,相信后面的學習就易如反掌了 7.使用slot實現內容分發實際工作中組件的組成大多數是類似下面的<parent><child><someother-component></someother-component></child></parent>slot的作用就是用來處理嵌套在組件標簽內部的內容 8.單一slot如果只有一個slot標簽并且沒有任何屬性,slot標簽將會被全部替換成嵌套在組件標簽內部的內容,如果slot標簽自身包裹內容,這個內容只會在組件標簽內部不包含任何東西的時候展示,demo如下如果一個child組件的模板內容如下<div><h2>I'm the child title</h2><slot>這里面的內容只會在沒有插入內容時顯示</slot></div>然后<child>hahahhahahah</child>那么hahahhahahah就會替換slot成為child模板的一部分 9.命名slot可以給slot起個名字,比如<slot name="header"></slot>然后給組件標簽內容添加slot屬性,屬性值和上面的名字相同,就可以實現特殊指派了,如<child><h1 slot="header">指定的內容</h1></child>這樣就實現的需求導入了 10.局部slot上面講的slot都是可以實現父組件傳遞數據到子組件中,現在想實現將子組件中的數據傳遞到slot要替換的內容中可以在子組件中的slot插槽中添加任意屬性,如 <slot text="子組件child中的數據"></slot>然后,在子組件標簽內部,如下<parent><child>// 必須使用template標簽,并且添加scope屬性,屬性值props就是包含slot傳遞的數據對象<template scope="props"><span>父組件parent中的數據</span><span>{{props.text}}</span></template></child></parent> 11.動態組件可以使用同一個綁定點,動態的切換渲染不同的組件,要實現這個功能要借助component標簽和is屬性<component :is="currentView"></component> vue實例代碼如下var vm = new Vue({el: "#example",data: {currentView: 'home'},components: { home,posts,archive }}) 通過改變currentView的值,可以實現動態切換組件 上面這種寫法可以滿足局部組件,也就是你自己定義的組件的切換,但是如果你使用全局組件,比如某些UI組件庫中的組件,那么就要像下面這樣用var Home = {template: ...};var vm = new Vue({el: "#example",data: {currentView: Home}});如果你想將切換渲染過的組件保留在內存中可以使用keep-alive將動態組件包裹<keep-alive><component :is="currentView">...</component><keep-alive>
vue動畫效果
**vue的過渡 過渡一般用于元素的插入,刪除,移除 下面講解過渡的知識1.對單個的元素或者組件使用過渡使用transition標簽包裹要應用過渡的元素<transition name="fade"><p v-if="show">hello</p></transition>當上面的p元素在顯示和隱藏中間切換時,會發生以下事情第一,檢測目標元素,自動添加或移除css過渡類名第二,執行transition的鉤子函數第三,如果上面兩步驟都沒有對應的設置,那么不會應用過渡效果2.過渡的類名v-enter 進入的開始狀態,在元素插入之前添加,在元素插入之后刪除v-enter-active 整個進入過程的狀態,連續的畫面,這個類就是用來定義動畫的持續時間,延遲和線性函數的v-enter-to 進入的結束狀態,在元素插入之后添加,在整個enter-active結束后刪除v-leave 消失的開始狀態v-leave-active 整個消失的過程v-leave-to 消失的結束狀態上面的這些類名的v是默認的前綴,你可以給transition標簽指定name屬性,用來自定義類名前綴上面提到的元素的插入和移除就是頁面上dom元素的一瞬間的狀態3.css過渡就是指定好開始和結束的css樣式,然后定義動畫的執行過程,如下所示.v-enter-active,.v-leave-active{transition: all .3s ease;}.v-enter,.v-leave-to{transform: translateX(10px);opacity: 0;}4.css動畫上面都是應用的transition,這里是animation,其實類似.v-enter-active{animation: bounce-in .5s;}.v-leave-active{animation: bounce-in .5s;}@keyframes bounce-in {0% {transform: scale(0);}50% {transform: scale(1.5);}100% {transform: scale(1);}}5.css過渡類名如果你使用animate.css這類的第三方css庫,可以借助如下的類名enter-classenter-active-classenter-to-classleave-classleave-active-classleave-to-class使用demo<transitionenter-active-class="animated tada"leave-active-class="animated bounceOutRight"><p v-if="show">hello</p></transition>6.如何區分animation和transition當你的動畫中同時使用transition形式和animation形式的動畫,必須添加type屬性,指定屬性值為animation或者transition7.指定動畫持續時間vue默認的動畫持續時間是基于根過渡元素,內部的子過渡元素的持續時間如果長于根過渡元素將會被忽略,所以可以在transition標簽上面添加duration屬性,demo如下<transition :duration="1000">...</transition><transition :duration="{enter: 500,leave: 800}"></transition>8.添加動畫鉤子函數,這部分內容用的比較少,感興趣自行了解9.對初次渲染的元素添加過渡添加appear屬性 <transition appear> </transition>添加這個屬性之后,會自動應用之前指定好的enter和leave的動畫,如果想實現單獨的動畫功能可以使用如下的方式<transitionappearappear-class="..."appear-to-class="..."appear-active-class="..."></transition>10.在多個元素中應用過渡上面討論的都是基于單個過渡元素,下面討論多個元素的過渡一般使用v-if/v-else在元素之前切換,相同的元素在切換的時候回復用,所以要添加key屬性,如下<transition><button v-if="isEditing" key="save">Save</button><button v-else key="edit">Edit</button></transition>此外,很可以添加mode屬性,用來指定顯示和隱藏的先后順序in-out 先入后出out-in 先出后入11.列表過渡上面講的都是一次過渡一個元素,現在講一次過渡多個元素過渡多個元素就要借助transition-group并且還要給需要過渡的元素添加key屬性,可以給transition-group標簽添加tag屬性,指定具體渲染后的元素,還可以添加.v-move類,當元素的位置變化了,自動添加此類,此動畫功能只適用于非display: inline元素 **過渡state數據可以對數字型的數據,顏色值,這類的數據做過渡效果,主要是配合第三方庫來做的,感興趣的自己去看吧
render函數
講實話這部分內容在實際使用中,幾乎用不上,個人感覺vue的單文件組件,已經替代了這個的功能,所以說強大的jsx功能在vue中可能就是一個擺設而已,這也是為什么高端互聯網企業選擇react的原因了吧 vue的render函數說白了就是用js編寫html,說實話和jsx比起來,render是非常麻煩的 vue中寫render就不需要template選項了Vue.component('demo-render',{render: function(createElement){// 這個函數的結果就是組件的templatereturn createElement(// 這個函數接受三個參數'div', 可以是組件也可以是html標簽{}, 當前vnode的屬性對象,這個屬性對象的介紹請看下面[] 字符串或者數組都可以,子節點,如果子節點下面還有子節點可以再次調用createElement方法)}}) 屬性對象的介紹{'class': {//v-bind:class},style: {//v-bind:style},attrs: {//正常的html屬性如id這類的},props: {//當前的節點是另外一個組件的話,這個就是傳遞給組件的屬性對象},domoProps: {//Dom節點的屬性對象比如innerHTML},on: {//v-on: 不支持修飾符},nativeOn: {// 只能在當前的節點是其它組件的時候生效},directives: [//自定義指令],slot: 'somename', //指定slot標簽,用于插入內容,屬性值是slot的name屬性值scopedSlots: {// 說實話這個東西對于初學者是很難懂的,我也是看了很多遍才明白/*局部插槽顧名思義,其實就是用來給子組件使用的,所以這部分內容就直接放在render里面編寫default: props => createElement('span',props.text);上面的代碼和下面的原始寫法是表達的意思是一模一樣的<template scope="props"><span>{{props.text}}</span></template>*/},key: 'myKey', 就是key屬性ref: 'myRef' 當前vnode的引用} 使用render的注意點所有的render內部使用的vnode必須都是獨一無二的,不同使用相同vnode的引用可以在vue中使用jsx代替你,render函數的復雜寫法,例子如下render (h) {return (<AnchoredHeading level={1}><span>Hello</span> world!</AnchoredHeading>)}這就是jsx語法,通俗易懂具體的學習地址https://github.com/vuejs/babel-plugin-transform-vue-jsx#usage建議:如果你被jsx的魅力所吸引,我個人覺得還是去學react的吧,在vue中的單文件組件完全可以滿足你的項目開發需求,如果你在.vue文件中使用jsx或者render會變得非常奇怪,在template中使用html又在js中使用html簡直就是怪胎
自定義指令
說實話,這部分內容我不太想寫出來,一門技術總有好的和壞的反面,偶爾了解一些不太好的東西,對自己學習其他知識,可以擴展視野 這部分內容就是自己寫一個指令比如v-myDirective,然后利用vue提供的鉤子函數,在合適的時機觸發他們。簡單demo如下Vue.directive('focus',{// 全局指令})或者directive: {focus: {// 局部指令// 可以在這里面指定鉤子函數,表示在何時執行這些鉤子函數// 說白了就是利用元素的生命周期鉤子實現所謂的自定義指令和vue實例的生命周期鉤子本質是一樣的,呵呵bind: function(// 所有的鉤子函數在這里面都可以傳遞參數,參數后面講){// 當指令綁定到元素上執行,只執行一次},inserted: // 元素插入的時候執行,update: // 元素自身更新,執行,componentUpdated: // 子組件更新執行,unbind: // 解綁的時候執行}}具體使用,就在需要的元素上面直接寫上指令名稱即可 <input v-focus> 鉤子函數的參數el // 綁定的dom元素binding // 關于指令的相關屬性對象,細節自己看vnode ,oldVnode // 虛擬節點對象 這部分內容了解,就可以了
Mixins混入
這部分內容用的也比較少,不過當你的組件中有很多重復的method或者其他的選項,可以使用這個減少冗余代碼 一個mixin對象可以包含實例的任何選項var myMixin = {created: function(){this.hello();},methods: {hello: function(){console.log('hello from mixin!')}}}var Component = Vue.extend({mixins: [myMixin]})var component = new Component(); 混入的規則如下1.鉤子函數會放進一個隊列里面,先執行mixin對象中的鉤子,然后執行實例的鉤子2.methods,components,directives都會被合并成一個對象,同名的屬性只會使用組件的,舍棄掉mixin對象的3.全局混入全局混入盡量不要用會污染所有的vue實例Vue.mixin({created: function() {...}})4.用戶自定義選項的合并默認是組件的直接覆蓋掉mixin對象的同名屬性如果想對自定義選項myOption應用自定義邏輯,可以使用如下的函數 Vue.config.optionMergeStrategies.myOption = function(toVal,fromVal){// ...}如果自定義選項是對象的話也可以使用methods選項的合并規則var strategies = Vue.config.optionMergeStrategies;strategies.myOption = strategies.methods
結語
有能力的同學,我建議去學學react,畢竟到這兒,vue你已經精通了