Vue组件间通信:Props、$emit和Vuex

117 阅读3分钟

今天的主题是vue组件间通信,闲话不多说,我们直接进入主题。

父 -> 子组件通信

父组件要传值给子组件的话,假设示例(options API)中的父组件是App.vue,子组件是List.vue

  1. 首先,在父组件中子组件标签上v-bind绑定一个属性用于传值
<template>
  <List :lists="list" /> // v-bind绑定属性lists用于传值,值是数据源中的list
</template>

<script>
import List from './components/List.vue';
  export default {
    components: {
      List,
    },
    data() {
      return {
        list: []
      }
    },
  }
</script>
  1. 然后,在子组件中通过props接收这个属性
<script>
export default {
    props: ['lists']
}
</script>

这样就完成了父组件传值给子组件,注意我们无法修改props中的值,数据流是单向的。

子 -> 父组件通信

话不多说,直接上例子,实例中父组件是App.vue,子组件是Add.vue

  1. 首先,在子组件通过this.$emit('事件名',参数)方法生成一个事件
<template>
    <div class="head">
        <input type="text" v-model="message">
        <button @click="add">添加</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            message: '',
        }
    },
    methods: {
        add() {
            this.$emit('add', this.message); // 生成一个add事件,并将message作为参数传入
            this.put = '';
        }
    }
}
</script>
  1. 然后,父组件通过v-on监听这个事件,当事件触发时,其中的参数会传给父组件
<template>
  <Add @add="handle" /> // 父组件通过v-on监听这个事件
</template>

<script>
import Add from './components/Add.vue';
  export default {
    components: {
      Add
    },
    methods: {
      handle(data) {     触发时,参数传入
        console.log(data);
        this.list.push(data);
      }
    }
  }
</script>

任意组件通信

要想实现任意组件的通信,最好的方法就是引入一个仓库,大家都把数据放入仓库,需要的时候都去向仓库取数据,这样就可以实现任意组件的通信了。这里我们将接收一个新的东西-vuex,它可以帮我们创建一个仓库。

仓库的创建

  1. 首先,我们在终端输入:npm install vuex@next --saveyarn add vuex@next --save 下载依赖(官方文档可以找到)
  2. 然后我们在vue项目的src文件夹下创建一个文件夹,在这个文件夹中创建一个js文件用于创建仓库
import { createStore } from 'vuex'

const store = createStore({

})
export default store
  1. 在main.js中导入并使用
import store from './store'
createApp(App).use(store).mount('#app')

仓库的使用

假设仓库已经有了这么一些数据

import { createStore } from 'vuex'

const store = createStore({
    state: {
        lists: ['html', 'css'] 
    },
    mutations: {
        add(state, val) {
            state.lists.push(val)
        }
    }
})
export default store
  1. 我们可以在组件中导入mapState方法来获取仓库的数据
<script>
import { mapState } from 'vuex'; // 导入mapState
export default {
    computed: {
        ...mapState(['lists'])  // 调用mapState,获取仓库中的lists数组
    }
}
</script>
  1. 同样,我们在组件中导入并使用mapMutations来将组件的数据存入仓库
<script>
import { mapMutations } from 'vuex' // 导入mapMutations
export default {
    data() {
        return {
            message: '',
        }
    },
    methods: {
        ...mapMutations(['add']), // 将 'add' mutation 映射为组件的一个方法
        submit() { 
            this.$store.commit('add', this.message)  // 提交状态变更
        }
    }
}
</script>
// 也就是把组件中的message的值放入仓库当中,这里具体来说是放入仓库中的lists数组中。

小结

使用props可以将数据从父组件传递给子组件,而emit可以在子组件中触发事件,并将数据传递给父组件。通过Vuex可以创建一个仓库来存储共享数据,组件可以通过mapState获取仓库中的数据,通过mapMutations提交状态变更。这样就可以实现灵活而高效的组件通信。