欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-04-02 23:04:27
...

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

这是本人的第一篇博客 哈哈哈哈哈哈哈哈写的好或不好 请谅解喔~
vue面试题:谈谈你对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的数据传递流程,如下图所示:
    vue面试题:谈谈你对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>

这时候我们就能在页面中看到
vue面试题:谈谈你对vuex的理解
就是这样用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在组件中怎么使用了吧~
让我们看一下效果⑧
vue面试题:谈谈你对vuex的理解
下面是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等
如有错误 请各位大神多多指教喔~
我们下期博客见!

相关标签: vue.js Vuex