Vue组件通信的几种方式

组件通信分类

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

组件通信方式

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)包含四个对象:statemutationsactionsgetters

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文件夹主要内容截图

image

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

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

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

# 如果需要安装vuex,执行下面的命令
npm install vuex -D
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值