返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Vue组件间通信的实现方法讲解
  • 271
分享到

Vue组件间通信的实现方法讲解

Vue组件间通信Vue组件通信Vue组件数据共享 2023-01-09 12:01:47 271人浏览 薄情痞子
摘要

目录前言一、Vuex是什么二、vuex的使用三、四个重要的映射函数四、多组件数据共享五、模块化使用vuex前言 前面介绍过几种可以实现组件间通信的方式props、ref、自定义事件绑

前言

前面介绍过几种可以实现组件间通信的方式props、ref、自定义事件绑定、全局事件总线、插槽…,这些要么就是实现组件间通信只能在特定条件下使用,要么就是实现起来太复杂,今天介绍到的vuex是Vue中一款强大的插件,使用vuex后可以实现任意组件间通信,并且支持模块化管理。接下来将会围绕一个计数案例进行展开,逐步引入vuex如何使用。

核心代码:

<template>
  <div>
      <h2>目前的数值结果是:{{n}}</h2>
      <div class="container1">
          <select v-model.number="step">
              <option value="1">1</option>
              <option value="2">2</option>
              <option value="3">3</option>
          </select>
          <button @click="addNum">增加</button>
          <button @click="subNum">减少</button>
          <button @click="oddNum">偶数再加</button>
          <button @click="longTimeAdd">延迟增加</button>
      </div>
  </div>
</template>
<script>
export default {
    // eslint-disable-next-line vue/multi-Word-component-names
    name:"Counts",
    data(){
        return {
            n:0,
            step:1
        }
    },
    methods:{
        addNum(){
            this.n+=this.step
        },
        subNum(){
            this.n-=this.step
        },
        oddNum(){
            if (this.n%2==0){
                this.n+=this.step
            }
        },
        longTimeAdd(){
            setTimeout(() => {
                this.n+=this.step
            }, 1000);
        }
    }
}
</script>
<style>
.container1>*{
    margin-left: 10px; 
}
</style>

一、vuex是什么

简单点说:是一个数据仓库,用于数据存储,数据共享,可以进行数据存放与获取,并全程监视数据的动向

使用官方语言入下:

Vuex 是一个专为 vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

这个状态自管理应用包含以下几个部分:

  • 状态,驱动应用的数据源;
  • 视图,以声明方式将状态映射到视图;
  • 操作,响应在视图上的用户输入导致的状态变化。

但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

多个视图依赖于同一状态。

来自不同视图的行为需要变更同一状态。

对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。

因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!

通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。

这就是 Vuex 背后的基本思想,借鉴了 Flux、Redux 和 The Elm Architecture。与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。

vuex适用于大型单页应用的开发,如果是小型的不推荐使用。

其中vuex3适配vue2,vuex4适配vue3

vue工作原理:

vuex中主要包含三个部分

  • Actions:相当于对数据的预处理(可以在这里使用异步加载进行数据校验等)
  • Mutations (跟开发者工具关系密切)
  • State (存放数据的地方,经过校验与变换的数据都存放在这里)

vuex中的两种数据操作

  • dispatch:将数据交给Actions
  • commit:将数据交给Mutations

vuex在项目中使用

大致有两种(实质上一样):

  • 1.vuex/store.js 创建vuex文件夹,将代码放进store.js中
  • 2.store/index.js 创建store文件夹,将代码放进index.js中

安装vuex

npm i vuex

二、vuex的使用

继续从以下三个模块与两个方法讲起:

三个模块:

  • Actions:相当于对数据的预处理(可以在这里使用异步加载进行数据校验等)
  • Mutations (跟开发者工具关系密切)
  • State (存放数据的地方,经过校验与变换的数据都存放在这里)

两个方法:

  • dispatch:将数据交给Actions
  • commit:将数据交给Mutations

如果调用vuex的dispatch方法会将数据提交到Actions中的函数,此时数据并不是最终的结果,在Actions中可以对数据进行进一步加工,然后调用commit方法提交,在Actions与Mutations中定义的函数可以获取到上下文找到state对象中存储的数据。

接下来结合代码看一下vuex如何使用(这一段代码暴露出去一个可以使用的vuex对象):

import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
const actions={
    odd_Num(comtext,value){
        // 可以通过上下文comtext找到commit方法,dispatch方法
        // 可以找到state对象,并找到其中的属性
        if (comtext.state.n%2===0){
            comtext.commit("add_Num",value)
        }
    },
    long_Time_Add(comtext,value){
        setTimeout(() => {
            comtext.commit("add_Num",value)
        }, 1000);
    }
}
const mutations={
    add_Num(state,value){
        // 这里的state被称为上下文,这里可以拿到state中的数据
        // console.log(state,value)
        state.n+=value
    },
    sub_Num(state,value){
        // console.log(state,value)
        state.n-=value
    },
}
//数据源,源数据
const state={
    n:0
}
//创建一个vuex对象
export default new Vuex.Store({
    actions,
    mutations,
    state
})

以下代码是使用vuex:

main.js

import App from "./App"
//这个便是刚才封装的vuex对象
import store from "./store"
import Vue from "vue"
new Vue({
    el:"#App",
    store,
    render:h=>h(App)
})

功能性组件:

export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            step:1
        }
    },
    computed:{
        n(){
            return this.$store.state.n
        }
    }
    ,
    methods:{
        addNum(){
            this.$store.commit("add_Num",this.step)
        },
        subNum(){
            this.$store.commit("sub_Num",this.step)
        },
        oddNum(){
            this.$store.dispatch("odd_Num",this.step)
        },
        longTimeAdd(){
            this.$store.dispatch("long_Time_Add",this.step)
        }
    }
}

除此之外vuex还有一个重要的模块供我们使用getters,这里面的方法通常用于获取定制后的state中的属性

比如下面一个实例,就是将state中的n扩大10倍后返回了出去。

const getters={
    numBig(state){
        return state.n*10
    }
}

三、四个重要的映射函数

如果vuex中的函数较多时,一个一个引入会相当麻烦,官方给出了四个映射函数,可以根据自己的需求将想要的函数一下引进来,分别是:mapState,mapGetters,mapActions,mapMutations。

以下两种写法,在使用时效果是一样的

不使用映射函数:

<script>
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            step:1
        }
    },
    computed:{
        n(){
            return this.$store.state.n
        },
        bigNum(){
            // 以下两种写法均可以
            // return this.$store.getters["numBig"]
            return this.$store.getters.numBig
        }
    }
    ,
    methods:{
        addNum(){
            this.$store.commit("add_Num",this.step)
        },
        subNum(){
            this.$store.commit("sub_Num",this.step)
        },
        oddNum(){
            this.$store.dispatch("odd_Num",this.step)
        },
        longTimeAdd(){
            this.$store.dispatch("long_Time_Add",this.step)
        }
    }
}
</script>

使用映射函数:

<script>
import {mapState,mapGetters,mapActions,mapMutations} from "vuex"
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            step:1
        }
    },
    computed:{
        ...mapState(["n"]),
        ...mapGetters({bigNum:"numBig"})
    }
    ,
    methods:{
        // 传入对象是常规写法,当对象中的键值相等时,可以用传入列表的方式进行传参
        // 例如上面的mapState(["n"])
        ...mapMutations({addNum:"add_Num",subNum:"sub_Num"}),
        ...mapActions({oddNum:"odd_Num",longTimeAdd:"long_Time_Add"})
    }
}
</script>

四、多组件数据共享

经过将多个组件使用到的数据提取到vuex,可以实现多组件间的数据共享,也就是说在a组件修改共享数据之后,在b组件可以渲染出数据改变后的结果,同样b组件中修改a组件也可以渲染。

以下案例一个计数组件负责计数,一个person组件,负责将人员列表渲染出来,person组件支持增加用户,我们要做的就是person组件中进行人员添加后,计数组件感应到人数变动,重新渲染列表,将总人数进行改变。

vuex插件

import Vue from "vue"
import Vuex from "vuex"
import {nanoid} from "nanoid"
Vue.use(Vuex)
const actions={
    odd_Num(comtext,value){
        // 可以通过上下文comtext找到commit方法,dispatch方法
        // 可以找到state对象,并找到其中的属性
        if (comtext.state.n%2===0){
            comtext.commit("add_Num",value)
        }
    },
    long_Time_Add(comtext,value){
        setTimeout(() => {
            comtext.commit("add_Num",value)
        }, 1000);
    },
    add_Person(context,value){
        var someone={id:nanoid(),name:value}
        context.commit("add_Person",someone)
    }
}
const mutations={
    add_Num(state,value){
        // 这里的state被称为上下文,这里可以拿到state中的数据
        // console.log(state,value)
        state.n+=value
    },
    sub_Num(state,value){
        // console.log(state,value)
        state.n-=value
    },
    add_Person(state,value){
        state.personList.unshift(value)
    }
}
const state={
    n:0,
    personList:[
        {
            id:"0001",
            name:"张三"
        }
    ]
}
const getters={
    numBig(state){
        return state.n*10
    },
    personNum(state){
        return state.personList.length
        // console.log("index"+state.personList.length)
    }
}
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})

计数组件

<template>
  <div>
      <h2>目前的数值结果是:{{n}}</h2>
      <h2>放大后的数值结果是:{{bigNum}}</h2>
      <div class="container1">
          <select v-model.number="step">
              <option value="1">1</option>
              <option value="2">2</option>
              <option value="3">3</option>
          </select>
          <button @click="addNum(step)">增加</button>
          <button @click="subNum(step)">减少</button>
          <button @click="oddNum(step)">偶数再加</button>
          <button @click="longTimeAdd(step)">延迟增加</button>
      </div>
      <h2>当前的总人数为{{personNum}}</h2>
  </div>
</template>
<script>
import {mapState,mapGetters,mapActions,mapMutations} from "vuex"
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            step:1
        }
    },
    computed:{
        ...mapState(["n"]),
        ...mapGetters({bigNum:"numBig",personNum:"personNum"})
    }
    ,
    methods:{
        // 传入对象是常规写法,当对象中的键值相等时,可以用传入列表的方式进行传参
        // 例如上面的mapState(["n"])
        ...mapMutations({addNum:"add_Num",subNum:"sub_Num"}),
        ...mapActions({oddNum:"odd_Num",longTimeAdd:"long_Time_Add"})
    }
}
</script>
<style>
.container1>*{
    margin-left: 10px; 
}
</style>

person组件

<template>
  <div>
      <h2>目前的计算结果为{{n}}</h2>
      //监听的键盘事件,当输入enter时添加用户
      <input v-model="tempname" @keydown.enter="add_Person(tempname)">
      <ul>
          <li v-for="p in personList" :key="p.id">
              学生id:{{p.id}} 学生姓名:{{p.name}}
          </li>
      </ul>
  </div>
</template>
<script>
import {mapState,mapActions} from "vuex"
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Persons",
    data(){
        return {
            tempname:""
        }
    },
    computed:{
        ...mapState(["n","personList"])
    },
    methods:{
        ...mapActions(["add_Person"])
    }
}
</script>
<style>
</style>

五、模块化使用vuex

如果不按照数据功能对数据进行模块划分,那么vuex将会显得非常杂乱,我们希望vuex可以根据数据的不同作用将其进行模块化,便于我们管理,对于接下来的代码大家需要熟悉的是如何使用划分后的函数、函数映射。

划分后的代码大概长这个样子,其中store中的index会将count.js与person.js引入并使用。vue代码中使用vuex依旧是引入index.js,值得注意的是进行模块划分后的vuex,在使用时跟以往有了不同。详细看代码

index.js

import Vue from "vue"
import Vuex from "vuex"
import counts from "./count"
import person from "./person"
Vue.use(Vuex)
export default new Vuex.Store({
    modules:{
        counts,
        person
    }
})

count.js

// import axiOS from "axios"
export default{
    namespaced:true,
    actions:{
    
    },
    mutations:{
    
    },
    state:{
        n:0,
    },
    getters:{
        numBig(state){
            return state.n*10
        }
    }
}

person.js

import {nanoid}  from "nanoid"
export default{
    namespaced:true,
    actions:{
    
    },
    mutations:{
    
    },
    state:{
        personList:[
            {
                id:"0001",
                name:"张三"
            }
        ]
    },
    getters:{
        personNum(state){
            return state.personList.length
            // console.log("index"+state.personList.length)
        }
    }
}

count.vue

<template>
  <div>
      <h2>目前的数值结果是:{{n}}</h2>
      <h2>放大后的数值结果是:{{bigNum}}</h2>
      <div class="container1">
          <select v-model.number="step">
              <option value="1">1</option>
              <option value="2">2</option>
              <option value="3">3</option>
          </select>
          <button @click="addNum(step)">增加</button>
          <button @click="subNum(step)">减少</button>
          <button @click="oddNum(step)">偶数再加</button>
          <button @click="longTimeAdd(step)">延迟增加</button>
      </div>
      <h2>当前的总人数为{{personNum}}</h2>
  </div>
</template>
<script>
import {mapState,mapGetters,mapActions,mapMutations} from "vuex"
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            step:1
        }
    },
    computed:{
        ...mapState("counts",["n"]),
        ...mapGetters("counts",{bigNum:"numBig"}),
        ...mapGetters("person",{personNum:"personNum"})
    }
    ,
    methods:{
        // 传入对象是常规写法,当对象中的键值相等时,可以用传入列表的方式进行传参
        // 例如上面的mapState(["n"])
        ...mapMutations("counts",{addNum:"add_Num",subNum:"sub_Num"}),
        ...mapActions("counts",{oddNum:"odd_Num",longTimeAdd:"long_Time_Add"})
    }
}
</script>
<style>
.container1>*{
    margin-left: 10px; 
}
</style>

persons.vue

<template>
  <div>
      <h2>目前的计算结果为{{n}}</h2>
      <input v-model="tempname" @keydown.enter="addPerson(tempname)">
      <button v-if="tag" @click="tag=!tag">目前可增加任意姓氏</button>
      <button v-if="!tag" @click="tag=!tag">目前只可以添加王氏</button>
      <ul>
          <li v-for="p in personList" :key="p.id">
              学生id:{{p.id}} 学生姓名:{{p.name}}
          </li>
      </ul>
  </div>
</template>
<script>
import {mapState,mapActions} from "vuex"
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Persons",
    data(){
        return {
            tag:true,
            tempname:""
        }
    },
    computed:{
        ...mapState("counts",["n"]),
        ...mapState("person",["personList"])
    },
    methods:{
        ...mapActions("person",["add_Person"]),
        addPerson(){
            if (this.tempname===""){
                return ""
            }
            if(this.tag){
                // 映射出来的函数
                this.add_Person(this.tempname)
            }else{
//[Vue warn]: Error in v-on handler: "TypeError: this.addPersonWang is not a function"
// 如果没有使用映射的话,不能这样使用
// this.addPersonWang(this.tempname)
                // 正确的使用方式(使用模块命名空间进行限定)
                this.$store.dispatch("person/addPersonWang",this.tempname)
            }
            this.tempname=""
        },
    }
}
</script>
<style>
</style>

除此之外还可以通过下面方法获取到vuex中的state中的属性。

this.$store.state.模块名.属性

this.$store.state.loginModel.userInfo

到此这篇关于Vue组件间通信的实现方法讲解的文章就介绍到这了,更多相关Vue组件间通信内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Vue组件间通信的实现方法讲解

本文链接: https://lsjlt.com/news/177148.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Vue组件间通信的实现方法讲解
    目录前言一、vuex是什么二、vuex的使用三、四个重要的映射函数四、多组件数据共享五、模块化使用vuex前言 前面介绍过几种可以实现组件间通信的方式props、ref、自定义事件绑...
    99+
    2023-01-09
    Vue组件间通信 Vue组件通信 Vue组件数据共享
  • vue组件间通信全面讲解
    目录前言组件介绍一、父传子1. 父组件通过 props 传递数据给子组件2. 定义props的类型和默认值二、子传父子组件通过 $emit 传递数据给父组件三、非父子组件间数据传递1...
    99+
    2024-04-02
  • Vue组件之间的通信方式详细讲解
    目录前言一、父级传数据给子级1、传输固定的具体数据2、动态语法3、子组件调用父组件二、子级传数据给父级1、使用自定义事件2、$refs的使用3、同级别组价以及任意组件之间的数据传递前...
    99+
    2024-04-02
  • Vue如何实现组件间通信方式
    这篇文章主要介绍了Vue如何实现组件间通信方式,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。props父组件可以通过props向下传递数据给子组件静态的Props通过为子组件...
    99+
    2023-06-29
  • Vue实现组件间通信的示例
    这篇文章主要介绍了Vue实现组件间通信的示例,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1. 父子间通信最常见的就是父子之间的通信,通信是双向的数据传递。1.1 父组件 -...
    99+
    2023-06-15
  • Javascript实现Vue跨组件通信的方法详解
    目录概述思路要清晰实现要迅猛测试效果优化总结概述 我们都知道。 xxx.$on可以订阅一个消息。 xxx.$emit可以发布一个消息。 xxx.$off可以取消订阅一个消息。 思路要...
    99+
    2024-04-02
  • Vue如何实现组件间通信
    目录1. 父子间通信1.1 父组件 --> 儿子组件1.2 儿子组件 --> 父组件2. 爷孙间通信3. 任意组件间通信3.1 EventBus3.2 Vuex1. 父子...
    99+
    2024-04-02
  • vue组件间通信如何实现
    本篇内容主要讲解“vue组件间通信如何实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“vue组件间通信如何实现”吧!父组件传子组件父传子方法(一) 属性传递 props//子组件&l...
    99+
    2023-07-04
  • Vue实现组件间通信的方式有哪些
    本篇内容主要讲解“Vue实现组件间通信的方式有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue实现组件间通信的方式有哪些”吧!1、Props 父 >>> 子&...
    99+
    2023-06-25
  • Vue组件间通信的方法有哪些
    这篇“Vue组件间通信的方法有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue组件间通信的方法有哪些”文章吧。方法一...
    99+
    2023-07-05
  • vue中怎么实现组件间通信
    vue中怎么实现组件间通信,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。父组件传子组件父传子方法(一) 属性传递 props//子组件 &...
    99+
    2024-04-02
  • vue中实现组件间通信的方式有哪些
    这篇文章给大家介绍vue中实现组件间通信的方式有哪些,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。方法一、 props / $emit父组件A通过props的方式向子组件B传递,B t...
    99+
    2024-04-02
  • vue实现组件通信的八种方法实例
    目录1、props父组件--->子组件通信2、$emit子组件--->父组件传递3、bus(事件总线)兄弟组件通信4、$parent、$children直接访问组件实例5...
    99+
    2024-04-02
  • 通过实例讲解vue组件之间的传值
    目录前言1.父组件向子组件进行传值2.子组件向父组件进行传值3.非父子组件之间的传值 总结前言 目前在做vue的项目,用到了子组件依赖其父组件的数据,进行子组件的相关请求和...
    99+
    2024-04-02
  • vue父子组件间通信怎么实现
    本篇内容介绍了“vue父子组件间通信怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.父组件传递数据给子组件父组件数据如何传递给子组...
    99+
    2023-07-04
  • Vue组件间的通信方式详析
    目录前言组件之间通信的场景父子组件之间的通信父组件通过 prop 向子组件传递数据子组件通过自定义事件向父组件传递数据兄弟组件之间的通信状态提升隔代组件之间的通信attrs/attr...
    99+
    2024-04-02
  • vue组件通信的多种方法详解
    目录1. 父传子2. 子传父3. 非父子组件传值4. vuex5. refs6. $children7. $parent8. provide & inject9. $attr...
    99+
    2024-04-02
  • Vue组件之间四种通信方式详解
    目录前言父子组件通信​父组件与子孙组件的通信​父组件获取子组件数据​无需考虑组件关系的通信​前言 vue 框架提供了前端开发组件的思想,可以通过组件来组合成一个完整的页面,都是随着组...
    99+
    2024-04-02
  • Vue实现组件间通信的几种方式(多种场景)
    目录1、Props 父 >>> 子  (Props)子 >>> 父 ($emit)2、Bus事件总线3、V...
    99+
    2024-04-02
  • vue中怎么实现父子组件间通信
    这篇文章将为大家详细讲解有关vue中怎么实现父子组件间通信,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。组件间通信($parent $refs)父组件要想获...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作