二檔視頻固然要比一檔視頻難一點,若是前面的內容尚未消化完畢的話,仍是建議你們繼續消化前面的內容,而後再看接下來的部分。這一部分是VUE的核心,講到組件化開發的基礎部分,多學,多練。javascript
Vue官網給出的生命週期圖html
<img src='https://cn.vuejs.org/images/l...' >
這張圖裏包含了基本的生命週期,實際上生命週期鉤子函數還有兩個不在圖內(activated,deactivated),這兩個生命週期函數這裏不給你們講,若是你們有興趣能夠自行到VUE官網看文檔,工做中用到他們的機會很少,這邊講也會擾亂你們的學習進程。這裏咱們經過代碼來說解Vue的生命週期vue
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .active{ color:red } </style> </head> <body> <div id="app"> <button v-on:click="add">+</button>{{num}}<button @click="minus">-</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el:"#app", data:{ num:1 }, methods:{ add(){ this.num++ }, minus(){ this.num-- } }, beforeCreate:function(){ console.log('頁面初始化以後馬上執行'); }, created:function(){ console.log('頁面初始化完成以後created,這裏模板尚未渲染呢!'); }, beforeMount:function(){ console.log('組件掛載以前beforeMount'); }, mounted:function(){ console.log('組件掛載以後mounted'); }, beforeUpdate:function(){ console.log('組件更新前beforeUpdate'); }, updated:function(){ console.log('組件更新後updated'); }, // activated:function(){ // console.log('activated'); // }, // deactivated:function(){ // console.log('deactivated'); // }, 你只須要知道這兩個生命週期是在這個位置進行就行了,別的能夠不要想太多。 beforeDestroy:function(){ console.log('組件銷燬以前beforeDestroy'); }, destroyed:function(){ console.log('組件銷燬後destroyed') } }) </script> </body> </html>
這些生命週期函數大致就演示到這裏,剩下的兩個沒能給你們展現的請你們牢記,咱們開始學組件的時候,就能夠體會到這兩個鉤子函數的用法了。java
Vue.component
註冊全局組件
Vue.component("組件名",{ 組件的各類屬性(模板啊,data啊,方法啊,生命週期啊之類的。) }), (視頻裏有一句口誤,應該是小駝峯。手動捂臉)node
這個全局API看過之後,咱們來實現一個組件的hello worldvue-cli
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <shuai-qm></shuai-qm> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> Vue.component("shuai-qm",{ data(){ return{ hello:'hello world' } }, template:'<h1>{{hello}}</h1>' }) var app = new Vue({ el:"#app", data:{ message:'Hello Word', isTrue:true, }, }) </script> </body> </html>
一個全局組件的hello world就完成了,可是你們是否是以爲全局組件很是不踏實?隨時可能一個變更摧毀咱們的項目?
那不要緊,接下來是局部組建的註冊方法。express
Vue的components屬性npm
咱們在註冊局部組建的時候,須要把局部組建掛載到Vue構造器的components內,注意:全局api不帶s,而這個屬性帶s。不說廢話,咱們先來構造一個。api
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> {{message}} <shuai-qm></shuai-qm> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el:"#app", data:{ message:'Hello World', isTrue:true, }, components:{ "shuaiQm":{ data(){ return{ hello:"hello world" } }, template:'<h1>{{hello}}</h1>' } } }) </script> </body> </html>
這樣咱們就獲得了一個能夠hello world的局部組件,可是,一堆組建都這個樣子羅列出來的話,會將咱們的項目弄得體無完膚?
因此咱們抽離一下代碼。變成這樣數組
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> {{message}} <shuai-qm></shuai-qm> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var shuaiQm = { data(){ return{ hello:"hello world" } }, template:'<h1>{{hello}}</h1>' } var app = new Vue({ el:"#app", data:{ message:'Hello World', isTrue:true, }, components:{ "shuaiQm":shuaiQm, } }) </script> </body> </html>
是否是用vue-cli開發過的同窗就比較眼熟了?那麼問題又來了,組件裏面的html全都是寫的字符串,都這麼玩下去,要亂死啊,沒問題,咱們繼續抽離。
這裏介紹的就是vue的template用法了,立刻又是一個cli黨眼熟的東西
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <template id="shuaiQm"> <h1>{{hello}}</h1> </template> <!-- 上面是html模板的用法,下面是script模板的用法,使用<script>標籤時,type指定爲text/x-template,意在告訴瀏覽器這不是一段js腳本,瀏覽器在解析HTML文檔時會忽略<script>標籤內定義的內容。--> <!-- 推薦 --> <script type="x-template" id="shuaiQm2"> <h2 style="color:blue">{{hello}}</h2> </script> <body> <div id="app"> {{message}} <shuai-qm></shuai-qm> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var shuaiQm = { data(){ return{ hello:"hello world" } }, template:"#shuaiQm2" } var app = new Vue({ el:"#app", data:{ message:'Hello World', isTrue:true, }, components:{ "shuaiQm":shuaiQm, } }) </script> </body> </html>
拆出來之後是否是莫名其妙引發了極度溫馨?固然後面咱們學到使用vue-cli的時候 咱們還會用到新的書寫方法 .vue 文件的方法,這裏就先不給你們多說了。
可能由同窗會問了,組件裏面還能夠嵌套組件嗎?我能夠很負責任地告訴你,徹底沒問題!怎麼寫呢?你若是會在Vue實例的構造器裏引用組件,你就會在別的組件內部引用組件,他們實際上是一個寫法。這邊我使用咱們的第三種模板寫法來給你們書寫。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <script type="x-template" id="father"> <div> <h2 style="color:blue">{{hello}}</h2> <childer /> </div> </script> <script type="x-template" id="childer"> <h2 style="color:blue">{{hello}}</h2> </script> <body> <div id="app"> {{message}} <shuai-qm></shuai-qm> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var childer = { data(){ return{ hello:"hello i'm dawangraoming" } }, template:"#childer" } var father = { data(){ return{ hello:"hello world" } }, template:"#father", components:{ "childer":childer } } var app = new Vue({ el:"#app", data:{ message:'Hello World', isTrue:true, }, components:{ "shuaiQm":father, } }) </script> </body> </html>
這裏你們也能夠看到,咱們在 app內部只引用了 shuaiQm這一個組件, shuaiQm又包含他的子組件 childer,所以父子都被渲染出來了。這就是父子組件的寫法。
這時候又有朋友要問了,若是我想在組件裏面繼續書寫html怎麼辦呢? slot插槽就是個很好的東西了,這裏我用代碼給你們演示一下slot插槽的用法。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <script type="x-template" id="shuaiQm2"> <div style="color:blue"> <h2>{{hello}}</h2> <solt name="solt1">我是插槽solt1</solt> <solt name="solt2">我是插槽solt2</solt> <!-- 若是插槽不使用的話,內部的默認文字就會展現出來 --> </div> </script> <body> <div id="app"> {{message}} <shuai-qm> <span slot="solt1">hello world</span> </shuai-qm> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var shuaiQm = { data(){ return{ hello:"hello world" } }, template:"#shuaiQm2" } var app = new Vue({ el:"#app", data:{ message:'Hello World', isTrue:true, }, components:{ "shuaiQm":shuaiQm, } }) </script> </body> </html>
插槽只有這一個做用嗎?不,那你就過小看插槽了,接下來要介紹一下插槽的做用域插槽用法。
做用域插槽,聽不懂可跳過,後面還會詳細講解
使用時候子組件標籤Child中要有 template scope=」scopeName」 標籤,再經過scopeName.childProp就能夠調用子組件模板中的childProp綁定的數據,因此做用域插槽是一種子傳父傳參的方式,解決了普通slot在parent中沒法訪問child數據的去問題;
這麼說太複雜了,直接上個例子顯而易見。
若是這裏聽不懂能夠暫時跳過,只須要會用slot插槽的基礎用法便可,在後面講Element項目的時候,我會結合實例給你們講解這個做用域插槽。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <script type="x-template" id="shuaiQm2"> <div style="color:blue"> <h2>{{hello}}</h2> <slot name="item" v-for="item in items" :text="item.text" :myname="item.myname" > slot的默認內容 </slot> </div> </script> <body> <div id="app"> {{message}} <shuai-qm> <template slot="item" scope="props"> <li>{{props.myname}}</li> <li>{{props.text}}</li> </template> </shuai-qm> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var shuaiQm = { data(){ return{ hello:"hello world", items:[{ text:"我在子組件內,經過插槽展現在父組件", myname:"Qm", },{ text:"我在子組件內,經過插槽展現在父組件", myname:"奇淼", }] } }, template:"#shuaiQm2" } var app = new Vue({ el:"#app", data:{ message:'Hello World', isTrue:true, }, components:{ "shuaiQm":shuaiQm, } }) </script> </body> </html>
講到這裏,已經到了VUE一個須要理解的地方了,父子傳值,咱們先講解一下,如何將值傳遞給子組件,這個總體來講仍是比較簡單。引用咱們的組件的標籤上寫上屬性,而且把參數傳入,這樣咱們在組件內部使用props就能夠得到傳過來的值了,咱們仍是以上面的代碼爲例。
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <script type="x-template" id="father"> <div> <h2 style="color:blue">{{hello}}</h2> {{apptoshuaiqm}} <childer :shuai-qmtochilder="shuaiQmGiveMe" /> </div> </script> <script type="x-template" id="childer"> <div> <h2 style="color:blue">{{hello}}</h2> {{shuaiQmtochilder}} </div> </script> <body> <div id="app"> <shuai-qm apptoshuaiqm="我是app傳過來的值" ></shuai-qm> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var childer = { props:['shuaiQmtochilder'], data(){ return{ hello:"hello i'm dawangraoming", } }, template:"#childer" } var father = { props:["apptoshuaiqm"],// 這裏你們必定要注意,請徹底使用小寫傳參 data(){ return{ hello:"hello world", shuaiQmGiveMe:"我是從shuaiQm傳過來的值" } }, template:"#father", components:{ "childer":childer } } var app = new Vue({ el:"#app", data:{ message:'Hello World', isTrue:true, }, components:{ "shuaiQm":father, } }) </script> </body> </html>
這一段代碼注意,再給html上面添加屬性的時候,咱們是不能夠直接添加駝峯命名的,由於html不會區分大小寫,因此咱們建議屬性的命名方式是徹底小寫或者橫線命名的方式。若是咱們使用橫線命名來傳遞參數的話,在接收的時候,橫線後面的首字母大寫,變成小駝峯來接受,不然使用的時候它會被渲染成NaN,這是爲何呢?別忘了咱們一檔講過的,在插值表達式內,是支持簡單計算的,- 會被看成減號處理,這裏我會在視頻中給你們詳細講解。
學到這裏,若是你們已經有些迷茫,如今請先停下,喘口氣,這裏難度已經慢慢加大。我也會放慢講解的速度。
若是咱們想要獲取到子組件內部的值,該怎麼辦呢?有什麼辦法可以讓咱們回去到內部的值呢?在這裏,先給你們插播一個JS寫法,我以爲這有助於理解子傳父值。
function thief (gold) { console.log(gold) } function richMan (){ var money = 1000086 thief(money) } richMan()
咱們想要在vue中作到子傳參給父,那咱們的父組件就要像子組件伸出小偷之手。我在代碼中爲你們書寫一下
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <script type="x-template" id="shuaiQm"> <div> </div> </script> <body> <div id="app"> {{qmGold}} <shuai-qm :father="thief"></shuai-qm> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var shuaiQm = { props:["father"], data(){ return{ money:"10000", } }, template:"#shuaiQm", created() { this.father(this.money) }, } var app = new Vue({ el:"#app", data:{ qmGold:0, }, components:{ "shuaiQm":shuaiQm, }, methods:{ thief(gold){ this.qmGold = gold } } }) </script> </body> </html>
這樣 你理解子傳參給父了嗎?
Vue.directivet
Vue.directive 咱們用來編寫全局指令,它也有本身的生命週期
// 註冊 Vue.directive('my-directive', { bind: function () {}, inserted: function () {}, update: function () {}, componentUpdated: function () {}, unbind: function () {} }) /* bind:只調用一次,指令第一次綁定到元素時調用。在這裏能夠進行一次性的初始化設置。 inserted:被綁定元素插入父節點時調用 (僅保證父節點存在,但不必定已被插入文檔中)。 update:所在組件的 VNode 更新時調用,可是可能發生在其子 VNode 更新以前。指令的值可能發生了改變,也可能沒有。可是你能夠經過比較更新先後的值來忽略沒必要要的模板更新 (詳細的鉤子函數參數見下)。 componentUpdated:指令所在組件的 VNode 及其子 VNode 所有更新後調用。 unbind:只調用一次,指令與元素解綁時調用。 接下來咱們來看一下鉤子函數的參數 (即 el、binding、vnode 和 oldVnode)。 在這些鉤子函數內部,均可以接受三個參數,咱們來看看文檔中的寫法。 el:指令所綁定的元素,能夠用來直接操做 DOM 。 binding:一個對象,包含如下屬性: name:指令名,不包括 v- 前綴。 value:指令的綁定值,例如:v-my-directive="1 + 1" 中,綁定值爲 2。 oldValue:指令綁定的前一個值,僅在 update 和 componentUpdated 鉤子中可用。不管值是否改變均可用。 expression:字符串形式的指令表達式。例如 v-my-directive="1 + 1" 中,表達式爲 "1 + 1"。 arg:傳給指令的參數,可選。例如 v-my-directive:foo 中,參數爲 "foo"。 modifiers:一個包含修飾符的對象。例如:v-my-directive.foo.bar 中,修飾符對象爲 { foo: true, bar: true }。 vnode:Vue 編譯生成的虛擬節點。 oldVnode:上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。 這裏我會在視頻中結合官方樣例講解 */
上面咱們羅列了這麼多它的特性,不過真正開發中,咱們最經常使用的只有 bind 和 update 這兩個時期
咱們能夠簡寫爲
Vue.directive('color', function (el, binding) { el.style.backgroundColor = binding.value })
下面咱們來舉個例子
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <script type="x-template" id="shuaiQm"> <div> </div> </script> <body> <div id="app"> <div v-color="color"> 我來測試測試directive </div> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> Vue.directive("color",function(el,binding){ el.style.color = binding.value }) var app = new Vue({ el:"#app", data:{ color:"red" } }) </script> </body> </html>
好了咱們能夠看到加上v-color的這個div內部的文字變紅了
Vue.set
Vue.set官網給出的用法是 Vue.set( target, key, value ) 向響應式對象中添加一個屬性,並確保這個新屬性一樣是響應式的,且觸發視圖更新。它必須用於向響應式對象上添加新屬性,由於 Vue 沒法探測普通的新增屬性
這麼聽起來是有些籠統的,我給你們用代碼展現一下它在咱們平常開發中常常出現的場景。
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <ul> <li v-for="(item,ket) in list" :key="key">{{item.hello}}</li> </ul> <button @click="addList">+</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el:"#app", data:{ list:[{hello:"hello world"},{hello:"hello two"}] }, methods:{ addList(){ this.list[0] = {hello:"ttt"} console.log(this.list) } } }) </script> </body> </html>
在上述代碼中,咱們經過this.list[0]直接修改了數組中的第0項目對象,那麼視圖是沒有更新的,可是數據確實變動了,這是爲何呢?由於Vue是經過Object.defineProperty()來進行數據的監聽,它的機制致使了它沒法直接檢測出數組中這種狀況的變化。這時候咱們就須要使用Vue.set了
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <ul> <li v-for="(item,ket) in list" :key="key">{{item.hello}}</li> </ul> <button @click="addList">+</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el:"#app", data:{ list:[{hello:"hello world"},{hello:"hello two"}] }, methods:{ addList(){ this.list[0] = {hello:"ttt"} console.log(this.list) } } }) </script> </body> </html>
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"> <ul> <li v-for="(item,ket) in list" :key="key">{{item.hello}}</li> </ul> <button @click="addList">+</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el:"#app", data:{ list:[{hello:"hello world"},{hello:"hello two"}] }, methods:{ addList(){ // this.list[0] = {hello:"ttt"} Vue.set(this.list,0, {hello:"我強制改變了!"}) // this.$set(this.list,0,{hello:"我強制改變了!"}) 在methods 中能夠寫成 this.$set console.log(this.list) } } }) </script> </body> </html>
看 是否是強制將它改變了呢? 有了Vue.set 數據就都再也不得瑟了