1、方法1:父子关系进行通信(父子之间)
1.1、父传子
-
思路: 父要获取到该子组件,然后给该子组件修改数据。
-
核心:父要如何获取到子
-
实现: 父组件内部 通过 this.$refs 来获取到子组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <style> #app{ width: 400px; height: 400px; background-color: #eee; } .box{ width: 200px; height: 200px; background-color: orange; } </style> </head> <body> <div id="app"> <h3>我是根组件</h3> {{msg}} <mydiv ref='mydiv'></mydiv> </div> <template id="mydiv"> <div class="box"> <h3>我是mydiv组件</h3> {{str}} </div> </template> </body> <script> Vue.component('mydiv',{ template:'#mydiv', data(){ return{ str:'' } }, methods:{ show(){ console.log("我是mydiv组件的方法"); } } }) new Vue({ el:"#app", data:{ msg:"我是根的msg" }, created(){ console.log(this); }, mounted(){ console.log(this.$refs.mydiv); // 父已经访问到了子 this.$refs.子组件名 console.log(this.$refs.mydiv.nums); this.$refs.mydiv.str = this.msg // 父可以通过 this.$refs.变量名 获取子的所有属性和方法 this.$refs.mydiv.show(); } }) // 父给子传递数据 // 父的HTML模板里面 给组件添加上 ref属性 <组件名 ref='变量'></组件名> // 子组件有一个 str 的变量 值为空, 在他的模板里面 渲染str {{str}} // 父的mounted生命周期函数里面, this.$refs.变量名 访问到子组件 // 父的mounted生命周期函数里面,给 子组件的对应变量赋值 this.$refs.变量名.str = 父里面的数据 //【 核心:】 父组件获取到了子组件对象 this.$refs.变量名 // 从而可以直接 修改子组件的数据 和 调用子组件的方法 </script> </html>
1.2、子传父
-
思路: 子组件要获取父组件,然后修改父组件的数据
-
核心:子要如何获取到父
-
实现: 子组件内部 通过 this.$parent 来获取到父组件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <style> #app{ width: 400px; height: 400px; background-color: #eee; } .box{ width: 200px; height: 200px; background-color: orange; } </style> </head> <body> <div id="app"> <h3>我是根组件</h3> {{msg}} <mydiv ref='mydiv'></mydiv> </div> <template id="mydiv"> <div class="box"> <h3>我是mydiv组件</h3> {{str}} </div> </template> </body> <script> Vue.component('mydiv',{ template:'#mydiv', data(){ return{ str:'我是天下第一帅!' } }, created(){ console.log(this); console.log(this.$parent); console.log(this.$parent.msg); this.$parent.msg = this.str // 赋给父 console.log(this.$parent.change); this.$parent.change(); // 调用父的方法 }, methods:{ } }) new Vue({ el:"#app", data:{ msg:"我是根的msg" }, created(){ }, methods:{ change(){ console.log("我是父的change"); } } }) // 子给父传递数据 // 子通过 this.$parent 获取当前组件的父组件 给父组件的变量进行修改, 调用父组件的方法 // 【核心:】 this.$parent </script> </html>
2、方法2:自定义属性、自定义事件(父子之间)
2.1、父传子:自定义属性
-
如何定义自定义属性: 利用的props
-
实现:
- 在子组件里面的props配置选项里面,添加上一些自定义属性
- 子组件的模板里面直接渲染这些属性
- 父组件模板里面 在该子组件的标签上面给自定义的属性添加值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <style> #app{ width: 400px; height: 400px; background-color: #eee; } .box{ width: 200px; height: 200px; background-color: orange; } </style> </head> <body> <!-- input是输入框 --> <input type="text" value="1000"> <div id="app"> <h3>我是根组件</h3> <mydiv :ttt='parmsg' age='333333' ></mydiv> </div> <template id="mydiv"> <div class="box"> <h3>我是mydiv组件</h3> {{ttt}} <br> {{age}} <br> </div> </template> </body> <script> Vue.component('mydiv',{ template:'#mydiv', props:['ttt','age'], // 规定组件有哪些属性, 规定了组件有ttt属性,age属性 }) new Vue({ el:"#app", data:{ parmsg:"朕的天下" } }) // 组件有一个porps属性。 props属性定了组件 有哪些可以接收外部数据的属性 // 在父的模板里面 <子组件名 :子组件的属性名='父组件的变量' ></子组件名> // 子的 配置项里面 porps:['子组件的属性名'] // 子的 模板里面 {{子组件的属性名}} // 父传子 通过 props 传入 </script> </html>
-
props验证
-
验证该属性 是否必须传入
-
验证该属性 数据类型是否正确
-
设置该属性的默认值
-
校验该属性的值是否符合条件
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <style> #app{ width: 400px; height: 400px; background-color: #eee; } .box{ width: 200px; height: 200px; background-color: orange; } </style> </head> <body> <!-- input是输入框 --> <input type="text" value="1000"> <div id="app"> <h3>我是根组件</h3> <mydiv :ttt="22222" :age='100' :nums='1900' :childchange='change'></mydiv> </div> <template id="mydiv"> <div class="box"> <h3>我是mydiv组件</h3> {{ttt}} <br> {{age}} <br> {{nums}} <br> <button @click='childchange'>22222</button> </div> </template> </body> <script> Vue.component('mydiv',{ template:'#mydiv', // props:['ttt','age'], // 规定组件有哪些属性, 规定了组件有ttt属性,age属性 props:{ ttt:{ type:[String,Number], default:"你好", required:true }, // age:Number // age:{ // default:'10000000' // } age:{ type:Number, required:true }, childchange:{ type:Function }, nums:{ type:Number, // default:function(){ // // 如果default是一个函数,那么这个函数一定要有返回值 // return 1111 // } required:true, validator:function(val){ // validator 的值是一个函数, 这个函数有一个形参,形参就是传入的数据 // validator 对应的函数一定要返回一个布尔值,表示验证成功还是失败 if(val>300){ return true; }else{ return false; } } } }, mounted(){ console.log(this); } }) new Vue({ el:"#app", data:{ parmsg:"朕的天下" }, methods:{ change(){ console.log('父的change'); } } }) // 组件有一个porps属性。 props属性定了组件 有哪些可以接收外部数据的属性 // 在父的模板里面 <子组件名 :子组件的属性名='父组件的变量' ></子组件名> // 子的 配置项里面 porps:['子组件的属性名'] // 子的 模板里面 {{子组件的属性名}} // 父传子 通过 props 传入 // props:['属性名','属性名2',...] /* // 描述验证 props:{ 属性名:类型 String,Number,Boolean,Object,Array,Function type:Stirng type:[String,Number] 属性名:{ type:类型, default:'默认值', default:function(){ // default 是函数一定要有返回值 return 数据 } required:true/false, validator:function(val){ // 验证函数 val就是传入的值 // 该函数一定要有返回布尔值,代表验证通过还是没通过 } } } */ // props 也可以传入方法 </script> </html>
-
2.2、子传父:自定义事件
-
如何定义一个自定义事件
<自定义组件名 @自定义事件名='事件函数'></自定义组件名>
-
如何触发一个自定义事件
this.$emit('自定义事件名',传参数);
-
子传父实现的原理:
// 1、父的里面 组件mydiv上面 定义好自定义事件mytest, 自定义事件mytest的触发函数是父的change // 2、子的模板里面 有个按钮 绑定了子的myalert事件。 // 3、myalert事件里面的触发了自定义事件 【this.$emit('自定义事件名')】 从而触发了父的change // 4、myalert事件里面的触发了自定义事件 且传入的了参数 【this.$emit('自定义事件名','传参')】 // 5、父的change函数里面 定义好了形参接收传入的数据 // 6、父的change函数里面, 用传入的数据 更新 自己的数据, 从而实现了子的数据来更新父的数据,也就是子传入了数据给父
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <style> #app{ width: 400px; height: 400px; background-color: #eee; } .box{ width: 200px; height: 200px; background-color: orange; } </style> </head> <body> <div id="app"> <!-- <h3 @click='change'>我是根组件</h3> --> <h3>我是根组件</h3> {{nums}} <mydiv @mytest='change'></mydiv> <!-- @随便写事件名='父的事件函数' --> <!-- mytest是mydiv的自定义事件 --> </div> <template id="mydiv"> <div class="box"> <h3>我是mydiv组件</h3> <button @click='myalert'>点击自己的myalert方法</button> </div> </template> </body> <script> Vue.component('mydiv',{ template:'#mydiv', data(){ return{ } }, methods:{ myalert(){ console.log('子的myalert方法'); // 触发自定义事件 // this.$emit('自定义事件名','传递数据'); this.$emit('mytest',200); } } }) new Vue({ el:"#app", data:{ nums:-10000 }, methods:{ change(x){ console.log(x); this.nums = x; console.log("我是父的change"); } } }) // 总结: 子给父传数据 是通过 自定义事件 // 1、父的里面 组件mydiv上面 定义好自定义事件mytest, 自定义事件mytest的触发函数是父的change // 2、子的模板里面 有个按钮 绑定了子的myalert事件。 // 3、myalert事件里面的触发了自定义事件 【this.$emit('自定义事件名')】 从而触发了父的change // 4、myalert事件里面的触发了自定义事件 且传入的了参数 【this.$emit('自定义事件名','传参')】 // 5、父的change函数里面 定义好了形参接收传入的数据 // 6、父的change函数里面, 用传入的数据 更新 自己的数据, 从而实现了子的数据来更新父的数据,也就是子传入了数据给父 </script> </html>
-
原理图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CtcBGqtS-1582019279741)(./imgs/aa.png)]
3、方法3:事件传播器(任意组件之间)
-
原理: node.js中 有一个events的模块
-
核心方法: on 添加事件 emit 触发事件
let EventEmitter = require('events') let myevent = new EventEmitter(); // 定义一个事件 myevent.on('change',function(x){ console.log('change被触发了') console.log(x) }) // 触发该事件 setTimeout(function(){ myevent.emit('change',20); },2000)
-
Vue中的也有 $on 和 $emit 方法
-
如何实现任意组件之间的通信呢?
- 创建一个空的Vue实例作为事件传播器
- 在这个事件传播器上面 添加自定义事件(A组件中),然后在触发这些自定义事件(B组建中)
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <style> #box{ background-color:#eee; width: 400px; height: 400px; } .aa,.bb{ float: left; width: 200px; height: 180px; } .aa{ background-color: red; } .bb{ background-color: orange; } </style> </head> <body> <div id="box"> <h3>我是根组件</h3> <aa></aa> <bb></bb> </div> <template id='aa'> <div class="aa"> 我是aa组件 <button @click='achange'>传给bbb</button> <hr> {{msg}} </div> </template> <template id='bb'> <div class="bb"> 我是bb组件 <button @click='bchange'>传给aaa</button> <hr> {{msg}} </div> </template> </body> <script> // 创建Vue实例 代替 事件传播器 let bus = new Vue(); Vue.component('aa',{ template:"#aa", data(){ return{ str:'我是天下第一帅的aa', msg:'aaaa' } }, created(){ // 给bus添加了一个自定义事件fn1, 修改了当前组件的msg bus.$on('fn1',txt=>{ this.msg = txt; }) }, methods:{ achange(){ console.log("我是aa组件的achange"); bus.$emit('fn2',this.str); } } }) Vue.component('bb',{ template:"#bb", data(){ return{ str:'我是天下第一帅的bb', msg:'bbbb' } }, created(){ bus.$on('fn2',txt=>{ this.msg = txt; }); }, methods:{ bchange(){ console.log("我是bb组件的bchange"); bus.$emit('fn1',this.str); } } }) new Vue({ el:"#box", data:{} }) </script> </html>
4、方法4:本地存储(任意组件之间)
- 原理: A组件存, B组件取