通常父子組件之間是需要相互傳數據的
一、父組件向子組件傳數據
1,父組件App.vue傳遞menus數組給子組件的menu
<!-- 父級往子級傳值步驟:
1.在子組件的屬性(props)驗證-->
2.給父組件的子組件標簽設置並綁定自定義屬性
(首先在子組件中驗證屬性,屬性名隨意,想要一個數組在li標簽中遍歷;接下來在父組件的子組件標簽中自定義屬性(屬性名與子組件驗證屬性名必須相同))
<template> <div id="app"> <Vheader></Vheader>
<!-- // 自定義標簽,可以自定義一個menu屬性,然后自定義綁定它(id、class、title是系統提供的屬性,menu是自定義屬性);'menus'是數組,即綁定數組 ;
即當前Vcontent組件有menu屬性了--> <!-- Vcontent組件怎么拿到menu屬性?(即需要父組件往子組件傳值,傳值約定:必須驗證props!!) --> <Vcontent:menu ='menus'></Vcontent> 通過使用v-bind綁定子組件的menu屬性,將menus數組傳遞給子組件
<!-- 將audio、ul、h3標簽移至Vcontent.vue中 --> <!-- <audio :src="audioSrc" autoplay="autoplay" controls=""> </audio> <ul> <li v-for='(item,index) in menus'> {{item}} </li> </ul> --> <!-- <h3>猛哥噸噸</h3> --> </div> </template> <script> import audio1 from'./assets/1.mp3' import Vheader from './components/Vheader.vue'
//導入子組件 import Vcontent from './components/Vcontent.vue' export default{ name:'App', data(){ return{ menus:['宮保雞丁','紅燒肉','酸辣湯'], //移至Vcontent.vue中 audioSrc:audio1 } }, components:{ Vheader,
//掛載子組件 Vcontent } } </script> <style scoped> </style>
2,子組件Vcontent.vue使用menu屬性接受父組件傳遞的menus
<template> <div class="content"> <!-- <audio :src="audioSrc" autoplay="autoplay" controls=""> </audio> -->
<ul> <!-- ???為什么將menus改成menu --> <li v-for='(item,index) in menus'> {{item}} </li> </ul> <h3>猛哥噸噸</h3> </div> </template> <script> // 拋出整個組件 export default { name:'Vcontent', data(){ return{
// 為什么menus數據不放在Vcontent.vue子組件中,放在App.vue父組件中? // 想要實現一開始加載項目時,App.vue就可以把數據拿到,即App.vue拿到后端數據,然后通過vue提供父子傳值的功能,數將據從App.vue里邊傳到子組件中 // 好處:子組件很多,一開始就把數據請求出來,分發各個子組件 // menus:['宮保雞丁','紅燒肉','酸辣湯'], // audioSrc:audio1
//this指的是當前組件(Vcontent)的實例化vue對象,即每個組件的this都是不同的,即當前this拿不到App.vue里邊的東西
menus:this.menu } }, // 父子傳值,屬性(props)必須驗證 // 為什么驗證? // 傳的值可以是字符串、數組、對象等,組件需要驗證一下傳的什么值 // 屬性是對象,對象里面有k:value, props:{ // 此次傳來的menu1是數組 menu:Array } } </script> <style scoped> </style>
二、子級往父級傳值
1.在子組件中觸發自定義事件 (傳值:字符串、數組、對象、數值、number)
this.$emit('自定義的事件名',傳值)
注:綁定到當前vue實例化對象里邊的屬性和事件前邊都要加一個$,$emit是vue內部提供的方法,
2.在父組件的子組件標簽中設置自定義事件
<Vheader @addMenu = 'addHandler'></Vheader>
addMenu:自定義事件名
addMenu等號后邊對應的addHandler:在當前組件中methods里邊聲明的事件
...
methods:{ addHandler(value){ alert(value);
///value就是傳過來的參數 this.menus.push(value); } },
子組件是通過事件向父組件傳遞數據,分如下兩種情況:
1.直接由當前Vcontent組件將'酸菜魚'傳到父組件App.vue的menus中,實現向數組中添加酸菜魚-->
<template> <div class="content"> <!-- <audio :src="audioSrc" autoplay="autoplay" controls=""> </audio> --> <ul> <!-- Vue強烈建議我們在組件里邊用v-for遍歷時,加一個綁定的key, <! ???為什么將menus改成menu --> <li v-for='(item,index) in menus' :key = 'index'> {{item}} </li> </ul> <h3>猛哥噸噸</h3> <!-- 如何將酸菜魚添加到數組中 --> <!--1. 直接由當前Vcontent組件將'酸菜魚'傳到父組件App.vue的menus中,實現向數組中添加酸菜魚--> <!--點擊button之后,調用addOneMenu函數,this.menu可以直接拿到父組件App.vue的數組,push('酸菜魚')之后,push的是menu菜單,
即自定義屬性,menu變化意味着Vcontent標簽中的menu屬性變化,意味着menus變化,即意味着data中menus數組變化,即li標簽中的menus變化,
接着v-for重新遍歷,將酸菜魚添加到當前Vcontent組件的列表中;為了證明酸菜魚是否也可以添加到父組件App.vue的menus中,
我們在父組件App.vue中也添加相同的li標簽,點擊按鈕之后,父組件App.vue的列表中也出現了酸菜魚,有一種響應式的綁定,
即可以直接在子組件Vcontent中向父組件App.vue的數組menus中添加值,即子傳父 --> <button @click = 'addOneMenu'>添加</button> </div> </template> <script> // 拋出整個組件 export default { name:'Vcontent', data(){ return{ menus:this.menu } }, methods:{ addOneMenu(){ this.menu.push('酸菜魚') } }, props:{ menu:Array } } </script> <style scoped> </style>
2.如何實現在Vheader組件中點擊button按鈕提交將菜單添加到Vcontent組件中(實現在其他組件中向父組件提交然后添加到Vcontent組件中)
點擊提交按鈕后,觸發addOneMenu函數,由this.$emit('addMenu','傳值')觸發一個addMenu自定義事件,接着傳值;接下來子組件中需要有一個addMenu這樣的自定義事件名;接下來需要在父組件中找關系,然后在父組件的子組件標簽中自定義事件名addMenu(必須與this.$emit的相同),addMenu等號后邊對應的addHandler方法是在當前組件中觸發的事件
<template> <div class="header"> <h3>{{msg}}</h3> <img :src="logoSrc" alt=""> <!--2.如何實現在Vheader組件中點擊button按鈕提交將菜單添加到Vcontent組件中(實現在其他組件中向父組件提交)--> <!-- 點擊button按鈕后,觸發addOneMenu函數,但是this.menu拿不到菜單,沒有返回值;又Vheader和Vcontent是同級兄弟關系,兩個都連接着App.vue,
因此我們可以把數據由Vheader傳到App.vue(子傳父),在由App.vue傳到Vcontent中(父傳子),我們在Vheader中提交,把數據提交到App.vue,
然后通過父傳子傳給Vcontent 2.1.點擊button按鈕之后,調用addOneMenu函數,接着由 this.$emit('自定義事件的名字','要傳的值')觸發自定義事件; 2.2.觸發App.vue中Vheader標簽的自定義事件addMenu,並傳值(酸菜魚)給addHandler函數,this.menus.push(酸菜魚)添加至menus數組 2.3.data中menus數組多一個酸菜魚(即menus變化),然后觸發<Vcontent :menu ='menus'></Vcontent>的menu屬性傳值(props:{menu:Array}),
然后data函數menus中變化,最后至li標簽menus變化,接着v-for重新遍歷,將酸菜魚添加到Vcontent組件的列表中--> <button @click = 'addOneMenu'>添加</button> </div> </template> <script> import logoSrc from '../assets/logo.png' export default { name:'Vheader', data(){ return{ msg:'hello 組件結構', logoSrc:logoSrc } }, methods:{ addOneMenu(){ // this.$emit('自定義事件的名字','要傳的值')可以觸發自定義事件 this.$emit('addMenu','酸菜魚'); } } } </script> <style scoped> h3 { color: yellow; } </style>
父組件App.vue
<template> <div id="app"> <!-- 子傳父: --> <!-- 1.首先要先自定義事件,通過自定義事件向父級傳值;Vheader可以自定義屬性,也可以自定義事件 2.給自定義事件命名addMenu(即addMenu為自定義事件名字),后邊''中也要對應一個事件,為addHandler,接着addHandler要在methods中聲明,
this.menus.push(value)就可以向menus數組添加數據,value是要添加的數據,也是子向父傳的值--> <Vheader @addMenu = 'addHandler'></Vheader> <Vcontent :menu ='menus'></Vcontent> </div> </template> <script> import audio1 from'./assets/1.mp3' import Vheader from './components/Vheader.vue' import Vcontent from './components/Vcontent.vue' export default{ name:'App', data(){ return{ menus:['宮保雞丁','紅燒肉','酸辣湯'], } }, methods:{ addHandler(value){ // alert(value) this.menus.push(value); } }, components:{ Vheader, Vcontent } } </script> <style scoped> </style>