vue组件间的通讯

vue组件间通讯主要有两种,一种使用事件总线的方式,两种是使用外部状态管理器vuex。这种方式的缺点就是不适合开发大型的应用,主要工作原理是使用事件,当应用逐渐长大,开发人员越来越多,定义的事件名称就会可能出现重复,导致应用不能正常工作,通常构建大型应用不建议使用这种通讯方式,适合个人短期的小应用,其优点就是简单,快速构建应用

3 min read
By myfreax
vue组件间的通讯

vue组件间通讯主要有两种,一种使用事件总线的方式,两种是使用外部状态管理器vuex

事件总线

这种方式的缺点就是不适合开发大型的应用,主要工作原理是使用事件,当应用逐渐长大,开发人员越来越多,定义的事件名称就会可能出现重复,导致应用不能正常工作,通常构建大型应用不建议使用这种通讯方式,适合个人短期的小应用,其优点就是简单,快速构建应用

Bus
创建事件总线中介

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

Items

<template>
  <div>
    <ul>
      <li v-for="item in items">{{item.content}}</li>
    </ul>
  </div>
</template>

<script>
  import bus from '../Bus'
  export default {
    name: 'items',
    created() {
      //在组件的created钩子创建监听器,items发生变化时更新dom
      bus.$on('AddTodo',(item) =>{
        this.items.push({content:item});
      })
    },
    methods: {
    },

    data: () => {
      return {items: []}
    }
  }
</script>

Headers

<template>
  <form>
    <input type="text" v-model="item"/>
    <button v-on:click="addTodo">Add</button>
  </form>
</template>

<script>
  import bus from '../Bus'
  export default {
    name: 'headers',
    data:() => {
    	return {
    		item:''
      }
    },
    methods:{
    	addTodo(e){
    	  if (this.item){
            //当用户点击Add时触发AddTodo
            bus.$emit('AddTodo', this.item);
        }
        e.preventDefault();
      }
    }
  }
</script>

vuex

vuex与事件总线相比,vuex相对较为复杂,带来很多新概念,比如state,action,getters等等,但在大型项目中应该无疑首选的,它让应用可以保持单向数的据流

store/index.js

// @flow
import Vue from 'vue'
import Vuex from 'vuex'
import createLogger from 'vuex/dist/logger'

Vue.use(Vuex); //加载store

export default  new Vuex.Store({
 plugins: [createLogger()],//非常有用的调试工具,与Redux的log中间件类似
  //初始化的状态
  state:{
    items:[]
  },
  //用于定义从state中派生出一些状态
  getters:{
    doneTodosCount(state){
      return state.items;
    }
  },
  actions:{
    //异步逻辑都应该封装到这里里。

  },
  mutations:{
    //提交 mutation 是更改状态的唯一方法,并且这个过程是同步的
    addTodo(state,item){
      state.items.push({content:item});
    }
  }
})

app.js

import Vue from 'vue'
import App from './App'
import store from './store'
import router from './router'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store, //store instanceof vuex
  template: '<App/>',
  components: { App }
});

Headers

<template>
  <form>
    <div>
      <input type="text" v-model="item"/>
      <button @click="addTodo(item)">Add</button>
    </div>
  </form>
</template>

<script>
  import {mapMutations} from 'vuex'
  export default {
    name: 'headers',
    data:() => {
    	return {
    		item:'',
        keyword:''
      }
    },
    //相当于提交Mutation
    /*methods:{
      addTodo(){
        this.$store.commit('addTodo', this.item)
      }
    },*/
    methods: mapMutations([
      'addTodo','search'
    ]),
  }
</script>

items

<template>
  <div>
    <ul>
      <li v-for="item in items">{{item.content}}</li>
    </ul>
  </div>
</template>

<script>
  import {mapState,mapGetters} from 'vuex';

  export default {
    name: 'items',
    /**
     * 计算属性,当数据更新时触发组件更新
     */
    computed: {
     ...mapState([
        // 映射 this.items 为 store.state.items
        'items'
      ])
    }
  }
</script>