🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
>[success] # bus 非父子组价通信 ~~~ 1.常见的几种传递,子传父,父传子,非父子组件通信 ~~~ >[info] ## 子传父/父传子综合案例 ~~~ 1.父传子使用props,子组件在使用的时候会在props中专门定义一个值,这 值用来完成父传子的中间站,子组件在自己的作用域中直接,调用这个中间 件,进而完成子组件中使用父组件的内容 2.子传父比较特别,他是通过在调用组件的时候,在组件上绑定了个方法, 举个例子说明: '<my-Com2 @fun="myChange"></my-Com2>' 正常来说 v-on 后面会跟一些已知的事件例如click,input,change,keyup 等,但是子传父绑定的是一个自定义名称,myChange 是父组件methods, 中的一个方法,在调用的时候,我们会通过子组件中的一个方法进行驱动例 如:'<button @click="changeParent">操作父组件的子组件方法</button>' 上面这个案例中'changeParent' 是子组件一个方法,在这个方法中去触发 '$emit' 来进而的控制父组件的方法,进而改变父组件例如: changeParent(){ // 根据上面的介绍原则等号左面的属于子组件的右面属于父组件 // 因此fun是子组件的,告诉自己的组件的点击事件,点击后触发 // $emit,让他去找参数中和func绑定的父组件的方法 // 第二个参数可以往父组件传值 this.$emit('fun','我是传值') } ~~~ >[danger] ##### 牛逼案例 ~~~ 1.这个案例是结合 父传子和子传父同时使用的一个案例,要记住的是 v-model 是一个语法糖,这个语法糖绑定是input 事件,因此handleInput, 中'$emit' 操控的就是这个input 事件,为了可以让子组件可以,获取父组件初始化input值,用在子组件定一个props['value'] 来接受这个父组件的value ,因为v-model 语法糖分解后事 @input='一个事件' v-bind:value='input值' ,所以子组件中的props:['value'] 用的是value 用来完成父传子。 2.下面的案例虽然没子传父是控制,父组件的方法,然而父组件中没有方 法,仅控在子组件控制了'input' 就是现实是因为v-model 语法糖的缘故 ~~~ ~~~ <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Examples</title> <link href="" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script> </head> <body> <div id="app"> <my-Com2 v-model="inputValue"></my-Com2> {{inputValue}} </div> <template id="sapp"> <div> <input @input="handleInput" :value="value"> </div> </template> <script type="text/javascript"> let myCom2 = { template:'#sapp', props:['value'], // data(){ // return { // value:"" // } // }, methods:{ handleInput(event){ const value = event.target.value this.$emit('input', value) } } }; var vms = new Vue({ el: "#app", data:{ inputValue:"测试" }, components:{ myCom2 , } }) </script> </body> </html> ~~~ >[info] ## 兄弟组件通信 ~~~ 1.兄弟组件在同一地方使用的两个组件 2.兄弟间的通信其实就是一个组件通过子传父改变父组件内容,然后另一个 组件接受这个父组件的改变值,形成父传子 ~~~ >[danger] ##### 案例 ~~~ 1.下面案例中myCom2 完成父传子和子传父,将子传父改变的值交给了, myCom3 组件,进而改变myCom2 组件内容 ~~~ ~~~ <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>Examples</title> <meta name="description" content=""> <meta name="keywords" content=""> <link href="" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script> </head> <body> <div id="app"> <my-Com2 v-model="inputValue"></my-Com2> <my-Com3 v-bind:content="inputValue"></my-Com3> </div> <template id="sapp"> <div> <input @input="handleInput" :value="value"> </div> </template> <template id="sapp1"> <div> {{content}} </div> </template> <script type="text/javascript"> let myCom2 = { template:'#sapp', props:['value'], methods:{ handleInput(event){ const value = event.target.value this.$emit('input', value) } } }; let myCom3 = { template:'#sapp1', props:{ content:{ type:String, default:"" } } }; var vms = new Vue({ el: "#app", data:{ inputValue:"测试" }, components:{ myCom2 , myCom3 , } }) </script> </body> </html> ~~~ >[info] ## 使用bus兄弟组件通信 ~~~ 1.上面的案例是必须有一个父组件在中间做'桥梁',这个'桥梁'来完成兄弟传递 2.可以使用bus 更简单的完成这个传递 3.首先要创建一个vue实例 用来做这个桥梁 4.使用 $on(eventName) 监听事件 5.使用 $emit(eventName) 触发事件 6.其实本质利用的就是'发布订阅解决思想模式' ~~~ >[danger] 案例 ~~~ <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>Examples</title> <meta name="description" content=""> <meta name="keywords" content=""> <link href="" rel="stylesheet"> <script type="text/javascript" src="lib/vue.js"></script> </head> <body> <div id="box"> <child1></child1> <child2></child2> </div> <script type="text/javascript"> var bus = new Vue();//空vue实例 var child1 = { template:` <div>child1 <button @click="handleClick()">click</button> </div> `, data(){ return { text:"来自child1的问候" } }, methods:{ handleClick(){ //传text 给 child2. // bus.$emit("kerwin",this.text); } } } var child2 = { template:` <div>{{innerHTML}}</div> `, data(){ return { innerHTML : "child2" } }, mounted(){ //组件加载完成 这个方法会被调用, console.log("child2 mounted"); //监听事件, ajax , bus.$on("kerwin",(data)=>{ this.innerHTML = data; }) } } // vm.$mount("#box") new Vue({ el:"#box", components:{ child1, child2 } }) </script> </body> </html> ~~~ >[danger] ##### vue-ui 使用bus 案例 ~~~ 1.创建一个空的vue实例 来作为交互的中介 2.接收的时候在mounted生命周期去接受 3.在lib 中创建一个bus.js 用来创建这个第三方 ~~~ * bus.js ~~~ import Vue from 'vue' const Bus = new Vue(); export default Bus ~~~ * 在视图组件中创建一个email,这个视图是用来传出值的 ~~~ <template> <div> <button @click="handleClick">点击</button> </div> </template> <script> export default { name: "email", methods:{ handleClick(){ // 通过emit 给bus 提交一个保存的值 // 第一个参数是保存进bus 的key,第二个参数保存在bus,key对应的value this.$bus.$emit('on-click','传递值') }, }, mounted(){ console.log(this.$bus) } } </script> <style scoped> </style> ~~~ * 在视图组件中创建一个tel.vue,这个视图是用来接受值的 ~~~ <template> <div> <h2>{{message}}</h2> </div> </template> <script> export default { name: "tel", data(){ return{ message:"", } }, mounted(){ this.$bus.$on('on-click',mes=>{ this.message = mes }) }, } </script> <style scoped> </style> ~~~ * 我在router 文件下的router.js 对两个路由的配置 ~~~ { path:'/name_view', components:{ email:()=>import('@/views/email.vue'), tel:()=>import('@/views/tel.vue'), } }, ~~~ * 在 main.js 注册这个bus ~~~ import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' import Bus from './lib/bus' Vue.config.productionTip = false; // 注册bus Vue.prototype.$bus = Bus; new Vue({ router, store, render: h => h(App) }).$mount('#app'); ~~~ * 在App Vue 创建好对应的命名视图,然后访问这连接 ~~~ <router-view name="email"></router-view> <router-view name="tel"></router-view> ~~~