针对不同的使用场景,如何选择行之有效的通信方式?这是我们所要探讨的主题。本文总结了 vue 组件间通信的几种方式,如
props
、$emit/$on
、vuex
、$parent / $children
、$attrs/$listeners
和provide/inject
,以通俗易懂的实例讲述这其中的差别及使用场景。
1、props/$emit
父组件向子组件传值. 父组件 A 通过 props 的方式向子组件 B 传递,B to A 通过在 B 组件中 $emit, A 组件中 v-on 的方式实现。
<template>
<div id="app">
<users :users="users" @getMsg="showMsg"></users>
</div>
</template>
<script>
import Users from "./components/Users"
export default {
name: 'App',
data() {
return {
users: ["Henry", "Bucky", "Emily"]
}
},
components: {
"users": Users
},
methods: {
showMsg(val) {
console.log(val)
}
}
}
子组件
<template>
<div class="hello">
<ul>
<li v-for="user in users" @click="sendMsg">{{user}}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
users: {
type: Array,
required: true
}
},
methods: {
sendMsg() {
this.$emit('getMsg', 'get data from child') //自定义事件 传递值“子向父组件传值”
}
}
}
</script>
$emit/$on
这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。当我们的项目比较大时,可以选择更好的状态管理解决方案 vuex。
var Event=new Vue();
Event.$emit(eventName,data);
Event.$on(eventName,data => {});
Vuex
1.dispatch 异步操作 this.store.dispatch('actions.example()', arg), 调用actions里的方法。
2.commit 同步操作 this.store.commit('mutations.example()', arg),调用mutations里的方法。
const user = {
state: {
token: ''
},
mutations: {
SET_TOKEN: (state, token) => {
state.token ="test " +token
},
},
actions: {
// 登录
Login({commit}, userInfo) {
return new Promise((resolve, reject) => {
login(userInfo.account, userInfo.password).then(aa => {
if(aa.status==200){
const tokenSuccess = aa.data.token.tokenValue
commit('SET_TOKEN', tokenSuccess )
token="test"+tokenSuccess ;
//setToken("test" +token)
resolve();
}
}).catch(error => {
console.log("登录失败")
reject(error)
})
})
},
}
}
toLogin() {
this.$store.dispatch('Login',arg).then((res) => {
console.log(res)
})
}
$attrs/$listeners
$attrs:当前组件的属性,通俗的讲也就是在组件标签定义的一系列属性,如input的value,placeholder等,但是不包括在当前组件里面定义的props属性
$listeners:当前组件监听的事件,通俗的讲也就是在使用组件的时候在标签中定义的事件,如@input,以及一些自定义事件@tempFn等
$props:当前组件从父组件那里接收的参数,通俗的讲和$attr差不多,但是只包括在当前组件中定义了的props属性
<childComponent v-bind="$attrs" v-bind="$listeners"></childComponent>
provide/inject
主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
父组件
export default {
provide: (){
return {
name: 'demo'
}
}
}
子组件
export default {
inject: ['name'],
mounted () {
console.log(this.name);
}
}