您的位置:首页 > 产品设计 > UI/UE

Vue组件通信

2017-08-25 16:15 190 查看

父子组件通信

父组件和子组件通信

使用
ref
为子组件指定一个索引
ID


<div id="counter-event-example">
<p @click="clickB">{{ msg }}</p>
<button-counter-a ></button-counter-a>
<button-counter-b ref="refB"></button-counter-b>
</div>


然后便可以在父组件中通过
this.$refs.refB
访问子组件方法了

Vue.component('button-counter-a', {
template: '<button v-on:click="eventClick">{{ msg }}</button>',
data: function () {
return {
msg: '组件A'
}
},
methods: {
eventClick: function () {
}
}
})

Vue.component('button-counter-b', {
template: '<button>{{ msg }}</button>',
data: function () {
return {
msg: '组件B'
}
},
methods: {
eventClick: function (msg) {
console.log(msg)
}
}
})

new Vue({
el: '#counter-event-example',
data: {
msg: '父组件'
},
methods: {
clickB () {
this.$refs.refB.eventClick(this.msg);
}
}
})


点击父组件便可以在控制台上看到子组件的输出了

可以在 这里 看看效果。

子组件和父组件通信

首先在父组件使用
$on(eventName)
监听, 然后在子组件
$emit(eventName)
触发事件。

官网 中的计数器实例,先是在父组件上监听事件
incrementTotal


<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter :count="count" v-on:increment="incrementTotal"></button-counter>
<button-counter :count="count" v-on:increment="incrementTotal"></button-counter>
</div>


然后在子组件中触发父组件事件,动态更改计数

Vue.component('button-counter', {
template: '<button v-on:click="incrementCounter">{{ counter }}</button>',
props : ["count"],
data: function () {
return {
counter: 0
}
},
methods: {
incrementCounter: function () {
this.counter += 1
this.$emit('increment', this.counter) // 第二个参数,可以传递到父组件中
console.log(this.count) // 调用父组件方法,然后发现count值变了,这里相当于接收返回值了
}
}
})

new Vue({
el: '#counter-event-example',
data: {
total: 0,
count: 0
},
methods: {
incrementTotal: function (count) {
console.log(count) // 接收子组件中的参数
this.count += 1
this.total += 1
}
}
})


这里父子组件通信,父组件通过
props
向子组件传值,子组件通过自定义是事件与父组件通信

可以在 这里 看看效果。

兄弟组件通信

A
组件想要和
B
组件通信,按照父子组件通信的思维,则是
A
和父组件通信,然后父组件再和
B
组件通信,比较绕。有没有更好的方法呢,事实上,
Vue
提供了个
Event Bus
(中央事件总线)的机制。

bus.js

import Vue from 'vue';
export default new Vue();


在A组件中触发组件 B 中的事件

import bus from 'bus.js';
bus.$emit('eventB', 'A')


在组件 B 创建的钩子中监听事件

import bus from 'bus.js';
bus.$on('eventB', function (msg) {
console.log(msg)
})


可以在 这里 看看效果。

Vuex

对于复杂的组件通信, 还是推崇
Vue
专门用来状态管理模式的
Vuex
。来看看下面官网上的这张图



图中的
State
, 就是驱动应用的原始数据源,以声明方式将这些
State
映射到
View
中,而要改变
State
,则要通过一些
Action
来驱动。



图中绿色虚线
Vuex
部分显示发生在
Component
上的一次事件中来
Commit
一个相应的
Mutations
方法,
Mutations
方法来
Mutate
对应的
State
,然后在组件中通过计算属性的监测,响应式更新视图。

来看个简单的计数器 实例

<div id="app">
<p>{{ count }}</p>
<p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</p>
</div>


const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: state => state.count++, // 箭头函数,相当于 function (state) {return state.count++}
decrement: state => state.count--
}
})

new Vue({
el: '#app',
computed: {
count () {
return store.state.count
}
},
methods: {
increment () {
store.commit('increment')
},
decrement () {
store.commit('decrement')
}
}
})


最后来个在实际项目中
Vuex
实例,需要安装
npm install vuex vuex-persistedstate
,
vuex-persistedstate
实际上使用了
HTML 5
中的
localStorage
来做缓存,这样在刷新页面后之前
state
的数据不会丢失。

mutation-type.js

// 更新 count
export const UPDATE_COUNT = 'UPDATE_COUNT';


mutation.js

import * as types from './mutation-types'

export default {
// 更新 count
[types.UPDATE_COUNT] (state, count) {
state.count= count
}
}


actions.js 【需注意在
mutations
里都是用大写下划线连接,在
actions
里都用小写驼峰对应】

import * as types from './mutation-types'

export default {
updateCount({ commit }, count) {
commit(types.UPDATE_COUNT, count)
}
}


getters.js

export default {
evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd'
}


state 【index.js】

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'

Vue.use(Vuex);

const state = {
count: 0
};

export default new Vuex.Store({
state,
mutations,
actions,
getters,
plugins: [createPersistedState()]
})


main.js

import store from './store'

new Vue({
el: '#app',
store,
template: '<App/>',
components: { App }
})


在具体某个组件中应用

<template>
<div @click="increment">{{count}} {{isEvenOrOdd}}</div>
</template>

<script>
export default {
name: 'bar',
computed: {
count () {
return this.$store.state.count
},
isEvenOrOdd () {
return this.$store.getters.evenOrOdd
}
},
methods: {
increment () {
this.count += 1
this.$store.dispatch('updateCount', this.count)
}
}
}
</script>


如果项目较大,而且操作的状态又多,要是都放在一棵树上,那么
store
对象就先显得臃肿,这时可以可以把
store
按一定逻辑分割成
module
(模块)

app.js

const app = {
state: {
count: 0
},
mutations: {
UPDATE_COUNT: (state, count) => {
state.count += count
}
},
actions: {
updateCount({ commit }, count) {
commit('UPDATE_COUNT', count)
}
}
getters: {
evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd'
}
}

export default app;


store/index.js

import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate'
import app from './modules/app';
Vue.use(Vuex);

const store = new Vuex.Store({
modules: {
app
},
plugins: [createPersistedState()]
});

export default store


引用

this.$store.state.app.count // 加上模块名
this.$store.dispatch('updateCount', 1)


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Vue Vuex