vue组件通信方式
模块化,组件化在前端框架中已经是很常见的玩意了,所以了解组件、模块之间的通信那就很重要了。 组件通信方式的话,有父与子,兄弟之间,祖先与子等方式。这儿主要以父子关系取阐述这些通信机制。 一、props方式父—>子父组件传props给子组件<son :what="name" :hello="world" :callback="thing"></son> 设置了传递的值的内容,name为一个对象,hello为字符串。 data() { return { name: { a: 1,b: 2 },world: '123',thing: function() { console.log(arguments) } } } 子组件中 props: { what: { type: Object,default: {} },hello: { type: String,default: '456' },callback: { type: Function,default: function() {} } } props类似于传参的方式传给子组件,子组件中就可直接使用this去访问和使用。 子—>父直接修改引用类型的数据。前面例子中,father组件传给了son组件一个对象,son组件内可以直接修改传入的对象,由于引用关系,father内的组件值也会改变,此时我们只需要在father设置一个监听就行了。 // 监听传给子组件的值 watch: { name: { handler(nV,oV) { console.log(nV); },deep: true } } father组件就能实时获取son组件对传入值操作的情况了 传入函数方式前面的例子中,father组件向son组件传了thing这个方法,而在son组件中可以通过调用这个方法向father组件传递数据。 mounted() { // 定时模拟用户操作了啥后 setTimeout(() => { this.callback(1,2,3); },2000); } 而在father组件中定义callback的地方就可以拿到这几个参数啦。 注意:我们直接修改father传给son的非引用类型的值时,是不成功的,而且vue会提示错误。 二、$attrs与$listeners假如有父、子、孙三层组件,父要向孙通过props的方式传递数据,按照第一种方式的话得父调子时写一层,子调孙时再写一层,很繁琐且读起来很不便捷。 所以vue在2.4版本中增加了$attrs和$listeners来处理这个问题。$attrs使得属性能够穿过中间组件,而$listeners是处理绑定事件的。 父组件中,在先前的例子上加了个函数,data的内容不去改变。 <son :what="name" :hello="world" :callback="thing" @show="showMe"></son> methods: { showMe(a) { console.log('I am father',a); } } 在son组件中,只使用hello这个变量值,其他的数据都要给grandchild组件。 <grandchild v-bind="$attrs" v-on="$listeners"></grandchild> export default { components: { grandchild },props: ['hello'] }; son组件中只接收了hello,剩余的属性将通过$attrs传递给了grandchild组件。而$listeners也将绑定在son上的事件传了下去。在grandchild中,我们打印通过props传过来的属性的内容,并emit祖父级组件上的事件, export default { created () { console.log(this.$attrs); this.$emit('show','yes'); } }; 此时控制台的打印: 注:inheritAttrs配合使用,表示组件是否把未被注册的props呈现为普通的HTML属性。 三、$on与$emit该方式,严格说只有子组件向父组件通信。 父组件中: <son @what="show"></son> methods: { show() { console.log(arguments); } } 子组件中通过$emit去调用父组件中的方法, mounted() { // 定时模拟用户操作了啥后 setTimeout(() => { this.$emit('what',1,2) },1000); } 这种方式是不是比props方式中直接传函数更“和谐”些呢? 四、Bus方式在外部定义一个总的js文件用于处理组件之间的通信,该方法不止是父子组件之间的通信,只要引用该文件,任何两个组件之间都是可以进行消息传递的(父子,兄弟等等)。 该种通信下,其实没有父子关系,只有监听与触发的关系,为了方便理解,还是使用父与子。 新建一个bus.js文件,编辑该文件为: import Vue from 'vue'; export default new Vue; father和son组件中都增加对bus.js文件的引用 import Bus from './bus.js'; father组件在创建之后,使用$on增加事件的监听, created() { Bus.$on('nice',(a,b) => { console.log(a,b); }); } son组件在mount后触发对应的nice事件: mounted() { Bus.$emit('nice',{ name: 111 },123); } 此时父组件中就能获取到对应的参数了。当然反过来,子组件$on,父组件$emit,就成了父组件向子组件通信的方式了。 五、inject与provide父组件中使用provide来提供变量,在子组件中通过inject来注入变量。不论子组件有多深,只要调用了inject那么就可以注入provide中的数据。该方式只要在父组件的生命周期内,子组件都可以注入。 父组件中 <son></son> provide: { name: 'demo' } 子组件中对应的inject该变量就行了,当然为了安全起见,可以给他设定默认值。 inject: { name: { default: '1234567890' } } // inject: ['name'] // 简写方式 在element-ui中的form等表单组件时,用的还是比较多的。为了简单,仍然用父子来代替多层级的关系。 六、$parent和$childrenvue2中没有了broadcast和dispatch这种通信方式,但是通过对$parent和$children的处理,我们仍可以模拟这种方式,例如在element-ui库中,作为混入的emitter.js文件中,就用此实现了事件的触发机制。 详细的内容可以查看:element-ui emitter.js文件源码学习。 七、$ref被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的$refs对象上。如果在普通的DOM元素上使用,那么指向的就是普通的DOM元素。 通过直接取到对应的组件来获取对应的值。 比如在子组件中简单的变量, data() { return { name: 'aaa' }; } 在父组件中,只要取到对应的ref就可以获得子组件下所有的属性, <son ref="son"></son> mounted() { console.log(this.$refs.son.name); } 控制台上就可以获取到对应的属性了。 八、vuexvue的状态管理工具,不详细说了,网上有很多的教程,而且我研究的也不深入。 九、本地存储cookie,storage,indexedDB等一些用于前端本地存储的也是可以用来给组件之间交互的。 十、总结我们来总结下,非vue的方式有使用本都存储的方式,而以上所有的方式都可以用于父子组件之间的通信。父到孙组件的话,有$attrs和$listeners,bus方式,inject和provide,vuex。 兄弟直接可以使用bus方式和vuex或者先传给父组件,再广播(利用$parent和$children查找也可以)。 bus方式可以在任何关系的组件中使用,不适用vuex的简单项目中可以选取,而项目复杂的可以上vuex进行管理。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |