父與子、子與父通信
- 1. 組件通信
- 1.1 組件嵌套
- 1.2 組件嵌套步驟
- 1.3 父與子、子與父通信
- 1.4 實作案例圖示
- 2. 父組件與子組件通信
- 2.1 父與子通信
- 2.2代碼實作父與子及詳細說明
- 3. 子組件與父組件通信
- 3.1 子與父通信
- 3.2 代碼實作子與父及詳細說明
1. 組件通信
1.1 組件嵌套
- vue中提供了很棒的組件化思想,組件提高了代碼的復用性,
- 組件中可以引入其他的組件
1.2 組件嵌套步驟
- 創建父、子組件
- 在父組件引入子組件
1.3 父與子、子與父通信
- vue.js中,父子組件的關系可以總結為props down ,events up
- 父組件通過props向下傳遞資料給子組件,子組件通過events給父組件發送訊息(后面結合代碼會細說)
- 父子通信資料傳遞的示意圖:

1.4 實作案例圖示

以下內容都是通過該案例展開的,我們希望實作:
- 在文本框輸入內容后點擊 + 時,下面事項串列能夠更新;
- 點擊每個事項后的 ×,該事項能夠洗掉,
2. 父組件與子組件通信
2.1 父與子通信
- 子組件要使用父組件的資料,我們需要通過子組件的props選項,如何理解props選項呢?
打個比喻:小孩拿著一個大布袋子問大人要糖吃,大人把糖放進了大布袋子中
props選項就是這個“大布袋子”,父組件把資料放在子組件的props選項中,子組件內部也就有了該資料,這就是上面所說的——props down - 當然,子組件要使用父組件的資料,不僅僅需要通過子組件的props選項,
在父組件的模板中,要動態的系結父組件的資料到子組件的props,與系結到任何普通的html特性相類似,就是用v-bind,簡寫就是冒號( : ),這樣每當父組件的資料變化時,該變化也會傳導給子組件,
2.2代碼實作父與子及詳細說明
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>父子通信</title>
<script src="../js/vue.js"></script>
<script>
var todoAdd={
props:["add_tasks"],
data(){
return{task:""}
},
template:`
<div>
<input type="text" v-model="task"><button @click="add">+</button>
</div>`,
methods:{
add(){
this.add_tasks.push(this.task);
this.task="";
}
}
}
var todoItem={
props:["t","i","item_tasks"],
template:`
<li>
{{i+1}}-{{t}}<a href="javascript:;" @click="del">×</a>
</li>`,
methods:{
del(){this.item_tasks.splice(this.i,1);}
}
};
var todoList={
props:["list_tasks"],
template:`
<ul>
<todo-item v-for="(t,i) of list_tasks" :t="t" :i="i" :item_tasks="list_tasks"></todo-item>
</ul>`,
components:{todoItem}
};
Vue.component("to-do",{
data(){
return{tasks:["吃飯","睡覺","打豆豆"]}
},
template:`
<div>
<h1>待辦事項串列</h1>
<todo-add :add_tasks="tasks"></todo-add>
<todo-list :list_tasks="tasks"><todo-list>
</div>`,
components:{todoAdd,todoList}
})
</script>
</head>
<body>
<div id="app">
<to-do></to-do>
</div>
<script>
new Vue({
el:"#app"
})
</script>
</body>
</html>
為了便于理解,用圖的方式解釋一下上面代碼:

按照上圖紅色標記序號詳細講一下:
為了方便理解,我們稱todo為爺爺組件,todoList為父親組件,todoItem為兒子組件
- 爺爺組件todo中的模板代碼(template)中——:list_tasks=“tasks”,引號中的tasks就是爺爺組件的資料tasks,等號左邊的list_tasks就是給到父親組件todoList中資料的名稱,用上邊的比喻來解釋就是,大人把這些糖叫做奶糖,小孩把這些糖叫做大白兔奶糖,雖然叫法不一樣,但指的是一個東西!(也可以叫一樣的名字,即 :tasks=“tasks”,但需要知道等號兩邊的tasks意義不同)
- 父親組件todoList中——props:[“list_tasks”],這時父親組件內部有了list_tasks這個變數,我們需要注意的是:在爺爺組件todo中tasks是一個陣列,陣列是參考型別,所以tasks變數中存的是一個地址,我們假設這個地址是0x1234,那么我們在父親組件todoList中拿到的list_tasks也存著一個地址,而且這個地址也是0x1234,這也就表示,我們從爺爺組件中拿到的資料不是副本,tasks和list_tasks指向同一個地址
- 父親組件todoList的模板代碼中使用了list_tasks變數
- 兒子組件todoItem也需要使用爺爺的tasks,但是他不能問爺爺要啊,他就問他爹要啦,他爹也有啊,但名字叫做list_tasks,兒子把要過來的資料又重新起名叫做item_tasks,就可以通過v-for指令在頁面生成我們想要得到的事務串列
- 兒子組件todoItem通過props拿到資料item_tasks,item_tasks同樣指向地址0x1234
- 觸發事件后,兒子組件todoItem呼叫自己的方法del,對item_tasks中的資料進行了洗掉,因為tasks、list_tasks和item_tasks都指向一個地址,觸發事件影響的也就是爺爺組件todo中的資料,
子組件todoAdd的道理也是如此,就不重復說啦~
這里再說一下綠色標記處的代碼:
- 兒子組件todoItem要使用父親組件todoList的 t 和 i 變數,父親組件中用代碼——:t=“t” :i=“i” 動態的將資料系結到兒子組件的props中,等號兩邊的 t 和 i 意義不同,同上面所說,
3. 子組件與父組件通信
學習了以上內容,子組件中內部的方法可以通過以上方式使用到父組件中的資料,但是上面栗子中add()方法、del()方法散落在各個子組件內部,如果有更多的子組件和方法,我們后期是難以維護的,所以,如果我們將所有的方法都放在父組件中,子組件需要使用的話則通過一定方式觸發父組件內的方法,這就是子組件與父組件通信,
3.1 子與父通信
- 父組件是使用props傳遞資料傳遞給子組件,但如果子組件要把資料傳遞回去,應該怎么做?那就是自定義事件!
- 使用$on(事件名稱)監聽事件
- 使用$emit(事件名稱)觸發時間
- 注意,不能用$on偵聽子組件拋出的事件,而必須在模板里直接使用v-on系結(v-on簡寫@)
- 父組件內:給子組件系結一個事件
<child @事件名稱="方法名稱(引數)"></child>
- 子組件內:在子組件內出發父組件指定的事件
this.$emit("事件名稱")
3.2 代碼實作子與父及詳細說明
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>子父通信</title>
<script src="../js/vue.js"></script>
</head>
<script>
var todoAdd={
template:`
<div>
<input type="text" v-model="task"><button @click="add">+</button>
</div>`,
data(){
return{task:""}
},
methods:{
add(){
this.$emit("add",this.task);
this.task="";
}
}
}
var todoItem={
props:["t","i"],
template:`
<li>
{{i+1}}-{{t}}<a href="javascript:;" @click="del">×</a>
</li>`,
methods:{
del(){this.$emit("del");}
}
};
var todoList={
props:["tasks"],
template:`
<ul>
<todo-item @del="del(i)" v-for="(t,i) of tasks" :t="t" :i="i"></todo-item>
</ul>`,
methods:{
del(i){this.$emit("del",i);}
},
components:{
todoItem
}
};
Vue.component("to-do",{
template:`
<div>
<h1>待辦事項串列</h1>
<todo-add @add="add"></todo-add>
<todo-list @del="del" :tasks="tasks"><todo-list>
</div>`,
data(){
return{
tasks:["吃飯","睡覺","打豆豆"]
}
},
methods:{
add(task){
this.tasks.push(task);
},
del(i){
this.tasks.splice(i,1);
}
},
components:{
todoAdd,
todoList
}
})
</script>
<body>
<div id="app">
<to-do></to-do>
</div>
<script>
new Vue({
el:"#app"
})
</script>
</body>
</html>
同樣先用圖解釋一下上述代碼:

先看紅色標記:
- 當點擊button按鈕時,子組件todoAdd觸發自己的方法add()
- 子組件todoAdd可以使用$emit觸發父組件todo的自定義事件,自定義事件名稱為add,this.task是引數
- 父組件todo的模板代碼(template)中定義了自定義事件(@add=“add”),等號左邊是事件名,右邊引號中是所觸發的父組件中的方法名
- 父組件todo中的add方法被執行,頁面上添加了新的事物
再看藍色標記:
為了方便理解,我們稱todo為爺爺組件,todoList為父親組件,todoItem為兒子組件
- 當點擊×時,兒子組件todoItem觸發了自己的方法del()
- 兒子組件todoItem使用$emit觸發父親組件todoList的自定義事件,自定義事件名稱為del
- 父親組件todoList的模板代碼(template)中定義了自定義事件(@del=“del(i)”),等號左邊是事件名,右邊引號中是所觸發的父親組件todoList中的方法名,
- 父親組件todoList中的方法del(i)中有一個引數i,i為當前要洗掉的tasks陣列中元素的下標(tasks陣列在爺爺組件的data屬性中),該方法同樣使用$emit觸發了爺爺組件todo的自定義事件,自定義事件名稱為del,i為引數(注意:不是this.i)
- 爺爺組件todo的模板代碼(template)中定義了自定義事件(@del=“del”),等號左邊是事件名,右邊引號中是所觸發的爺爺組件中的方法名
- 爺爺組件todo中的del方法被執行,選中的事務將被洗掉
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/263463.html
標籤:其他
