Menu

Vue重点知识总结—Vuex篇

1.vuex是什么?怎么使用?哪种功能场景使用它?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单来说就是:应用遇到多个组件共享状态时,使用vuex。

文档:https://vuex.vuejs.org/zh/

场景:多个组件共享数据或者是跨组件传递数据时

原理:实际上是通过实例化Vue来实现

流程(工作原理):页面通过mapAction异步提交事件到action。action通过commit把对应参数同步提交到mutation,mutation会修改state中对应的值。最后通过getter把对应值跑出去,在页面的计算属性中,通过,mapGetter来动态获取state中的值。(单向数据流,便于管控)

Vue重点知识总结—Vuex篇

2.vuex有哪几种属性

有五种,分别是State , Getter , Mutation , Action , Module

  1. state:vuex的基本数据,用来存储变量
  2. geeter:从基本数据(state)派生的数据,相当于state的计算属性
  3. mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。
  4. action:和mutation的功能大致相同,不同之处在于 ==》1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。
  5. modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

4.异步请求代码应该写在组件的methods中还是vuex的actions中?

一、如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。

二、如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。

5.mutation中能放异步操作吗?为什么?

最好不要。但不会报错。会造成状态改变的不可追踪。异步操作通过 Action 来提交 mutation实现,这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

这个只是规范,而不是逻辑的不允许,是为了让devtool工具能够追踪数据变化,另外方便我们更好的处理数据逻辑。

6.Vuex中actions和mutations的区别

Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。

const store = createStore({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})

Action 类似于 mutation,不同在于:

  1. Action 需要提交 mutation去变更状态,而不是直接变更状态。
  2. Action 可以包含任意异步操作。
  3. mutation是同步更新数据(内部会进行是否异步检测,严格模式会报错,实现检测方法是通过$watch)
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

7. commit和dispatch,这两个有什么作用呢?

类似与在vue中通过click事件,触发methods中的方法。

当存在异步时,在vuex中需要dispatch来触发actions中的方法,actions中的commit可以触发mutations中的方法。

同步,则直接在组件中commit触发vuex中mutations中的方法。

通过this.$store.state.属性 的⽅法来访问状态。

通过this.$store.commit(‘mutation中的⽅法’) 来修改状态。

8.双向绑定和vuex是否冲突?

当在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 v-model 会比较棘手。因为双向绑定修改状态时没有通过 mutation 函数, 这里会抛出一个错误。

9.Vuex可以直接修改state的值吗?

可以直接修改,但是极其不推荐。

当我们将vuex的模式改成严格模式的时候,我们在通过直接修改state的方式修改状态的时候,控制台会报错。

state的修改必须在mutation来修改,否则⽆法被devtool所监测,⽆法监测数据的来源,⽆法保存状态快照,也就⽆法实现时间漫游、回滚之类的操作。

简单来说,就是使用commit来更改状态主要是为了状态能够很好的跟踪,开发者工具更好的处理状态变化,更好的调试体验。

10.什么情况下使⽤ Vuex?

如果应⽤够简单,最好不要使⽤Vuex ,⼀个简单的 Event Bus 就可实现跨组件通信(公共的vue实例)。

//使用中间vue实例实现子-子通信

//mid
Vue.prototype.$bus = new Vue()

//某子组件发消息
//....
methods: {
    tellname () {
       // 发出事件,传递数据,givename自定义事件
     this.$bus.$emit('givename', this.mybfname) 
  } 
}

//某子组件收消息

// 组件一加载就进行兄弟组件所发出的事件的监听
created () {
    // vm.$on(vue自定义的事件, 处理函数)
    // 处理函数有一个默认参数,就是其它组件所传递的数据
    this.$bus.$on('givename', (data) => {
      console.log(data);
      this.mysbfname = data
    })
}

需要构建⼀个中⼤型单页应⽤时,使⽤Vuex能更好地在组件外部管理状态。

11.页面刷新后Vuex的state数据丢失怎么办?

Vuex只是在页面内存中保存状态,页面刷新后是必然会丢失状态。

当然可以使用localStoragesessionStoragecookie进行存储。我们一般使用localStorage做持久化(Cookie、sessionStorage、localStorage的区别

初始化state数据时可以直接从localStorage中获取备用值,但是需要每次在修改状态时使用localStorage.setItem(key,val)保存最新值,这样感觉不太优雅。

// 初始化
const store = createStore({
    state(){
        return {
            count: localStorage.getItem('count')
        }
    },
    mutations: {
        // 更新值
        updateCount(state, value){
            state.count++
            localStorage.setItem('count',state.count)
        }

    }
})

// 或者在调用时手动更新值
store.commit('updateCount')
localStorage.setItem('count', store.state.count)

存在问题:

  1. 不是所有的状态都需要持久化,所以需要区别对待,有一定心智负担。
  2. 如果需要保存的状态很多,每次手动重设缓存就比较繁琐,不够优雅。

解决方式:

1) 使用Vuex提供的Api –> subscribe做统一处理。(订阅 store 的 mutation。handler 会在每个 mutation 完成后调用,接收 mutation 和经过 mutation 后的状态作为参数),可以将处理函数封装为插件。

const unsubscribe = store.subscribe((mutation, state) => {
  console.log(mutation.type)
  console.log(mutation.payload)
  if(mutation.type==='updateCount'){
    localStorage.setItem('count', state.count)
  }
})

// 你可以调用 unsubscribe 来停止订阅。
unsubscribe()

// 封装为插件
const myPlugin = (store) => {
  // 当 store 初始化后调用
  store.subscribe((mutation, state) => {
    // 每次 mutation 之后调用
    // mutation 的格式为 { type, payload }
  })
}
// 使用插件
const store = createStore({
  // ...
  plugins: [myPlugin]
})

2) 可以使用开源的插件进行持久化,原理同上。插件如 vuex-persist、vuex-persistedstate等。

12.Vuex的缺点

Vuex 可以集中组件的公共状态,利用响应式,很方便我们做开发。但模块化这一块做得比较复杂,使用不是很方便,需要经常看文档去回顾。

另外,如果不打算开发⼤型应⽤,使⽤Vuex可能是繁琐冗余的。Vuex是重量级的,对性能有一些影响。换句话说,Vuex其实不适合中小型应用。

1)模块使用比较繁琐,获取状态模式不统一,复杂度较高,增加心智负担,容易出错

// 使用插件
const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})
// 使用
store.state.b // -> moduleB 的状态
store.state.a  // 要带上 moduleA 的 key(.a) ,内嵌模块的话会很长,代码阅读性不佳,不得不配合 mapState 使用
store.getters.c  // moduleA 里的 getters ,没有 namespaced: true 时又变成了全局的
store.getters['a/c']  // namespaced: true 时需要加 path
store.commit('d')  // 没有 namespaced 时又是全局的
store.commit('a/d')  // namespaced: true 时也需要加 path,要使用mapMutations 的话也比较麻烦

2)对TS的支持不太友好,没有友好的类型支持和提示

虽然Vuex在后期版本通过定义类型化的 InjectionKey 使得类型支持有所改善,但使用会很不优雅。

3)体积较大,重量级,小型项目对性能有一定影响。

如今团队又推出了新一代的状态管理插件:Pinia,它使用 Vue 3 中的新反应系统来构建一个直观且完全类型化的状态管理库。其库容量和性能要优于Vuex。而且完全支持Ts。

Pinia是Vuex的良好替代品吗?

本文固定连接:https://code.zuifengyun.com/2020/06/1631.html,转载须征得作者授权。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

¥ 打赏支持