大前端百科全书vue专题之vuex

736 阅读5分钟

大前端百科全书,前端界的百科全书,记录前端各相关领域知识点,方便后续查阅及面试准备

  • 说一下 vuex 的原理以及自己的理解
  • 页面刷新后的vuex的state数据丢失怎么办?
  • 为什么要用 vuex 或者 Redux?
  • Vuex 的 action 和 mutation 的特性是什么?有什么区别?
  • Vuex 怎么知道 state 是通过 mutation 修改还是外部直接修改的?
  • Redux和Vuex有什么区别,说一下它们的共同思想?
  • Vuex和localStorage的区别是什么?

说一下 vuex 的原理以及自己的理解

如图示,Vuex为Vue Components建立起了一个完整的生态圈,包括开发中的API调用一环。围绕这个生态圈,简要介绍一下流程 and 各模块在核心流程中的主要功能

image.png

核心流程

① Vue Components 是我们的 vue 组件,组件会触发(dispatch)一些事件或动作,也就是图中的 Actions;

② 我们在组件中发出的动作,肯定是想获取或者改变数据的,但是在 vuex 中,数据是集中管理的,我们不能直接去更改数据,所以会把这个动作提交(Commit)到 Mutations 中;

③ 然后 Mutations 就去改变(Mutate)State 中的数据;

④ 当 State 中的数据被改变之后,就会重新渲染(Render)到 Vue Components 中去,组件展示更新后的数据,完成一个流程。

各模块在核心流程中的主要功能

Vue Components:Vue组件。HTML页面上,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。

dispatch:操作行为触发方法,是唯一能执行action的方法。

actions:操作行为处理模块。负责处理Vue Components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发。向后台API请求的操作就在这个模块中进行,包括触发其他action以及提交mutation的操作。该模块提供了Promise的封装,以支持action的链式触发。

commit:状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。

mutations:状态改变操作方法。是Vuex修改state的唯一推荐方法,其他修改方式在严格模式下将会报错。该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,以进行state的监控等。

state:页面状态管理容器对象。集中存储Vue components中data对象的零散数据,全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,利用Vue的细粒度数据响应机制来进行高效的状态更新。

getters:state对象读取方法。图中没有单独列出该模块,应该被包含在了render中,Vue Components通过该方法读取全局state对象。

页面刷新后的vuex的state数据丢失怎么办?

  • 在点击页面刷新时先将state数据保存到sessionStorage
  • beforeunload这个事件在页面刷新时先触发的
  • 选择放在app.vue这个入口组件中,这样就可以保证每次刷新页面都可以触发
export default {
  name: 'App',
  created () {
    //在页面加载时读取sessionStorage里的状态信息
    if (sessionStorage.getItem("store")) {
        this.$store.replaceState(
            Object.assign(
                {}, 
                this.$store.state,
                JSON.parse(sessionStorage.getItem("store"))
            )
        )
    } 

    //在页面刷新时将vuex里的信息保存到sessionStorage里
    window.addEventListener("beforeunload", ()=>{
        sessionStorage.setItem("store", JSON.stringify(this.$store.state))
    })
  }
}

为什么要用 vuex 或者 Redux?

由于传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力.我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝.以上的这些模式非常脆弱,通常会导致代码无法维护

所以我们需要把组件的共享状态抽取出来,以一个全局单例模式管理,在这种模式下,我们的组件树构成了一个巨大的视图,不管在树的哪个位置,任何组件都能获取状态或者触发行为

另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护.

Vuex 的 action 和 mutation 的特性是什么?有什么区别

Action

  • 一些对 State 的异步操作可放在 Action 中,并通过在 Action 中 commit Mutation 变更状态
  • Action 可通过 store.dispatch() 方法触发,或者通过 mapActions 辅助函数将 vue 组件的 methods 映射成 store.dispatch()调用

Mutation

  • 在 vuex 的严格模式下,Mutaion 是 vuex 中改变 State 的唯一途径
  • Mutation 中只能是同步操作
  • 通过 store.commit() 调用 Mutation

总结

mutations 可以直接修改 state, 但只能包含同步操作,同时,只能通过提交 commit 调用。actions 是用来触发 mutations 的,它无法直接改变 state, 它可以包含异步操作, 它只能通过 store.dispatch 触发

Vuex 怎么知道 state 是通过 mutation 修改还是外部直接修改的?

通过 $watch 监听 mutation 的 commit 函数中的 _committing 是否为 true

Vuex 中修改 state 的唯一渠道就是执行 commit('xx', payload) 方法, 其底层通过执行 this._ withCommit(fn) 设置_committing 标志变量为 true, 然后才能修改 state, 修改完毕还需要还原_committing 变量。外部修改虽然能够直接修改 state, 但是并没有修改 _committing 标志位, 所以只要 watch 一下 state, state change 时判断 _committing 值是否为 true, 即可判断修改的合法性

Redux和Vuex有什么区别,说一下它们的共同思想?

Redux和Vuex区别

  • Vuex改进了Redux中的Action和Reducer函数,以mutations变化函数取代Reducer,无需switch,只需在对应的mutation函数里改变state值就可以
  • Vuex由于Vue自动重新渲染的特性,无需订阅重新渲染函数,只要生成新的state就可以
  • Vuex数据流的顺序是: View调用 store.commit 提交对应的请求到 Store 中对应的 mutation 函数 -> store改变(vue检测到数据变化自动渲染)

通俗理解就是: Vuex弱化dispatch,通过commit进行store状态的一次变更;取消了action概念,不必传入特定的action形式进行指定变更;弱化reducer,基于 commit 参数直接对数据进行转变,使得框架更加简易

共同思想

  • 单一的数据源
  • 变化可以预测
  • 本质上: Redux和Vuex都是对MVVM思想的服务,将数据从视图中抽离的一种方案
  • 形式上: Vuex借鉴了Redux,将store作为全局的数据中心,进行数据管理

Vuex和localStorage的区别是什么?

最重要的区别

  • vuex存储在内存
  • localstorage以文件的方式存储在本地

localstorage只能存储字符串类型的数据,存储对象需要JSON的stringify和parse方法进行处理。读取内存比读取硬盘速度要快

应用场景

  • vuex是一个转为为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。vuex用域组件之间的传值
  • localstorage是本地存储,是将数据存储到浏览器的方法,一般是在跨页面传递数据时使用的
  • vuex能做到数据的响应式,localstorage不能做到

永久性

  • 刷新页面时vuex存储的值会丢失,localstorage不会丢失

很多人觉得用localstorage可以代替vuex,对于不变的数据确实可以,但是是当两个组件公用一个数据源(对象或数组)时,如果其中一个组件改变了该数据源,希望另一个组件响应该变化时,localstorage无法做到,原因在区别1那里