vue面试题:谈谈你对vuex的理解

面试题:谈谈你对vuex的理解 在这里插入图片描述

当面试官问我们对vuex的理解的时候,我们不能只说“vuex是一个专为vue.js应用程序开发的状态管理模式”,尽量不要让面试官连续追问(总会问到自己不会的然后说你实力还差那么点来可以得降薪),应该从这几个方面一次性去说清楚:
1.为什么要用vuex?
2. 什么是vuex?
3. 怎么用vuex(五大核心属性概念,应用…)

一、为什么要用vuex?

在大型复杂的项目中(多级组件嵌套),需要实现一个组件更改某个数据,多个组件自动获取更改后的数据进行业务逻辑处理,这时候使用vuex比较合适。假如只是多个组件间传递数据,使用vuex未免有点大材小用,其实只用使用组件间常用的通信方法即可 。
那么怎么安装使用vuex呢?
1.首先 安装vuex
cnpm install vuex -save
2. 在src目录下创建store文件夹
3. 在store文件夹内创建index.js文件
4. 在index.js 文件内引入 vue 和注册vuex
import Vue from “vue”
import Vuex from “vuex”
5.对vuex进行实例化 并导出
const store = new Vuex({
核心配置
})
export default store
6. 将store配置到vue实例中

new Vue({
        router,
        store,
        render: h => h(App)
    })

二、什么是vuex?

Vuex是专门为Vue服务,用于管理页面的数据状态、提供统一数据操作的生态系统,相当于数据库mongoDB,MySQL等,任何组件都可以存取仓库中的数据。

理解性(可读)

Vuex采用MVC模式中的Model层,规定所有的数据必须通过action—>mutaion—>state这个流程进行来改变状态的。再结合Vue的数据视图双向绑定实现页面的更新。统一页面状态管理,可以让复杂的组件交互变的简单清晰,同时在调试时也可以通过DEVtools去查看状态。

在当前前端的spa模块化项目中不可避免的是某些变量需要在全局范围内引用,此时父子组件的传值,子父组件间的传值,兄弟组件间的传值成了我们需要解决的问题。虽然vue中提供了props(父传子)commit(子传父)兄弟间也可以用localstorage和sessionstorage。但是这种方式在项目开发中带来的问题比他解决的问题(难管理,难维护,代码复杂,安全性低)更多。vuex的诞生也是为了解决这些问题,从而大大提高我们vue项目的开发效率

三、怎么用vuex?

vuex五大核心属性:state,getter,mutation,action,module

  1. state:存储数据,存储状态;在根实例中注册了store 后,用 this.$store.state 来访问;对应vue里面的data;存放数据方式为响应式,vue组件从store中读取数据,如数据发生变化,组件也会对应的更新。
  2. getters:可以认为是 store 的计算属性,它的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
  3. mutation:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
  4. action:包含任意异步操作,通过提交 mutation 间接更变状态。
  5. module:将 store 分割成模块,每个模块都具有state、mutation、action、getter、甚至是嵌套子模块。
    对于vuex的数据传递流程,如下图所示:
    在这里插入图片描述
    关于state
import Vuex from 'vuex'

Vue.use(Vuex)

const state = {
   count: 0
}

export default new Vuex.Store({
   state
})

我们在store里定义了count,该怎么在组件里去用呢?

  <div class="hello">
    <h3>{{$store.state.count}}</h3>
  </div>
</template>

这时候我们就能在页面中看到
在这里插入图片描述
就是这样用state啦~下面是mutations怎么用 其实他就像组件里的methods 能够对state状态进行修改

 * mutations 里面放置的是我们操作state对象属性的方法
 */
const mutations = {
    mutationsAddCount(state, n = 0) {
        return (state.count += n)
    },
    mutationsReduceCount(state, n = 0) {
        return (state.count -= n)
    }
}
export default new Vuex.Store({
    state,
    mutations
})

我们在mutations写了两个修改状态的方法

  <div class="hello">
    <h3>{{$store.state.count}}</h3>
    <div>
      <button @click="handleAddClick(10)">增加</button>
      <button @click="handleReduceClick(10)">减少</button>
    </div>
  </div>
</template>
    handleAddClick(n){
      this.$store.commit('mutationsAddCount',n);
    },
    handleReduceClick(n){
      this.$store.commit('mutationsReduceCount',n);
    }
  }

相信这样大家就能看懂mutations在组件中怎么使用了吧~
让我们看一下效果⑧
在这里插入图片描述
下面是actions的使用

  actionsAddCount(context, n = 0) {
      console.log(context)
      return context.commit('mutationsAddCount', n)
  },
  actionsReduceCount({ commit }, n = 0) {
      return commit('mutationsReduceCount', n)
  }
}
export default new Vuex.Store({
  state,
  mutations,
  actions
})

这里我在两个方法中使用了两个不同的参数,一个是context,它是一个和store对象具有相同对象属性的参数。在第二个函数中,我是直接使用了这个对象的commit的方法。

  <div>
    <button @click="handleActionsAdd(10)">异步增加</button>
    <button @click="handleActionsReduce(10)">异步减少</button>
  </div>
     this.$store.dispatch('actionsAddCount',n)
   },
   handleActionsReduce(n){
     this.$store.dispatch('actionsReduceCount',n)
   }

actions和mutations操作效果一样的 只不过actions是异步操作 为啥是异步呢?因为actions不能直接修改state 需要通过调用mutations里的方法来执行操作 然后我们在组件内通过this.$store.dispatch(“方法名”,要传的值)

然后就剩getters啦! 他的作用跟组件里的computed类似 下面就来使用一下吧

    getterCount(state) {
        return state.count 
    }
}
export default new Vuex.Store({
    state,
    mutations,
    actions,
    getters
})

在组件内通过 this.$store.getter.getterCount 来使用就可以啦~

最后是 modules 它可以使store变得模块化
之前的项目都是

 * mutations 里面放置的是我们操作state对象属性的方法
 */
const mutations = {
    mutationsAddCount(state, n = 0) {
        return (state.count += n)
    },
    mutationsReduceCount(state, n = 0) {
        return (state.count -= n)
    }
}
export default new Vuex.Store({
    state,
    mutations
})

都是根级别的state mutations getters 这些 这种单一的状态树,应用的所有状态都会集中在一个比较大的对象上面,随着项目需求的不断增加,状态树也会变得越来越臃肿,增加了状态树维护的复杂度,而且代码变得沉长;因此我们需要modules来为我们的状态树分隔成不同的模块,每个模块拥有自己的state,getters,mutations,actions;而且允许每个module里面嵌套子module;如下:

  state: { ... },//局部state
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

*const moduleB = {
  state: { ... },//局部state
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({state:{ ... },//全局state
  modules: {
    a: moduleA,
    b: moduleB
  }
})

需要注意的

  1. Vuex在组件中computed中使用的时候,计算属性不能和state的数据项同名(同名了也不会报错,就是获取不了数据了)
  2. 默认情况下,没有设置命名空间的时候,模块内部的 action、mutation 和 getter 是(除了state)注册在全局命名空间的(如果有重名就会报错 [vuex] duplicate getter key: [method])——这样使得多个模块能够对同一 mutation 或 action 作出响应。

解决方法是加命名空间 namespaced: true

在modules内的每个模块加入命名空间
注册到组件中

computed: {
    ...mapState('module1', {
        width: state => state.width,  // 关联, 此处的state 为 module1/state
        height: state => state.height
    })
    },
methods: {
    ...mapMutations('module1', {  // 命名空间module1
        widthAdd: 'WIDTH_ADD',  // 通过mutation-types.js
        addHeight: 'addHeight'  // 直接加在mutations上面的方法
    }),
}

3.注册完成,使用

    this.widthAdd()   // 将 `this.widthAdd()` 映射为 `this.$store.commit('module1/widthadd')`
    console.log(this.width)  // this.width已经变为commit以后的值

划分模块的好处
state更为容易管理,尤其在团队人数多的时候,自己负责自己的state,既保证store了完整的状态树,又避免了相互之间的state冲突
不管是命名,或是操作 state 都会变得更加扁平和直观

到此为止vuex就没啥压力咯
但是vuex官方给了我们一个更简单的方式来使用vuex, 也就是 {mapState, mapMutations, mapActions, mapGetters} 通过这几个辅助函数 来使用store中的state mutations actions getters等
如有错误 请各位大神多多指教喔~
我们下期博客见!

  • 2
    点赞
  • 0
    评论
  • 16
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页

打赏作者

爱敲代码的静静

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值