vue组件通信

160 阅读2分钟

组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。这时候就需要组件之间的通信了:

组件通信的几种方式

1、父子组件通信

2、兄弟组件通信

3、跨多层级组件通信

4、任意组件(vuex)

一、父子组件

1、父组件通过props传递数据给子组件,子组件通过$emit发送事件传递数据给父组件(单向数据流)

2、还可以通过v-model语法糖(双向数据绑定)

3、parent,parent,children对象来访问组件实例中的方法和数据

4、listeners,listeners,sync(2.3版本以上),listeners属性会将父组件中(不含.native修饰器)von事件监听器传给子组件,子组件可以通过访问listeners属性会将父组件中(不含.native修饰器)v-on事件监听器传给子组件,子组件可以通过访问listeners来自定义监听器,.sync属性是个语法糖,可以简单的实现子组件与父组件通信

5、$ref也可进行组件通信,放在组件上可以获取组件实例

<!--父组件中-->
<input :value.sync="value"/>
<!--以上写法等同于-->
<input :value="value" @undate:value="v=>value=v"></comp>
<!--子组件中-->
<script>
    this.$emit('update:value',1)
</script>

二、兄弟组件通信

1、可借助父组件当做通讯的桥梁

2、利用eventBus总线实现,(实际上就是新建一个vue实例,用eventBus.emit替代this.emit替代this.emit,一样用v-on监听事件变化)

// main.js
import Vue from 'vue'
import App from './App'
 
export const eventBus = new Vue()
 
new Vue({
    el: '#app',
    render: h => h(App)
})

在兄弟组件中导入

<!-- BrotherCard.vue -->
 
<script>
    import { eventBus } from '../main'
</script>

对于这种情况可以通过查找父组件中的子组件实现,也就是this.parent.parent.childrren,在children中可以通过组件name查询到需要的组件实例,然后进行通信。children中可以通过组件name查询到需要的组件实例,然后进行通信。children返回的是一个组件集合

1)$refs

首先,给子组件做标记,demo:

<firstchild ref="one"></firstchild>

然后再父子间中,通过this.$refs.one就可以访问到这个子组件了,包括访问子组件的data里面的数据,调用他的函数

三、跨多层级组件通信

// 父组件 A
export default {
  provide: {
    data: 1
  }
}
// 子组件 B
export default {
  inject: ['data'],
  mounted() {
    // 无论跨几层都能获得父组件的 data 属性
    console.log(this.data) // => 1
  }
}

四、任意组件

使用vuex 与 localStorage

   简要介绍 Vuex 原理:
   Vuex 实现了一个单向数据流,在全局拥有一个 State 存放数据,当组件要更改 State 中的数据时,必须通过 Mutation 进行,Mutation 同时提供了订阅者模式供外部插件调用获取 State 数据的更新。而所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走 Action,但 Action 也是无法直接修改 State 的,还是需要通过 Mutation 来修改 State 的数据。最后,根据 State 的变化,渲染到视图上。
	let defaultCity = "北京"
	try {   // 用户关闭了本地存储功能,此时在外层加个try...catch
	  if (!defaultCity){
	    defaultCity = JSON.parse(window.localStorage.getItem('defaultCity'))
	  }
	}catch(e){}
	export default new Vuex.Store({
	  state: {
	    city: defaultCity
	  },
	  mutations: {
	    changeCity(state, city) {
	      state.city = city
	      try {
	      window.localStorage.setItem('defaultCity', JSON.stringify(state.city));
	      // 数据改变的时候把数据拷贝一份保存到localStorage里面
	      } catch (e) {}
	    }
	  }
	})

这里需要注意的是:由于 vuex 里,我们保存的状态,都是数组,而 localStorage 只支持字符串,所以需要用 JSON 转换:

	JSON.stringify(state.subscribeList);   // array -> string
	JSON.parse(window.localStorage.getItem("subscribeList"));    // string -> array