Vuex

739 阅读4分钟

组件之间共享数据的方式

  • 父向子 使用属性绑定传值 v-bind

  • 子向父 使用事件绑定传值 v-on

  • 兄弟组件之间共享数据 :Event Bus

    • $on 接收数据 的那个组件

    • $emit 发送数据的哪个组件

Vuex是什么

vuex是专为vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,可以更方便的实现组件之间的数据共享。

image-20210704212054131

使用Vuex管理数据的优点

  • 能够在Vue中集中管理共享数据 ,便于开发和有利于后期的维护
  • 能够实现组件之间的数据共享,提高开发效率
  • 存储在Vuex的数据是响应式的,只要数据发生改变,页面中的数据也会同步更新。

使用Vuex的场景

  • 一般情况下,只有数组之间共享的数据 ,才有必要存储在Vuex中
  • 组件的私有数据,存储在自身组件 的data中

Vuex的基本使用

  • 安装 方案一
  1. npm安装 Vuex依赖包

    npm install vauex --save 
    
  2. 导入 Vuex 包

    import Vuex from "vuex"
    Vue.use(Vuex) //挂载到vue上
    
  3. 创建store 对象

    const store=new Vuex.Store({
      //state中存放的就是全局共享的数据
       state:{count:0}
    })
    

    4.将store对象挂载到 Vue实例中

  • new Vue({
     el:"#app",
     render:h=>(app),
     router,
     //所有组件,就可以直接从store中获取全局的数据 
     store
    })
    
  • 安装 方案二

  1. 打开终端,输入命令:vue ui

  2. 创建项目,设置项目名称和包管理器

    创建vuex项目01

  3. 设置手动配置项目

    创建vuex项目02

  4. 设置功能项

    创建vuex项目03

  5. 标准配置 、创建项目。

    创建vuex项目05

Vuex中的核心特性

State (数据)

  • 组件 访问State中数据 的方式 一

State提供唯一的公共数据源,所有共享的数据都要统一放到State中进行存储

//创建 store数据源,提供唯一公共数据
const store= new Vuex.Store({
    state:{ count:0 }
})
//组件中的插值表达式中访问State中数据的第一种方式
this.$store.state.全局数据名称
  • 组件访问State中数据的方式二
// 从vuex中按需导入mapState函数
import {mapState} from 'vuex'

//通过刚才导入的mapState函数,将当前组件需要的全局数据,映射为当前组件的computed 计算属性
  computed:{
   ...mapState(['count']) //使用扩展运算符... 可使 mapState映射成当前组件的计算属性
  }

Mutation (方法)

Mutation 里不能执行 异步任务 异步任务需要使用Action

  • Mutation用于变更Store中的数据 (方式一)
    • 只能通过Mutation变更Store数据,不可以直接操作Store中的数据
    • 通过这种方式虽然 操作起来稍微繁琐一些,但是可以集中监控所有数据的变化
    • 在组件的methods中使用 this.$store.commit 可获取mutation的方法
    • 可在触发mutation时传递参数
    <script>
       //Store.vue文件中定义Mutation
     const store=new Vuex.Store({
       state:{
         count:0
       },
       mutations:{
           //只改变数据,不会传参
         add(state){
          //变更状态
          state.count++
         },
         //触发mutation时传递参数 step
         addN(state,step){
          // 变更数据 
          state.count+=step
        } 
       }
     })
     <script>
    
    
     <script>
    //在组件中使用  触发Mutation
      methods:{
        handle1(){
       //commit用于触发mutation的某个函数
        this.$store.commit("add") 
        }
        handle2(){
         //commit用于触发mutation函数时并携带参数
         this.$store.commit("addN",3)
        }
      }
    <script>
    
  • 触发mutation的第方式二
    • 从Vuex中按需导入 mapMutations函数

      //从vuex中按需导入mapMutations函数 
       import {mapMutations} from "vuex"
      
    • 通过刚导入的mapMutations函数,将需要的mutations函数,映射为当前组件的methods方法

      使用... 扩展运算符 同样可以传递参数

      <script>
      //在组件中将mutations函数,映射为当前组件的methods函数
      methods:{
         ...mapMutations(["add","addN"])  //add,与addN为mutation的方法
         handle1(){
           this.add() //使用mutation中的add方法
          },
         handle2(){
          this.addN(3) //使用mutation中的addN方法 并传递参数 3
         }
      }
      <script>
      

Action(执行异步任务)

Action用于处理异步任务

  • 触发Action异步任务 方式一
    • 操作异步变更数据,必须通过Action,而不能使用Mutation,但是在Action中必须通过触发Mutation的方式间接变更数据
    • 在组件中使用this.$store.dispatch(“方法名”) 触发 Action
<script>
// 在store.vue文件中
const store=new Vuex.store({
   state:{
     count:0
   },
  mutations:{
    add(state){
      state.count++
    },
    addN(state){
      state.count++
    }
  },
  actions:{    //actions处理异步操作
    addAsync(context){
     setTimeout(()=>{
       context.commit("add") //commit触发mutation的add方法
      },1000)
    },
    addNAsync(context,step){
      setTimeout(()=>{
        context.commit("addN",step)//commit触发mutation的addN并携带 参数step
      },1000)
    }
  }
})
<script>
<script>
//在组件中使用  触发Action
methods:{
  handle1(){
    //触发actions的第一种方式
     this.$store.dispatch("addAsync")
   },
  handle2(){
     //dispatch触发 actions的异步 并携带参数
      this.$store.dispatch("addNAsync",5)
   }
 }
<script>
  • 触发 Action异步任务 方式二

    • ...mapActions(”方法名“) 是触发Action的第二种方式

      // 从vuex 中按需导入 mapActions函数
       import mapActions from "vuex"
      
    • 通过刚导入的mapActions函数,将需要的actions函数,映射为当前组件的methods方法

      <script>
      //将指定的 actions函数,映射为当前组件的 methodes 函数 
      methods{
       ...mapActions(["add","addN"])
         handle1(){
           this.add() //使用mutation中的add方法
          },
         handle2(){
          this.addN(3) //使用mutation中的addN方法 并传递参数 3
         }
      }
      <script>
      

Getter (处理形成新数据)

  • Getter用于对Store中的数据进行加工处理形成新的数据,类似Vue的计算属性

  • Store的数据发生改变,Getter的数据也会发生改变

    <script>
    // 在store文件中 定义 Getter
     const store= new Vuex.Store({
         state:{
           count:0
        },
        getters:{
        // 定义了showNum函数 
         showNum:state=>{
            return:"当前最新的数据是 ‘+state.count+’ "
          } 
        }
     })
    <script> 
    
  • 在组件中使用 getters的第一种方式:

    this.$store.getters.函数名称
    
  • 使用getters的第二种方式 。映射 ....

  • 注意 需要在computed的计算属性中使用

    import {mapGetters} from "Vuex"
    computed:{
      ...mapGetters({"showNum"})
     }
    

module(分割成模块)

应用场景:当项目变得非常复杂时,store ,mutation,action,getter。就有可能变得相当臃肿。而modules分割成模块方便于管理

  • 全局定义

    //全局定义  moduleA和moduleB模块最后在modules注册
    const moduleA = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    ​
    const moduleB = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... }
    }
    ​
    const store = createStore({
      modules: {
        a: moduleA,
        b: moduleB
      }
    })
    ​
    store.state.a // -> moduleA 的状态
    store.state.b // -> moduleB 的状态
    
  • 模块命名

    注意不要在不同的,无命名空间的模块中定义两个相同的getter从而导致冲突

    • 添加 namespaced: true 的方式使其成为带命名的模块,从而模块具有更高的复用性和封装度

    • 当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。例如: commit('account/login')

      const store = createStore({
        modules: {
      //父模块
          account: {
            namespaced: true,
      ​
            // 模块内容(module assets)
            state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
            getters: {
              isAdmin () { ... } // -> getters['account/isAdmin']
            },
            actions: {
              login () { ... } // -> dispatch('account/login')
            },
            mutations: {
              login () { ... } // -> commit('account/login')
            },
      ​
            // 嵌套模块
            modules: {
              // 继承父模块的命名空间 
              myPage: {
                state: () => ({ ... }),
                getters: {
                  profile () { ... } // -> getters['account/profile']
                }
              },
      ​
              // 进一步嵌套命名空间
              posts: {
                namespaced: true,
      ​
                state: () => ({ ... }),
                getters: {
                  popular () { ... } // -> getters['account/posts/popular']
                }
              }
            }
          }
        }
      })
      

访问数据和修改数据的调整

  • 访问模块中的数据,要加上模块名

    获取数据项:  {{$store.state.模块名.数据项名}}
    获取getters: {{$store.getters['模块名/getters名']}}
    
  • 访问模块中的mutations/actions:

    • 如果namespaced为true,则需要额外去补充模块名
    • 如果namespaced为false,则不需要额外补充模块名
    $store.commit('mutations名')        // namespaced为false
    $store.commit('模块名/mutations名')  // namespaced为true
    

「点赞、收藏和评论」

❤️关注+点赞+收藏+评论+转发❤️,鼓励笔者创作更好的文章,谢谢🙏大家。