【Vue.js】Vuex使用心得以及踩的一个坑

之前用Vue的组件传参可谓是比较麻烦且复杂的,代码也不容易维护。例如一个页面中A组件引入子组件B有没有办法声明一个全局变量达到两个组件共用呢?尤其是在用户登录方面,不同组件都需要用户的登录信息,一个个传难免影响性能——尤其是单页面中组件数目较多的时候

所以我们要使用Vuex!

什么是Vuex?

先大致看一下官方文档第一页
官方文档:https://vuex.vuejs.org/zh/

可以看到这是一个状态管理工具,简单点说就是可以帮我们管理全局变量。

官方所说:它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
意思差不多是我们让全局变量给其管理,我们对数据的操作也要遵循其规则。比如修改数据源 state、触发 actions 等等,都需要遵循它的规则,以此来达到让项目结构更加清晰且易于维护的目的。

好好看清楚

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

必须要记住的两点是:
①Vuex中的变量状态是响应式的。类似于双向绑定
②我们既然要遵循规则,我们用户和程序是无法改变Vuex中的变量的,必须通过Vuex的API来操作,该接口就是通过commit mutation来实现的

那么首先定义我们的数据源State

新建文件夹src/vuex/store.js
vuex中的数据源,我们需要保存的数据就保存在这里

//文件的作用是在整个Vue项目中声明:我们要使用Vuex进行状态管理

//引入
import  Vue from 'vue'
import  Vuex from 'vuex'

Vue.use(Vuex);

//创建Vuex实例
const store=new Vuex.Store({
     state:{
       username:"罗杰",
       level:1
       isLogin:true
     }
})

//导出store
export default store

每一个 Vuex 应用的核心就是 store(仓库)。store 基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。然后我们在main.js文件中引入该文件,再在vue实例全局引入store对象;

import store from './vuex/store.js'

new Vue({
  el: '#app',
  router,
  store,// 在vue实例全局引入store对象
  components: { App },
  template: '<App/>'
})store.js'

可以在页面通过 this.$store.state.属性来获取我们定义的数据;例如在某一个Vue文件中加入

<div>{{this.$store.state.username}}的等级:LV.{{this.$store.state.level}}</div>
      <button @click="addFun()">+</button>
      <button @click="reductionFun()">-</button>

效果如下:
在这里插入图片描述

Getter

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

Getter 接受 state 作为其第一个参数:
在这里插入图片描述
调用如下

<div>距离满级还差:{{this.$store.getters.computedFull}}</div>

在这里插入图片描述

【重点】mutation和action

既然知道了使用仓库 store 中的状态数据。接下来就要说怎么操作仓库 store 中的状态数据

明白一点,按照规则只有 mutation 能动 State

两者区别

1、流程顺序

“相应视图—>修改State”拆分成两部分,视图触发Action,Action再触发Mutation。

2、角色定位

基于流程顺序,二者扮演不同的角色。

Mutation:专注于修改State,理论上是修改State的唯一途径

Action:业务代码、异步请求。

3、限制

角色不同,二者有不同的限制。

1.同步函数:当一个函数同步调用时,该函数不会被调用时不会立即返回,直到该函数所要做的事情全部做完了才返回
2.异步函数:当一个异步函数被调用时,该函数会立即返回,尽管这个函数规定的操作任务还没有完成

**Mutation:**必须同步执行。

**Action:**可以异步,但不能直接操作State。

在这里插入图片描述
代码添加如下:

//创建Vuex实例
const store=new Vuex.Store({
     state:{
       username:"罗杰",
       level:1
     },
     getters:{//类似于Vue的computed
       computedFull:function(state){
         return 100-state.level
       }
     },
     /*************************************************************/
     mutations:{

       add(state){//上面定义的state
         state.level=state.level+1
       },

       reduction(state,n){//传参数,减多少级
         state.level=state.level-n
       }

     },
     //*********************************************************/
     actions:{//注册action,类似于Vue里的mothods
       addFun(context){
         //接收一个与store实例具有相同方法的属性得到context对象
         context.commit("add")
       },

       reductionFun(context,n){
         context.commit("reduction",n)
       }
     }

})

然后用户界面添加方法,用户操作调用

  <div>{{this.$store.state.username}}的等级:LV.{{this.$store.state.level}}</div>
  <div>距离满级还差:{{this.$store.getters.computedFull}}级</div>

  <button @click="addFun()">+</button>
  <button @click="reductionFun()">-</button>
methods:{
  addFun(){
    this.$store.dispatch("addFun")//一次加1级
  },
  reductionFun(){
     this.$store.dispatch("reductionFun",3)//一次减3级
  }

【坑】多页面共用一个store?

既然是全局变量,是不是就意味着我在A页面改变了,B页面中显示也会被改变this.$store.state.level的值?
当然不会!看是否共用一个store主要是看是否是同一个Vue实例。网上好多博客没说清楚,属实是一个坑,挣扎了好久折腾。

Vuex的应用不是针对多页面,而是为了解决组件的传值问题。现在我举个栗子,我弄了3个Vue界面
A界面修改state,然后跳转到B,而C是B的子组件。
按照以往我们要路由跳转传参,然后父子组件传参

你可能会理解这里是两个独立的页面,但并不是,他们是基于同一个Vue实例的,所以是共享store,不需要传参操作。可以看this
在A、B的created钩子函数console.log(this),通过查看uid判断是否是同一个vue实例
从A跳到B,如果打印了两次,说明是new了两个实例,如果只打印一次this,说明是并没有创建新的Vue实例
在这里插入图片描述
通过this.$router.push({name:'Login'});跳转到B页面(name:Login)

跳转后发现仍然可以读取store目前的值
在这里插入图片描述
B是页面,然后C组件是头像框,BC和A共享了store 的state
打印台并没有打印新的this,所以判断是三者共享。

如果你单独打开A和B,则不论你在A里怎么修改都不会影响到B\C,因为不属于同一个Vue实例自然也无法共享。主要就是看组件挂载情况,不是看页面数量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值