目次
- 前言
- 一、props、$emit单向数据流
- 二、$parent、$children
- 三、$attrs、$listeners
- 四、provide、inject
- 五、eventBus(变乱总线)
- 六、vuex
- 七、localstorage
- 总结
前言
组件通讯在我们平时开发过程中,特别是在vue和在react中,有着举足轻重的职位。本篇将总结在vue中,组件之间通讯的几种方式:
- props、$emit
- $parent、$children
- $attrs、$listeners
- provide、inject
- eventBus
- vuex
- 本地存储
一、props、$emit单向数据流
father.vue:
- <template>
- <div>
- <div>我是父亲:<input type="button" value="父亲" /> 数字为: {{num}}</div>
- <son :num="num" @change="change"></son>
- </div>
- </template>
-
- <script>
- import son from "./son.vue";
- export default {
- name: "Father",
- components: {
- son,
- },
- data() {
- return {
- num: 1,
- };
- },
- methods:{
- change(val){
- this.num = val
- }
- }
- };
- </script>
复制代码
son.vue:- <template>
- <div>我是儿子:<input type="button" value="儿子" @click="change"/>数字为:{{num}}</div>
- </template>
-
- <script>
- export default {
- name: "App",
- components: {},
- props: {
- num: {
- default: 0,
- },
- },
- created() {},
- methods: {
- change(){
- // this.num = 2 props通信是单向数据流,在这直接修改父组件传过来的num将会报错 // 可以用$emit触发change事件,father组件绑定change事件 this.$emit('change', 2)
- }
- },
- };
- </script>
复制代码
对于上面的场景:子组件的change变乱只是为了修改父组件中某一个值,还可以有以下几种写法:
1.父组件绑定给子组件的变乱利用箭头函数- father:
- <son :num="num" @change="val => num = val"></son>
-
- son:
- this.$emit('change', 2)
复制代码
2.update:num和.sync- father:
-
- <son :num.sync="num"></son>
-
- son:
-
- this.$emit('update:num', 2)//update是规定的写法,不可更换
复制代码
3.v-model
先修改props和绑定的变乱:- father:<son :value="num" @input="val => num = val"></son>son:this.$emit('input', 2)
- 可用v-model简写:<son v-model="num"></son>
复制代码
二、$parent、$children
$parent、$children可直接在父子组件中调用各自的方法以及修改数据
子组件中直接:this.$parent.num = 2
父组件中$children是个数组,因此详细是哪个子组件不太直观,可以用$refs来操作子组件
vue官方并不保举利用这种通讯方式:控制地利用复制代码 和复制代码 - 它们的主要目的是作为访问组件的应急方法,更保举用 props 和 events 实现父子组件通讯。
三、$attrs、$listeners
$attrs可以拿到父组件传过来的属性:- <div>我是儿子:<input type="button" value="儿子" @click="change"/>数字为:{{$attrs}}</div>
复制代码
dom节点:
$attrs会直接将传过来的属性放到对应的标签上,反观props就不会。假如想去掉标签中的这些属性,可以用inheritAttrs:
值得注意的是:props的优先级大于$attrs,即当props存在的时间,$attrs为空对象:
$attrs常用于跨多级组件传递属性,好比祖孙组件,用父组件做中转:
father:- <son v-bind="$attrs"></son>
复制代码
$attrs用于属性跨级传递,方法跨级传递则用$listeners。
grandFather.vue:- <template>
- <div>
- <div>我是祖父: 数字为:{{nums}}</div>
- <father :nums="nums" @up="up" @down="down"></father>
- </div>
- </template>
-
- <script>
- import father from "./father.vue";
- export default {
- name: "App",
- components: {
- father,
- },
- data(){
- return {
- nums:0
- }
- },
- methods: {
- up() {
- alert('up')
- }, down() { alert('down') },
- },
- };
- </script>
复制代码
father.vue:- <son v-bind="$attrs" v-on="$listeners"></son>
复制代码
son.vue:- <div>我是儿子:<input type="button" value="儿子" @click="$listeners.up"/></div>
复制代码
四、provide、inject
这对选项必要一起利用,以允许一个祖先组件向其全部子孙后代注入一个依赖,岂论组件条理有多深,并在其上下游关系建立的时间里始终收效
provide选项应该是一个对象或返回一个对象的函数。
inject选项应该是一个字符串数组或一个对象。
App:- ...
-
- export default {
- provide(){
- return {vm: this}
- },
-
- ...
复制代码
son:- ...
-
- export default {
- inject: ['vm'], data(){}, mounted(){ console.log(this.vm) }
-
- ...
复制代码
注意:provide 和 inject 绑定并不是可相应的。这是刻意为之的。然而,假如你传入了一个可监听的对象,那么其对象的 property 还是可相应的。
inject注入中的值会沿着组件向上查找,服从"就近原则"。
provide 和 inject中的数据流是双向的。
五、eventBus(变乱总线)
eventBus通过发布订阅全局变乱,供其他组件利用。
在main.js中:- Vue.prototype.$bus = new Vue();
复制代码
parent.vue:- <template>
- <div>
- <son1></son1>
- <son2></son2>
- </div>
- </template>
-
- <script>
- import son1 from './son1.vue'
- import son2 from './son2.vue'
- export default {
- name: 'parent',
- components: {
- son1,
- son2
- },
- created(){
- this.$bus.$on('busEvent',(v)=>{
- console.log(v);
- })
- },
- beforeDestroy(){
- this.$bus.off('busEvent')
- }
- }
- </script>
复制代码
son1和son2中的mounted:- son1:mounted(){
- this.$bus.$emit('busEvent','son1哈哈')
- }son2:mounted(){ this.$bus.$emit('busEvent', 'son2嘻嘻')}
复制代码
打印结果:
利用eventBus有三点必要注意,1.$bus.on应该在created钩子内利用,假如在mounted利用,它可能吸收不到其他组件来自created钩子内发出的变乱;
2.$bus.emit应该在mounted中利用,等候created中的$bus.on变乱绑定完成;
3.发布订阅的变乱在beforeDestory钩子里必要利用$bus.off排除,组件烧毁后没须要一直监听。
六、vuex
借助vuex的状态管理来实现组件通讯,vuex实用于较为复杂的项目,频繁的数据共享且数据量比力大。
store/index.js:- import Vue from 'vue'
- import Vuex from 'vuex'
-
- Vue.use(Vuex)
-
- const store = new Vuex.Store({
- state: {
- isLogin: false
- },
- mutations: {
- loginState (state, isLogin) {
- state.isLogin = isLogin
- }
- }
- })
-
- export default store
复制代码
App.vue:- created(){
- this.$store.commit('loginState',true)// 设置登录状态为true
- },
复制代码
son.vue:- <template>
- <div>我是儿子:<input type="button" value="儿子" />登录状态:{{isLogin}}</div>
- </template>
-
- <script>
- import {mapState} from 'vuex';
- export default {
- name: "son",
- computed:{
- ...mapState(['isLogin'])
- }
- };
- </script>
复制代码
七、localstorage
localstorage是欣赏器的本地存储,将会长期存储在欣赏器中,非常庞大的数据不建议用此方式。
App.vue- created(){
- localStorage.setItem('isLogin', true)
- },
复制代码
son.vue:- computed:{
- isLogin(){
- return localStorage.getItem('isLogin')
- }
- }
复制代码
常见的组件通讯方式根本就是这些啦,有什么遗漏或不足的,接待评论区留言!
总结
到此这篇关于vue组件间通讯的文章就先容到这了,更多相干vue组件间通讯内容请搜索草根技术分享从前的文章或继承欣赏下面的相干文章渴望大家以后多多支持草根技术分享! |