vue中的组件通信和vuex

组件是vue.js中最重要的一个功能,在vue中组件的实例都是相互独立的,但开发过程中组件雨组件之间的数据相互引用是必不可少,下面来阐述vue的几种通信方式

1:父组件->子组件:通过props接受父传递数据

步骤1:子通过props键来接受父传递过来的数据 props:[‘变量名1’,…,‘变量名n’]
步骤2:父传递给子 父必须在调用子的组件上通过语法 v-bind:子props中的变量名=“父data中的键”

// 声明fathertag组件
Vue.component("fathertag", {
    // 声明模型数据
    data() {
        return {
            // 调用的时候注意大小写
            sonName: "赵冠希"  
        }
    },
    // 声明组件内容
    template: `
        <fieldset>
            <legend>父组件</legend>

            <div>
                <p>我是父组件,我儿子叫:{{sonName}}</p> 
                
                <!-- 调用子组件 -->
                <sontag v-bind:myName="sonName"></sontag>
            </div>

        </fieldset>
    `,
    // 声明子组件
    components: {
        // 键就是组件标识
        sontag: {
            // 通过props键来获取父传递的数据
            props: ['myName'],
            // 这里的下props相当于下面data 
            // data() {
            //     return {
            //         // myName: 数据
            //         myName: 6666,
            //     }
            // },
            // 声明子组件内容
            template: `
                <fieldset>
                    <legend>子组件</legend>
                    <p>我是子组件,我爸爸给我取名:{{myName}}</p>
                </fieldset>
            `
        }
    }
})

2:子组件->父组件:通过$emit创建自定义事件发送数据

步骤1:子创建自定义事件 通过语法this.$emit(事件名称, 数据1, …, 数据n)
步骤2:父调用自定义事件 父在调用子组件上通过 @自定义事件名称=“函数名” 你在父定义函数接受数据即可

// 声明fathertag组件
Vue.component("fathertag", {
    // 声明模型数据
    data() {
        return {
            // 调用的时候注意大小写
            sonName: "赵冠希",
            mySonData: ""
        }
    },
    // 声明组件内容
    template: `
        <fieldset>
            <legend>父组件</legend>

            <div>
                <p>我是父组件,我儿子叫:{{sonName}}</p> 
                
                <!-- 调用子组件 -->
                <sontag @getSonData="showSonDataFn" v-bind:myName="sonName"></sontag>
                <p>
                    子的数据: {{ mySonData }}
                </p>
            </div>

        </fieldset>
    `,
    // 声明父普通函数
    methods: {
        showSonDataFn(data) {
            // console.log(data)
            this.mySonData = data
        }
    },
    // 声明子组件
    components: {
        // 键就是组件标识
        sontag: {
            // 简单理解:页面加载完毕 -> 组件渲染完毕会触发下面这个键
            mounted() {
                // 在这里面创建自定义事件
                this.$emit("getSonData", this.myName2)
            },
            // 通过props键来获取父传递的数据
            props: ['myName'],
            // 脚下留心:下props相当于下面data 
            data() {
                return {
                    // myName: 数据
                    // myName: 6666,
                    myName2: "xxxxxx"
                }
            },
            // 声明子组件内容
            template: `
                <fieldset>
                    <legend>子组件</legend>
                    <p>我是子组件,我爸爸给我取名:{{myName}}</p>
                </fieldset>
            `
        }
    }
})

3:兄弟组件:通过EventBus(事件总线)

步骤1:创建所有组件共享数据中心 const eventBus = new Vue()
步骤2:传递数据 eventBus. e m i t ( 自 定 义 事 件 名 称 , 数 据 1 , . . . , 数 据 n ) 步 骤 3 : 接 受 数 据 e v e n t B u s . emit(自定义事件名称, 数据1,...,数据n) 步骤3:接受数据 eventBus. emit(1,...,n)3eventBus.on(自定义事件名称,处理函数)

// 创建一个组件数据共享中心
const eventBus = new Vue()

Vue.component("mytag1", {
    // 声明组件模型数据
    data() {
        return {
            msg: "webopenfather",
            other: 66666
        }
    },
    // 声明组件内容
    template: `
        <fieldset>
            <legend>兄弟1</legend>
            <button @click="sendDataFn">点击传递数据</button>
        </fieldset>
    `,
    // 声明普通方法
    methods:{
        sendDataFn() {
            // 发送数据
            eventBus.$emit("mytag1MsgData", this.msg, this.other)
        }
    }
})
Vue.component("mytag2", {
    // 声明组件内容
    template: `
    <fieldset>
        <legend>兄弟2</legend>
        <p>{{data}}</p>
        <p>{{data2}}</p>
    </fieldset>
    `,
    // 声明自己的模型数据
    data() {
        return {
            data: "",
            data2: ""
        }
    },
    // 组件渲染完毕触发函数 
    mounted() {
        eventBus.$on("mytag1MsgData", (data, data2, data3) => {// 推荐写箭头函数
            console.log(data)
            console.log(data2)
            console.log(data3)
            // 将数据保存到自己的模型里面 -> 展示
            this.data = data
            this.data2 = data2
        })
    }
})

4:状态管理vuex

在实战中组件之间通信麻烦(两三个兄弟无所谓,但是n个兄弟 比较复杂),所以Vuex实现组件数据统一管理


const store = new Vuex.Store({
  // 声明仓库数据
  state: {
      // 跟其他组件定义data一样:,//
      ...
  },
  // 仓库数据过滤
  getters: {
      方法名(state) {
           +return
      },
      ...
  },
  // 更新仓库数据(这里面不允许写异步请求)
  mutations: {
  // 无参数
      get/set方法名(state) {
           
      },
  // 有参数(思考:有几个形参,根据actions调用传递的实参定)
      get/set方法名(state, data1, ..., datan) {
          state.= 异步请求数据(data1)
      }
  },
  // 更新仓库数据(这里面专门写异步请求,但是不能直接操作state 操作mutations)
  actions: {
  get/set方法名(context) {
  //不传递参数:context.commit(mutations里面的方法名)
  //传递参数: context.commit(mutations里面的方法名, 数据1,..,数据n)
 
   }
  }
})
//
//在组件中触发仓库里面数据语法
//如果在组件中调用state&getter:
computed: {
  方法名() { // 推荐方法名就是vuex.state中的键名
      return this.$store.state/getters.}

}
// 如何调用mutations
// 如何调用actions
methods: {
  方法名() {
      this.$store.commit(mutations里面方法名)
      this.$store.dispatch(actions里面的方法名)
  }
}

辅助函数

辅助函数(state):在组件computed里面写 …Vuex.mapState([键1,…,键n])
辅助函数(getters):在组件computed里面写 …Vuex.mapGetters([方法名1,…,方法名n])
辅助函数(mutations)在组件methods等其他 …Vuex.mapMutations([]或者{})
辅助函数(actions) 在组件methods等其他 …Vuex.mapActions([]或{}})
[‘mutations/action方法名里面方法名’] 注:这时候普通方法名 同 数组里面的值

{ 键就是普通方法名,值mutations/action方法名里面方法名 键:值 }

const store = new Vuex.Store({
    // 声明仓库数据
    state: { // 计算属性 this.$store.state.键
        age: 19,
        name: 'jack'
    },
    // 声明过滤的仓库数据
    getters: { // 计算属性 this.$store.getters.方法名
        username(state) {
            return 'hello2' + state.name
        }
    },
    // 声明更新仓库数据键
    mutations: { // commit
        setAge(state) {
            state.age++
        }
    },
    // 声明更新仓库数据(异步请求 -> mutations)
    actions: { // dispatch
        setAge(context) {
            context.commit('setAge')
        }
    }
})

// this.$store/$el/$data
let vm = new Vue({
    // 激活
    store,  
    el: '#app',
    data: {
    },
    computed: {
        // 推荐方法名就是vuex.state中的键
        // age() {
        //     return this.$store.state.age
        // },
        // name() {
        //     return this.$store.state.name
        // },
        // username() {
        //     return this.$store.getters.username
        // }
        ...Vuex.mapState(['age', 'name']),
        ...Vuex.mapGetters(['username'])
    },
    methods: {
        // testMutation() {
        //     this.$store.commit('setAge')
        // },
        // 下述数组里面的值 就是 vuex.mutations里面的方法名
        // 默认普通方法名就是 vuex.mutations里面的方法名
        // ...Vuex.mapMutations(['setAge']),
        ...Vuex.mapMutations({
            //前面普通方法名,后面是vuex.mutations里面的方法名
            testMutation: 'setAge'
        }),
        // testAction() {
        //     this.$store.dispatch('setAge')
        // }
        ...Vuex.mapActions({
            testAction: 'setAge'
        })
    }
})

模块化思想

store 在new vue中激活

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  // 公共的
  state
  getters
  mutations
  actions

  // 单个模块的
  modules: {
    a: moduleA,
    b: moduleB
  }
})

//调用组件中获取数据
// 它们都是在computed
...mapState({
    方法名: state => state.状态,
    方法名: state => state.moduleA.状态,
    方法名: state => state.moduleB.状态
}),
...mapGetters({
    方法名: '方法名',
    方法名: 'moduleA/方法名',
    方法名: 'moduleB/方法名'
})

// 它们都是在methods
...mapMutations({
    方法名: 'moduleA/方法名',
    方法名: 'moduleB/方法名'
}),
...mapActions({
    方法名: 'moduleA/方法名',
    方法名: 'moduleB/方法名',
})
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue3的兄弟组件通信可以使用事件总线(Event Bus)或者provide/inject来实现,而不一定需要使用Vuex。 事件总线是一个Vue实例,在App.vue或者根组件创建一个新的Vue实例,然后通过`$emit()`方法触发自定义事件,再通过`$on()`方法在另一个组件监听事件并执行相应的操作。这样,兄弟组件之间就可以通过事件总线来进行通信。 例如,创建一个事件总线实例: ``` // EventBus.js import Vue from 'vue'; export const EventBus = new Vue(); ``` 在发送组件触发自定义事件: ``` // Sender.vue <template> <button @click="sendData">发送数据</button> </template> <script> import { EventBus } from './EventBus'; export default { methods: { sendData() { EventBus.$emit('event-name', data); } } } </script> ``` 在接收组件监听事件: ``` // Receiver.vue <script> import { EventBus } from './EventBus'; export default { created() { EventBus.$on('event-name', this.handleData); }, methods: { handleData(data) { // 处理数据 } } } </script> ``` 另一种方式是使用provide/inject来实现兄弟组件通信。在发送组件的父级组件使用provide提供数据,在接收组件的父级组件使用inject注入数据,然后在接收组件就可以直接使用提供的数据。这样,兄弟组件之间就可以共享数据。 例如,在父级组件提供数据: ``` // Provider.vue <template> <child-component :data="data"></child-component> </template> <script> export default { provide() { return { data: this.data } }, data() { return { data: '需要共享的数据' } } } </script> ``` 在接收组件注入数据并使用: ``` // Injector.vue <template> <div>{{ injectedData }}</div> </template> <script> export default { inject: ['data'], computed: { injectedData() { return this.data; } } } </script> ``` 以上两种方式都可以实现兄弟组件之间的通信,选择使用哪种方式取决于项目的需求和场景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值