vue组件通信

Posted 测试zhzh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue组件通信相关的知识,希望对你有一定的参考价值。

  1. 父子组件通信

        父组件向子组件传值通过props属性,子组件向父组件传值通过$emit来触发事件。

子组件代码:

<template>

  <div>

    <h4 @click="showMsg">{{msg}}</h4>

    <div class="item" v-for="(v,iin list" :key="i">

      我是{{v.name}}

      <button @click="sendInfo(v)">点击发送</button>

    </div>

  </div>

</template>

<script>

export default {

  props: ["msg""list"],

  mounted() {},

  methods: {

    showMsg() {

      this.$emit("getMessage""这是父组件");

    },

    sendInfo(v) {

      this.$emit("showInfo"v);

    }

  }

};

</script>

<style scoped>

.item {

  margin-top10px;

}

</style>

props中的msg和list都是父组件传过来的,

父组件代码:

<template>

  <div class="home">

    <h1>爷爷:孙子们,来说话</h1>

    <h4 v-if="isShow">我是{{info.name}},我今年{{info.age}}岁</h4>

    <Child :msg="msg" :list="list" @getMessage="showMsg" @showInfo="showInfo"></Child>

  </div>

</template>


<script>

import Child from "@/components/child.vue";


export default {

  name: "home",

  components: {

    Child

  },

  data() {

    return {

      child2Msg: 'Hello World',

      message: "",

      msg: "child组件",

      list: [

        {

          name: '孙子1',

          age: 10

        },

        {

          name: '孙子2',

          age: 15

        },

        {

          name: '孙子3',

          age: 18

        },

        {

          name: '孙子4',

          age: 15

        }

      ],

      info: {


      },

      isShow: false,

    };

  },

  methods: {

    showMsg(title) {

      this.message = title;

    },

    showInfo(prop) {

      this.isShow = true;

      this.info = prop;

    }

  }

};

</script>

父组件通过props把msg和list两个参数传给子组件,渲染子组件,父传子。

在父组件中的child子组件上注册事件@getMessage和@showInfo两个事件,在子组件中的按钮上注册点击事件通过this.$emit("getMessage""这是父组件");以及this.$emit("showInfo"v);来触发事件实现将第二个参数传给父组件,父组件接收到后进行操作,这是子传父。


2.非父子组件通信  ($emit/$on)

    这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。

在根组件上注册上bus,

main.js代码: 

import Vue from 'vue'

import App from './App.vue'

import router from './router'

import store from './store'


Vue.config.productionTip = false


new Vue({

  router,

  store,

  render: h => h(App),

  data: {

    Bus: new Vue()

  }

}).$mount('#app')


child组件代码如下: 

<template>

  <div>

    <h4 @click="showMsg">{{msg}}</h4>

    <div class="item" v-for="(v,iin list" :key="i">

      我是{{v.name}}

      <button @click="sendInfo(v)">点击发送</button>

    </div>

  </div>

</template>

<script>

export default {

  props: ["msg""list"],

  mounted() {},

  methods: {

    showMsg() {

      this.$emit("getMessage""这是父组件");

    },

    sendInfo(v) {

      this.$emit("showInfo"v);

      this.$root.Bus.$emit('sendName'v);

    }

  }

};

</script>

<style scoped>

.item {

  margin-top10px;

}

</style>

child2组件代码如下:

<template>

  <div>

    <h1>{{name}}</h1>

    {{child2}}

  </div>

</template>

<script>

export default {

  props: ["child2"],

  data() {

    return {

      name: ""

    };

  },

  created() {

    this.$root.Bus.$on("sendName"value => {

      this.print(value);

    });

  },

  methods: {

    print(v) {

      this.name = v.name;

    }

  },

  beforeDestroy() {

    this.$root.Bus.$off("sendName");

  }

};

</script>

<style scoped>

</style>

home组件代码:

<template>

  <div class="home">

    <h1>爷爷:孙子们,来说话</h1>

    <h4 v-if="isShow">我是{{info.name}},我今年{{info.age}}岁</h4>

    <Child :msg="msg" :list="list" @getMessage="showMsg" @showInfo="showInfo"></Child>

    <Child2 :child2="child2Msg"></Child2>

  </div>

</template>


<script>

import Child from "@/components/child.vue";

import Child2 from "@/components/child2.vue";


export default {

  name: "home",

  components: {

    Child,

    Child2

  },

  data() {

    return {

      child2Msg: 'Hello World',

      message: "",

      msg: "child组件",

      list: [

        {

          name: '孙子1',

          age: 10

        },

        {

          name: '孙子2',

          age: 15

        },

        {

          name: '孙子3',

          age: 18

        },

        {

          name: '孙子4',

          age: 15

        }

      ],

      info: {


      },

      isShow: false,

    };

  },

  methods: {

    showMsg(title) {

      this.message = title;

    },

    showInfo(prop) {

      this.isShow = true;

      this.info = prop;

    }

  }

};

</script>

在home组件中我们可以看到child和child2是非父子组件
在child2中通过

this.$root.Bus.$on("sendName"value => {

      this.print(value);

    });

去注册一个自定义事件,value是接收到的参数,sendName是事件名,print是具体的执行函数,在child组件中通过

this.$root.Bus.$emit('sendName'v);去触发sendName函数,传递参数v,

child2组件能接收到v进行具体的操作数据。

如果有多个组件组件需要通信,不需要的根组件上多建几个 Bus,只要保证事件名 (sendName)不一样就行了。


3.vuex

Vuex实现了一个单向数据流,在全局拥有一个State存放数据,当组件要更改State中的数据时,必须通过Mutation进行,Mutation同时提供了订阅者模式供外部插件调用获取State数据的更新。而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走Action,但Action也是无法直接修改State的,还是需要通过Mutation来修改State的数据。最后,根据State的变化,渲染到视图上。

新建store/test.js文件: 

const test = {

    namespaced: true,

    state: {

        count: 3

    },

    mutations: {

        increment(statepayload) {

            state.count += payload;

        },

        reduce(statepayload) {

            state.count -= payload;

        }

    },

    actions: {

        getCountRet(context) {

            context.commit('increment'10);

        },

        getCountRet2(context) {

            context.commit('reduce'10);

        }

    }

}

export default test;

store/index.js代码: 

import Vue from 'vue'

import Vuex from 'vuex'

import Test from './test';


Vue.use(Vuex)


export default new Vuex.Store({

  state: {

  },

  mutations: {

  },

  actions: {

  },

  modules: {

    Test

  }

})

child2代码: 

<template>

  <div>

    <h1>{{name}}</h1>

    {{child2}}----

    {{count}}

    <button @click="getCount">增加</button>

    <button @click="reduce">减少</button>

  </div>

</template>

<script>

import { mapActionsmapMutationsmapState } from "vuex";

export default {

  props: ["child2"],

  data() {

    return {

      name: ""

    };

  },

  created() {

    this.$root.Bus.$on("sendName"value => {

      this.print(value);

    });

    this.getCountRet();

  },

  computed: {

      // ...mapState(模块名,[属性名]);

    ...mapState("Test", ["count"])

  },

  methods: {

      // 要使用哪个模块的什么方法

    ...mapActions("Test", ["getCountRet""getCountRet2"]),


    getCount() {

      this.getCountRet();

    },

    reduce() {

      this.getCountRet2();

    },

    print(v) {

      this.name = v.name;

    }

  },

  beforeDestroy() {

    this.$root.Bus.$off("sendName");

  }

};

</script>

<style scoped>

</style>

child代码: 

<template>

  <div>

    <h4 @click="showMsg">{{msg}}--------{{count}}</h4>

    <div class="item" v-for="(v,iin list" :key="i">

      我是{{v.name}}

      <button @click="sendInfo(v)">点击发送</button>

    </div>

  </div>

</template>

<script>

import { mapActionsmapMutationsmapState } from "vuex";

export default {

  props: ["msg""list"],

  mounted() {},

  computed: {

    ...mapState("Test", ["count"])

  },

  methods: {

    ...mapActions("Test", ["getCountRet"]),

    showMsg() {

      this.$emit("getMessage""这是父组件");

    },

    sendInfo(v) {

      this.$emit("showInfo"v);

      this.$root.Bus.$emit("sendName"v);

    }

  }

};

</script>

<style scoped>

.item {

  margin-top10px;

}

</style>

在test.js的muations中有两个方法,在actions中提交。

在child2组件中通过

...mapState("Test", ["count"])监测属性count

...mapActions("Test", ["getCountRet""getCountRet2"]),使用getCountRet和getCountRet2方法去改变vuex中的值。

在child组件中监测{{count}}的变化。

在child2组件中通过按钮分别调用getCountRet和getCountRet2事件来控制count值的增减,child组件会随之发生变化。


以上是关于vue组件通信的主要内容,如果未能解决你的问题,请参考以下文章

Vue父子组件间通信(数据传递)

vue2组件通信之$parent/$root

VUE:组件与组件之间的通信

Vue 组件通信

vue组件间通信

Vue 非父子组件通信方案