一、父組件傳遞參數給子組件
-
1、父組件傳遞參數
<template> <div> <Son1 :name="name" :age="20" :bookList="['三國演義', '西遊記']" :details="{'name': '張三', address: '廣東深圳'}" :isActive="false" /> </div> </template>
-
2、在子組件中定義接收
<template> <div> <hr /> <h3>我是子組件</h3> <p>{{name}}</p> <p>{{age}}</p> <p>{{bookList}}</p> <p>{{details}}</p> <p>{{isActive}}</p> </div> </template> <script> export default { name: 'son1', props: { name: { type: String, default: '', }, age: { type: Number, default: 0, }, bookList: { // 如果是對象或者數組必須使用下函數生成的方式 type: Array, default: () => [], }, details: { type: Object, default: () => ({}), }, isActive: { type: Boolean, default: false, }, }, mounted() { console.log(this); }, }; </script> <style scoped></style>
二、子組件修改父組件傳遞的數據
由於
vue
屬於單向數據流,子組件中不直接修改父組件的數據,而是在組件觸發事件或者派發通知到父組件,通知父組件修改數據,父組件數據被修改了,傳遞到子組件中,子組件的數據也被修改了。
方式一、直接在子組件中定義方法,然後通過emit
發出一個事件到父組件中修改(類似回調函數的方式)
-
1、在子組件中
<template> <div> <hr /> <h3>我是子組件</h3> <p>{{name}}</p> <button @click="change">修改</button> </div> </template> <script> export default { name: 'son1', props: { name: { type: String, default: '', }, }, mounted() { console.log(this); }, methods: { change() { // 對父組件派發一個change事件 this.$emit('change', '哈哈,我是子組件過來的'); }, }, }; </script> <style scoped></style>
-
2、在父組件中使用,然後修改數據
<template> <div> <!--在父組件中使用change事件--> <Son1 :name="name" @change="change" /> </div> </template> <script> import Son1 from './Son1'; export default { name: 'parent1', data() { return { name: '哈哈', }; }, methods: { change(value) { this.name = value; }, }, mounted() { console.log(this); }, components: { Son1, }, }; </script> <style scoped></style>
方式二、子組件中派發的事件名稱叫input:value
(和方式一一樣的)
-
1、子組件中
// 子組件中派發一個input:value的事件給父組件 this.$emit('input:value', '?哈哈');
-
2、父組件中
html <template> <div> <!--父組件接收子組件的input:value事件--> <Son1 :name="name" @input:value="change"></Son1> <!-- 或者直接將函數寫在行間 <Son1 :name="name" @input:value="(val)=>this.name=val" ></Son1> --> </div> </template> <script> import Son1 from './Son1'; export default { name: 'parent1', data() { return { name: '哈哈', }; }, methods: { change(value) { this.name = value; }, }, mounted() { console.log(this); }, components: { Son1, }, }; </script> <style scoped></style>
方式三、使用修飾符sync
數據同步,注意點:子組件必須派發的是update:屬性
事件
-
1、子組件中派發的事件名稱
<template> <div> <h1> 我是子組件內容 </h1> <button @click="change1">使用sync的方式</button> </div> </template> <script> export default { methods: { change1() { this.$emit('update:name', '?哈哈'); }, }, }; </script>
-
2、父組件中
<template> <div> <!-- 使用的方式一 --> <Son1 :name="name" @update:name="(val)=>this.name=val"></Son1> <!-- 使用的方式二 --> <Son1 :name.sync="name"></Son1> </div> </template>
方式四、子組件中接收的是value
屬的時候,派發的事件是input
-
1、子組件
<template> <div> <hr /> <h3>我是子組件</h3> <p>{{value}}</p> <button @click="change">修改</button> </div> </template> <script> export default { name: 'son1', props: { value: { // 必須是value屬性 type: String, default: '', }, }, mounted() { console.log(this); }, methods: { change() { // 發送的事件也是定死的input this.$emit('input', '哈哈,我是子組件過來的'); }, }, }; </script> <style scoped></style>
-
2、父組件中
<template> <div> <Son1 :value="name" @input="(val)=>this.name=val"></Son1> <!-- 可以進一步簡寫成這樣 --> <Son1 v-model="name"></Son1> </div> </template> <script> import Son1 from './Son1'; export default { name: 'parent1', data() { return { name: '哈哈', }; }, }; </script>
三、孫組件修改父父組件的數據
主要的思路是孫組件派發事件通知父組件修改數據,父組件派發事件通知父組件修改
方式一、孫組件中使用$parent.$emit
派發事件
-
1、孫組件
... changeVal () { this.$parent.$emit('input', '孫組件修改的'); }, changeAge () { this.$parent.$emit('changeAge', 40); } ...
-
2、父組件
<template> <div> <hr /> <h3>我是子組件</h3> <p>{{value}}==={{age}}</p> <hr /> <h3>孫組件</h3> <Grandson1 :value="value" :age="age" /> </div> </template> <script> import Grandson1 from './Grandson1'; export default { name: 'son1', props: { value: { type: String, default: '', }, age: { type: Number, default: 0, }, }, methods: {}, components: { Grandson1, }, }; </script> <style scoped></style>
-
3、父父組件
<template> <div> <Son1 v-model="name" :age="age" @changeAge="val => this.age = val"></Son1> </div> </template>
方式二、使用自己擴展到Vue
原型上的$dispatch
方法
-
1、擴展方法
import App from './App'; import Vue from 'vue'; Vue.prototype.$dispatch = function(eventName, value) { let parent = this.$parent; // 循環遞歸派發事件 while (parent) { parent.$emit(eventName, value); parent = parent.$parent; } }; const vm = new Vue({ el: '#app', render: (h) => h(App), });
-
2、孫組件中使用
... methods: { changeVal () { this.$dispatch('input', '孫孫組件修改的') }, changeAge () { this.$dispatch('changeAge', 40) } }, ...
-
3、父父組件中
<Son1 v-model="name" :age="age" @changeAge="val => this.age = val"></Son1>
四、自定義廣播
類似
angularjs
中的廣播,其實也就是一個發佈者與訂閱者的關係,發佈一個消息,訂閱的組件就執行
-
1、在
main.js
中擴展方法Vue.prototype.$broadcast = function(enevtName, value) { // 遞歸查找全部的子組件 const broadcast = (children) => { children.forEach((child) => { child.$emit(enevtName, value); if (child.$children) { broadcast(child.$children); } }); }; broadcast(this.$children); };
-
2、組件中訂閱廣播
<template> <div> <Grandson1 :value="value" :age="age" @say="say" /> </div> </template> <script> ... methods: { say (val) { console.log(`我是孫組件中的廣播,接收的消息是:${val}`) } }, ... </script>
-
3、發出一個廣播通知
... mounted () { this.$broadcast('say', '放假了'); }, ...