整理了vue中组件通信,分以下情况:(代码环境:vue2.0 vue-cli 3.0.1)
一:父--》子通信
1、通过props:
//子组件 <template> <div class="son">{{msg}}</div> </template> <script> export default { name: 'son', props:{ msg:String } } </script>
//父组件 <template> <div class="parent"> <son :msg="myName"></son> </div> </template> <script> import son from '../components/son' export default { name: 'parent', components:{ son }, data() { return { myName:'hello world' } } } </script>
以上就是将父组件parent中的myName传入到了子组件son中
注意:根据官方文档,所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
二:子--》父
通过事件,使用$emit触发,具体看以下代码:
//子组件 <template> <div class="son" > <button @click="getNum">click</button> </div> </template> <script> export default { name: "son", data() { return { num:6666 }; }, methods: { getNum() { this.$emit('getNum',this.num) } } }; </script>
//父组件 <template> <div class="parent"> <son @getNum="getNum"></son> </div> </template> <script> import son from '../components/son' export default { name: 'parent', components:{ son }, methods:{ getNum(e){ console.log(e)//可以获取到子组件中的num值 } } } </script>
三:其实父子组件通信还可以使用vm.$refs 一个对象,持有注册过 ref特性 的所有 DOM 元素和组件实例。
//父组件 通过调用子组件的方法,以参数的形式传入到子组件中;同样的子组件也可以使用方法将值传到父组件中 <template> <div class="parent"> <son ref="son"></son> </div> </template> <script> import son from '../components/son' export default { name: 'parent', components:{ son }, data() { return { myName:'hello world' } }, mounted(){ this.$refs.son.getName(this.myName)
console.log(this.$refs.son.getNum())//输出的就是子组件中num值 } } </script>
//子组件 <template> <div class="son"> </div> </template> <script> export default { name: "son",
data(){return {num:123}}, methods: { getName(e) { console.log(e)//e就是传入的myName值 },
getNum(){
return this.num
}
} }; </script>
注意:根据官方文档 $refs
只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs
。
因此还是不建议使用ref来进行父子之间的数据传递;
四:非父子组件中的数据传递
1、路由url传递
-
在传统开发时我们常常把需要跨页面传递的数据放到url后面,跳转到另外页面时直接获取url字符串获取想要的参数即可,在vue跨组件时一样可以这么做,
// router index.js 动态路由 { path:'/params/:Id', component:Params, name:Params } // 跳转路由 <router-link :to="/params/12">跳转路由</router-link>
- 在跳转后的组件中用$route.params.id去获取到这个id参数为12,但这种只适合传递比较小的数据,数字之类的
2、 eventBus通信
eventBus这种通信方式,针对的是非父子组件之间的通信,它的原理还是通过事件的触发和监听。
但是因为是非父子组件的关系,他们需要有一个中间组件来连接。
使用eventBus传递数据,我们一共需要做3件事情
- 1.在组件之外定义一个bus.js作为组件间通信的桥梁,适用于比较小型不需要vuex又需要兄弟组件通信的,或者给app组件添加Bus属性 (这样所有组件都可以通过this.$root.Bus访问到它,而且不需要引入任何文件)
- 2.在组件1里,this.$root.Bus.$emit触发事件
- 3.在组件2里,this.$root.Bus.$on监听事件
//bus.js import Vue from 'vue' export default new Vue() /* 或者在main.js中添加Bus属性 import Vue from 'vue' new Vue({ el: '#app', components: { App }, template: '<App/>', data(){ return { Bus : new Vue() } } }) 通过this.$root.Bus.$emit()/.$on()来处理 */
//组件1 <template> <div class="home"> <button @click="handlerClick">clickBus</button> </div> </template> <script> // @ is an alias to /src import Bus from '../models/bus' export default { name: "home", methods:{ handlerClick(){
Bus.$emit('handlerClick','兄弟组件传递参数')
} } }; </script>//组件2 <template> <div class="about"> <h1>This is an about page</h1> </div> </template> <script> import Bus from '../models/bus' export default { data(){ return {} }, mounted(){ Bus.$on('handlerClick',(e=>{
console.log(e) })) } }; </script>注意:首屏渲染完之后,没有进入组件2,在组件1中直接点击handlerClick按钮时,并不会触发组件2中的clickBus事件,可能是这时候组件2并没有渲染事件并没有绑定,无法触发
五:祖--》孙
如果跨组件传递通过以上一步步的传递是比较麻烦的,可以使用$attr来实现祖孙之间的传递
意思就是父组件传向子组件传的,子组件不prop接受的数据都会放在$attrs中,子组件直接用this.$attrs获取就可以了。如过从父->孙传,就在子组件中添加v-bind='$attrs',就把父组件传来的子组件没props接收的数据全部传到孙组件,具体看以下代码
//祖组件 <template> <div class="grandFather"> <parent :number="num" :output="myName"></parent> </div> </template> <script> import parent from './Parent' export default { name: 'grandFather', components:{ parent }, data() { return { num:666, myName:'grandFather' } } } </script>
//父组件 <template> <div class="parent"> <son v-bind="$attrs" ></son> </div> </template> <script> import son from '../components/son' export default { name: 'parent', components:{ son }, props:{ number:Number//这里在父组件中定义了number,因此在父组件以及子组件中this.$attrs无法获取number值 }, mounted(){ console.log(this.$attrs)//打印output } } </script>
//子组件 <template> <div class="son" > son </div> </template> <script> export default { name: "son", mounted(){ console.log(this.$attrs)//打印output } }; </script>
得到一下输出结果:
六:其他的通信方式
1、用localStorage或者sessionStorage这种通信比较简单,缺点是数据和状态比较混乱,不太容易维护。
通过window.localStorage.getItem(key) 获取数据
通过window.localStorage.setItem(key,value) 存储数据
注意用JSON.parse() / JSON.stringify() 做数据格式转换。
2、provide/inject还有$children/$parent
3、使用vuex
参考文章:
vue组件通信全面总结
以上是根据上面两篇文章进行的总结,如果看不懂可以访问原链接,原文里面也有其他的方法可以参考,有错误的地方希望可以提出。