1 組件
擁有專屬的HTML,CSS和數據的頁面獨立區域。
優點:便於重用、鬆散耦合、分工協作
頁面由一個個獨立的區域組成,封裝爲組件。即每個頁面由多個組件組成
1.創建Vue組件:
1.1先在<template></template>中定義組件的HTML片段,要求<template>內只能有唯一的父元素包裹
1.2創建Vue組件
Vue.component(“組件名”,{
template:”選擇器”, //找到頁面上一個<template>元素,並監控其中的內容——組件的HTML片段
//data:function(){return {}}的簡寫
data(){ //每使用一次組件,就調用一次data函數,爲當前組件生成一個新data對象
return {
模型變量
}
},
…同new Vue()
})
2.使用組件: 一個組件,其實就是一個可重用的標籤!組件名就是標籤名
運行時: 用<template>中的HTML片段代替<組件名>標籤的位置
2 組件生命週期
一個組件的加載過程
包括: 4個階段:
1.Create創建:創建組件實例對象,並創建data對象
2.Mount掛載:將組件模板中的元素,綁定後,掛載到DOM樹
3.Update:模型變量被更新
4.Destory:要銷燬一個組件
生命週期鉤子函數: 每個生命週期階段拋出的事件處理函數
只要希望在某個生命週期階段執行一項任務時,都要寫在該階段對應的構造函數中。
包括:
beforeCreate: 創建組件實例之前觸發
created: 創建組件實例之後,但掛載組件到DOM樹之前觸發
new Vue($data:模型數據 $el:undefined)
已經可以發送ajax請求
暫時不能執行DOM操作!
beforeMount: 掛載組件到DOM樹之前觸發
mounted: 掛載組件到DOM樹之後觸發
new Vue($data:模型數據 $el:虛擬DOM樹)
也可以發送ajax請求
可執行DOM操作!
beforeUpdate: 模型數據被更新前觸發
updated: 模型數據更新後觸發
beforeDestroy: 銷燬組件對象之前觸發
destroyed: 銷燬組件後觸發
3 組件化開發
組件: 擁有專屬的HTML,CSS,JS和數據的頁面獨立區域
組件化開發: 拿到頁面後,先劃分區域,每個區域都是擁有專有HTML,CSS,數據的獨立組件
組件分類:
-
根組件: new Vue({el:"#app", data:{}})
通常一個頁面,只有一個根組件 -
全局組件,可在任何位置隨意使用的組件
Vue.component(“組件名”,{
template:"#tplxxx",
data:function(){ return {} }
}) -
局部組件,也稱子組件,只能用於某個特定父組件內的組件
1)將作爲子組件的全局組件,降級爲普通的對象, 組件對象名應該是將來的組件標籤名改爲駝峯命名
2)在父組件中添加components屬性:{
子組件對象, …
}
Vue會將駝峯命名的子組件,轉化爲-命名的小寫標籤名.
4 組件間傳參
-
父->子:父組件的模型變量,子組件無權直接使用
解決: “屬性下行”
1)子組件var 子組件={ template:"xxx", props:["變量", ... ] //聲明一個內外兩用的變量 //對外: 父元素可爲其綁定數據 //對內: 相當於data:{ 變量 } } <template id="tpl子組件"> {{變量}} <ANY :屬性="變量" </template>
2)父組件
<template id="tpl父組件"> <子組件 :變量="模型變量"></子組件> 父組件將自己的模型變量的值傳遞給子組件的變量屬性,子組件就獲得了父組件的數據
-
子->父: 事件上行
問題: 子組件無權直接刪除父組件中的模型變量的內容
解決: 事件上行
1)父組件:在子組件身上提前定義自定義事件和處理函數:<template id="tpl父組件"> <子組件 @自定義事件="父的處理函數"//不要加() //當有人觸發自定義事件時,自動執行父組件中的處理函數,修改父組件自己的數據 父組件{ ... methods:{ 處理函數(形參) {//形參會收到子傳來的參數 //操作父組件中的數據 } } }
2)子組件
子組件對象={ … methods:{ 事件處理函數(){ This.$emit(“自定義事件”,要給父的值) } } }
事件上行下行示例
<template id="tplTodoAdd">
<div>
<input v-model="new_task"><button @click="add()">添加</button>
</div>
</template>
<script>
var todoAdd={
template:"#tplTodoAdd",
data:function(){
return { new_task:"" }
},
methods:{
add(){
this.$emit("add",this.new_task);
this.new_task="";
}
}
}
</script>
<template id="tplTodoItem">
<li>{{i+1}} - {{task}}</li>
</template>
<script>
var todoItem={
template:"#tplTodoItem",
props:["task","i"]//對外:父組件可綁定數據
//對內: data:{ task:xx, i:x }
}
</script>
<template id="tplTodoList">
<ul>
<todo-item v-for="(task,i) of tasks" :task="task" :i="i"></todo-item>
</ul>
</template>
<script>
var todoList={
template:"#tplTodoList",
props:["tasks"],//對外: 父組件可綁定數據
//對內: 相當於data:{tasks}
components:{ todoItem }
}
</script>
<template id="tplTodo">
<div>
<h1>待辦事項列表</h1>
<todo-add @add="do_add"></todo-add>
<todo-list :tasks="tasks"></todo-list>
</div>
</template>
<script>
Vue.component("todo",{
template:"#tplTodo",
data:function(){
return {//data
tasks:["吃飯","睡覺","打亮亮"]
}
},
components:{
todoAdd,//Vue自動轉爲todo-add
todoList//Vue自動轉爲todo-list
},
methods:{
do_add(new_task){
this.tasks.push(new_task);
}
}
})
</script>
<div id="app">
<todo></todo>
</div>
<script>
new Vue({
el:"#app",
data:{}
})
</script>