二檔視頻固然要比一檔視頻難一點,若是前面的內容尚未消化完畢的話,仍是建議你們繼續消化前面的內容,而後再看接下來的部分。這一部分是VUE的核心,講到組件化開發的基礎部分,多學,多練。javascript
Vue官網給出的生命週期圖html
<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>
複製代碼
``` 這些生命週期函數大致就演示到這裏,剩下的兩個沒能給你們展現的請你們牢記,咱們開始學組件的時候,就能夠體會到這兩個鉤子函數的用法了。
Vue.component 註冊全局組件 Vue.component("組件名",{ 組件的各類屬性(模板啊,data啊,方法啊,生命週期啊之類的。) }), (視頻裏有一句口誤,應該是小駝峯。手動捂臉)vue
這個全局API看過之後,咱們來實現一個組件的hello worldjava
<!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就完成了,可是你們是否是以爲全局組件很是不踏實?隨時可能一個變更摧毀咱們的項目? 那不要緊,接下來是局部組建的註冊方法。node
Vue的components屬性vue-cli
咱們在註冊局部組建的時候,須要把局部組建掛載到Vue構造器的components內,注意:全局api不帶s,而這個屬性帶s。不說廢話,咱們先來構造一個。express
<!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的局部組件,可是,一堆組建都這個樣子羅列出來的話,會將咱們的項目弄得體無完膚? 因此咱們抽離一下代碼。變成這樣npm
<!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全都是寫的字符串,都這麼玩下去,要亂死啊,沒問題,咱們繼續抽離。api
這裏介紹的就是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"></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"></script>
<script type="x-template" id="childer"></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"></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"></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"></script>
<script type="x-template" id="childer"></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 數據就都再也不得瑟了