您的位置:首页 > Web前端 > Vue.js

Vue组件通信的几种方式

2019-03-26 10:15 501 查看

组件通信分类

  • 父组件——子组件
  • 子组件——父组件
  • 兄弟组件

组件通信方式

1. props

通过使用

props
将数据从父组件传递到子组件。

<!-- Parent Component -->
<template>
<div>
<child-component :msg="msg"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent'

export default {
name: 'ParentComponent',
components:{
ChildComponent
}.
data() {
return {
msg: '我是父组件传的值'
}
}
}
</script>
<!-- Child Component -->
<template>
<div>
<p>{{msg}}</p>
</div>
</template>
<script>
export default{
name: 'ChildComponent',
props: {
msg: {
type: String
}
}
}
</script>

2. provide & inject

2.2.0版本新增API
// 父级组件提供 'foo'
var Provider = {
provide: {
foo: 'bar'
},
// ...
}

// 子组件注入 'foo'
var Child = {
inject: ['foo'],
created () {
console.log(this.foo) // => "bar"
}
// ...
}

provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作

inject 选项应该是:

  • 一个字符串数组,或
  • 一个对象,对象的 key 是本地的绑定名,value 是: 在可用的注入内容中搜索用的 key (字符串或 Symbol),或
  • 一个对象,该对象的: from 属性是在可用的注入内容中搜索用的 key (字符串或 Symbol)
  • default 属性是降级情况下使用的 value

provide 和 inject 绑定并不是可响应的

3. 自定义事件

通过使用自定义事件

$emit
将数据从子组件传递给父组件。

<template>
<div>
<child-component :msg="msg" @to-parent="childMsg=$event"></child-component>
<p>{{childMsg}}</p>
</div>
</template>
<script>
import ChildComponent from './ChildComponent';
export default {
name: 'ParentComponent',
data(){
return {
msg: '这是来自父组件的值',
childMsg: ''
}
},
components: {
ChildComponent
},
}
</script>
<!-- Child Component -->
<template>
<div>
<h4>{{ msg }}</h4>
<button @click="$emit('to-parent', newMsg)">点击向父组件传值</button>
</div>
</template>
<script>
export default {
name: 'ChildComponent',
props: ['msg'],
data: () => ({
newMsg: '这是来自子组件的值'
})
}
</script>

4. EventBus事件线

通过创建一个新的全局Vue实例来支持独立组件之间订阅

$on
和发布
$emit
自定义事件。

创建

bus.js
文件,在里面创建一个bus的Vue实例:

import Vue from 'vue';
export const bus = new Vue();

然后可以在组件中引用之后,使用bus的接口来发出事件。

<!-- ShowComponent.vue -->
<template>
<div>
<p>{{msg}}</p>
</div>
</template>
<script>
import {bus} from '../js/bus.js';
export default {
name: 'ShowComponent',
data(){
return {
msg: ''
}
},
created(){
bus.$on('to-other', msg => {
this.msg = msg;
})
}
}
</script>
<!-- InputComponent.vue -->
<template>
<div>
<input v-model="msg" type="text" />
<button @click="toOther">点击向其他组件传值</button>
</div>
</template>
<script>
import {bus} from '../js/bus.js';
export default {
name: 'InputComponent',
data(){
return {
msg: ''
}
},
methods:{
toOther(){
bus.$emit('to-ohter', msg);
}
}
}
</script>
<!-- App.vue -->
<template>
<div id="app">
<show-component></show-component>
<input-component></input-component>
</div>
</template>
<script>
import ShowComponent from './components/ShowComponent';
import InputComponent from './components/InputComponent';
export default {
name: 'App',
components: {
ShowComponent, InputComponent
}
}
</script>

5. 简单的状态管理

通过创建全局对象,可以将一些变量数据或者操作方法存储在该对象上,实现组件之间的共享。

创建

store.js
,创建全局对象
store
:

const store = {
state: {
msg: '通过自定义全局对象store进行传值'
},
changeMsg(newMsg) {
this.state.msg = newMsg;
}
}
export default store;

在组件中使用:

<!-- ShowComponent.vue -->
<template>
<div>
<p >{{storeState.msg}}</p>
</div>
</template>
<script>
import store from '../js/store.js';
export default {
name: 'ShowComponent',
data() {
return {
storeState: store.state
}
}
}
</script>
<!-- ChangeComponent.vue -->
<template>
<div>
<input v-model="msg" type="text" />
<button @click="changeMsg">点击向其他组件传值</button>
</div>
</template>
<script>
import store from '../js/store.js';
export default {
name: 'ChangeComponent',
data(){
return {
msg: ''
}
},
methods:{
changeMsg(){
store.changeMsg(msg);
}
}
}
</script>

6. Vuex

一个动作(Action)提交给一个变量(Mutation)。变量会改变状态,然后影响视图或组件。视图或组件使用

getter
检索存储数据。

Vuex存储(Vuex Store)包含四个对象:

state
mutations
actions
getters

state

state
定义共享变量。

mutations

mutations
同步修改共享变量。

actions

actions
异步请求数据。

getters

getters
过滤修改共享变量。

module

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter。

import axios from 'axios';

// user.js
const state = {
userName: ''
}
const getters = {
userName: state => state.userName
}
const mutations = {
USERNAME: (state, userName) => {
state.userName = userName
}
}
const actions = {
getUser({commit}, userInfo) {
return new Promise((resolve, reject) => {
axios({
method: 'post',
url: '/login',
data: userInfo
}).then(res => {
commit('USERNAME', res.userName);
resolve(res);
}).catch(err => {
reject(err)
})
})
}
}

export default {
state,
getters,
mutations,
actions
}
// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);
// 引入定义好的模块
import user from './modules/user'

const store = new Vuex.Store({
modules: {
user
// ...
}
})

有了Vuex存储之后,组件通常可以执行以下两种操作之一,

  1. 获取(GET)状态信息(通过访问store中state或getters)
  2. 调用(DISPATCH)actions。
<!-- ChangeComponent.vue -->
<template>
<div>
<input v-model="msg" type="text"/>
<button @click="changeMsg">点击向其他组件传值</button>
</div>
</template>
<script>
export default {
name: 'ChangeComponent',
data(){
return {
msg: ''
}
},
methods: {
changeMsg(){
this.$store.dispatch('changeMsg', this.msg)
}
}
}
</script>
<!-- ShowComponent.vue -->
<template>
<div>
<p>{{getMsg}}</p>
</div>
</template>
<script>
export default {
name: 'ShowComponent',
computed: {
getMsg() {
return this.$store.getters.getMsg
}
}
}
</script>
// message.js
const state = {
msg: '这是Vuex中存储的状态信息'
};
const mutations = {
CHANGE_MSG(state, msg) {
state.msg = msg;
}
};
const actions = {
changeMsg({commit}, msg) {
commit("CHANGE_MSG", msg);
}
};
const getters = {
getMsg(state) {
return `${state.msg} --vuex` ;
}
};
export default {
state,
mutations,
actions,
getters
}

项目src文件夹主要内容截图

下载模板,按照上图所示的目录结构创建文件夹,将文中代码复制到对应的文件中,执行即可查验。

# 安装基础模板
vue init webpack-simple my-project

# 切换到项目文件夹并安装依赖
cd my-project && npm install

# 如果需要安装vuex,执行下面的命令
npm install vuex -D
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: