很久不写文章了,断了有一年多。这期间加入了新的团队做leader,认识新的朋友,迎接新的挑战。本应该坐下来整理自己的所见与所得,但又担心是否会起到作用,是否大家会认同。就像以前有一个朋友问我写这么多入门的文章有用吗?还有一些文章好像在自说自话。

其实还真是这样,反观自己的文章,其实大部分是自己写给自己的。越长大越孤单,很多想法,很多疑问,很多心里话其实是通过文章间接的与自己沟通。换个角度审视自己的行为与思想。

我也尽可能的想通过自己的文章传达一些技术之外的东西,要明白 “授之以鱼不如授之以渔”。除了技术技巧之外,有什么东西可以受用一生,可以帮助你更快掌握知识点,更快实现目标?我有很多要整理的内容,不放在这里细说,后面我会整理一下自己关于项目管理,团队管理,前端工作流,前端组件化,前端模板化,前端直播的一些成果,在这里和大家分享。

好了,回归正题,今天我们聊一聊 Vuex。看看大家是否真正完全掌握了 Vuex。过去一段时间,我发现大部分同学对技术的理解没有到达一定深度。只是停留在简单的知识点上,并没有深入的去进行思考。这就导致很多知识点其实并没有完全掌握。随便找一个方向进行深入发问,就会触到你的知识盲区。今天我们就对 Vuex 的各个点进行发问,以一个初学者的角度来重新认识下 Vuex

下面的内容中我会用各种问题来进行串联,请大家遇到我的提问时能先简单做下思考。有了结果后再看我的答案。我说的是我的理解,不一定就是对的,希望你也有自己的看法和理解,我的答案只是你心中的答案一个对照。

什么是 Vuex?

在官网的介绍中这样写到:

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

我们去了解一个技术方案时,第一步应该想清楚 “这个方案解决什么样的问题?”

Q: 那么第一个问题来了, Vuex 是为了解决什么问题呢?是什么样的问题让我们必须要用 Vuex 解决呢?

A: 我们说 Vue.js 是单向数据流模型。在单页面应用中,数据由父组件向子组件进行传递,子组件通过触发父组件事件的方式可以进行数据回传。想象这样一个场景,如果页面有复杂的组件嵌套,并且嵌套层次可能很深。这种情况下我们的数据需要通过 prop 一级一级向下传递,叶子组件的事件需要一级一级向上触发。这样的方式显然是不好的,我们希望父组件能够更方便的与各个子孙组件进行通信。再想象一个场景,单页面多路由的情况下,A页面需要传递数据给B页面,我们如何做路由间的数据传递呢?按照以往的解决方案,一般会选择 storage,cookie或者url携带参数来解决。这种方案也存在数据安全,数据传递大小限制等问题。以上的问题有没有一个更优雅的解决方案呢?

Q: 如果让你来解决以上的问题,不使用现有框架,有什么好的办法吗?

A: 如果我来实现,我会在window下设置一个变量,值为一个空对象。可以将所有需要传递的变量数据存储在这个对象中。通过 Object.defineProperty 对所有属性添加 set 监听,每当属性值发生变化时 通过 window.dispatchEvent 触发一个全局事件。该事件注册到所有组件中,每当属性变化时通知到各个页面与组件,再由各个组件进行取出单独处理。

我们再看下Vuex是不是这样做的,Vuex的核心结构包括:State,Getter,Mutation, Action, Module。我们把 State 看作是那个存储全部共享数据的对象。当你需要跨路由,跨组件进行数据共享时,把需要共享的数据保存到 State 中即可。Vuex 框架会帮你进行同步,只要有修改就会同步到各个组件中。并及时更新页面数据。

数据设置好之后,我们就可以在各个组件中使用 this.$store.state 来获取 state 对象并使用数据。当你需要修改数据时,你需要触发一个 mutation 来进行数据修改,官网的示例我们看下:

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

每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler), 在上面的例子中 type 为 increment当我们要修改 state 中的 count 属性时,需要这么做:

store.commit('increment')

通过触发 mutation 下的 increment 事件来修改 对此,官网也有一句解释:

“更改 Vuex 的 store 中的状态的唯一方法是提交 mutation”

Q: 第三个问题来了,为什么不能直接通过 this.$store.state.count = 3 来进行赋值?为什么不能直接对 state 下的数据进行赋值?为什么一定要使用 mutation?

A: 最初提出这个问题时,我听到两个回答是:

“mutation 保证数据可溯源”

“mutation更明确地追踪到状态的变化”

在官网我找到这么一段话:

”再次强调,我们通过提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让我们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,我们甚至可以实现如时间穿梭般的调试体验。“

按照文档内容,上面的两个回答是没问题的。我们可以引申另一个问题:

Q: 数据为什么要溯源?为什么要记录每次状态改变?为什么要保存状态快照?

A: 首先,通过 this.$store.state.count 进行赋值是没有任何问题的,在非严格模式下这么写不会报错,数据修改可以被监听到。为什么非要使用 mutation 使数据可溯源呢?试想:

当我在A页面使用 this.$store.state.count = 10;

然后在B页面再次修改 this.$store.state.count = 3;

你是否可以观察到这个修改顺序?你不能,你只能看到修改的结果是 count 值为3,并不知道过程中是谁修改了他。为了在调试工具中观察到数据变化过程,我们统一使用 mutation 来修改数据,会有一个log系统记录下你的每一次修改,如图:

理解了为什么必须使用 mutation 更新数据后,我们再来看一看 mutation 还有什么问题。在官网对 mutation 的介绍中有这么一句话:

”一条重要的原则就是要记住 mutation 必须是同步函数。“

Q: 为什么 mutation 必须是同步函数?我在接口请求的异步回调中执行 store.commit('increment') 可以吗?

A: 首先,官网的 mutation 必须是同步函数,是要求 mutation 下的每个事件的回调函数必须是同步代码。对 commit 触发事件的时机并没有要求,也就是你可以在任意异步方法中执行 store.commit() 来修改数据。为什么 mutation 的事件回调必须是同步代码呢?其实还是为了保证溯源的准确性,当遇到下面情况时:

store.commit('A');
store.commit('B');
store.commit('B');

我们希望观察数据变化时,log中能体现正确的执行顺序:A -> B -> C。当这其中任意一个方法是异步处理时,就有可能出现偏差,数据失真,加大了调试的复杂度,其结果可能是:A -> C -> B / C -> A -> B。所以这就是为什么 mutation 的事件回调必须是同步代码。

除了 mutation 外还有一个修改 state 的办法,就是通过 Action。Action 类似于 mutation,不同在于:

1. Action 提交的是 mutation,而不是直接变更状态。

2. Action 可以包含任意异步操作。

也就是说 Action 是 mutation 的包装,但是 Action 中可以执行异步代码。代码示例:

const store = new Vuex.Store({state: {count: 0},mutations: {increment (state) {state.count++}},actions: {increment ({ commit }) {setTimeout(() => {commit('increment')}, 1000)
}}
})

Q: 就因为异步执行代码就发明 actions 吗?actions 和 mutations 为何一个可以异步一个不可以呢?actions 如何保证溯源的准确性呢?

A: 还是那句话,了解一个方案时,要先看这个方案解决什么问题。actions 解决什么问题呢?试想,一个单页面应用下,在各个页面都要获取一下最新的活动数据,然后在接口请求成功后通过 store.commit('updateDialogData') 来更新全局数据。这样做是不是很傻,我们不能在一个公共的地方写这个数据请求吗?

mutations 下是不可以的。所以我们提供一个 actions。这样你就可以把之前需要写到各个组件,各个页面的异步代码放到一起统一管理了。通过 this.$store.dispatch('xxx') 来触发事件。这样的情况下如何保证正确溯源呢?以往我们是通过 mutations 下的 type 来记录历史的。此处同样可以根据 mutations 记录真实的数据变化。但他不是原始的操作顺序,原始的操作顺序需要按照 actions 的触发顺序记录。

与 actions 的做法类似,当我们每次取出 state 下的数据后都要进行一次格式化,那为什么不能在一个公共的位置统一处理呢?Getter 就是解决这个问题,内部包含了对 state 下数据的 格式化整理函数。

同理,当state上的数据堆积过多,我们需要划分不同的数据区时,Module 可以更简单的提供这个功能。

总结:

以上问题其实没有任何深度,只是记录了一次内部探讨过程。分享出来与大家共同学习。我们只需要多思考就可以明白作者为什么要这么设计,这样设计的好处是什么。但往往我们对一个知识点的深度理解就缺少这么几个问题。多去发现问题,提出问题,解决问题。这样才能够快速提高,做到知其然知其所以然。

以上,与君共勉。

vuex刷新页面数据丢失怎么解决_你是否真正了解Vuex相关推荐

  1. vuex刷新页面数据丢失怎么解决_vuex状态机浅谈

    我最近项目上在使用vuex的过程中,遇到下面两个问题 F5刷新后,vuex中状态丢失 v-model需要与vuex结合 针对这两个问题,我的解决办法是 问题1:F5刷新后,vuex中状态丢失 解决办法 ...

  2. Ajax回退刷新页面问题的解决办法

    Ajax回退刷新页面问题的解决办法 参考文章: (1)Ajax回退刷新页面问题的解决办法 (2)https://www.cnblogs.com/GooPolaris/p/7801828.html 备忘 ...

  3. vuex【解决方案】刷新页面数据丢失(两种方法)—— 含 vuex-along 教程

    问题描述 存入vuex中的数据,在用户刷新页面后会丢失 原因解析 js代码运行时所有变量.函数都保存在内存中.刷新页面后,以前申请的内存被释放,脚本代码重新加载,变量会重新赋值. 解决方案一 sess ...

  4. vuex刷新state数据丢失问题

    用vuex来做全局的状态管理时, 发现当刷新网页后,保存在vuex实例store里的数据会丢失. 1. 产生原因 其实很简单,因为store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载v ...

  5. js 刷新页面但是不闪烁_前端开发还在手动刷新页面?手把手教你搭建一个自动刷新工具...

    作为一名前端,开发web页面是我们的本职工作.在完成一个页面开发的过程中,保存代码然后手动刷新页面查看效果,这样的动作需要重复无数次,虽然一次这样的动作可能只要花费几秒钟的时间,但是次数多了也挺浪费时 ...

  6. 浏览器 刷新页面后回到顶部_当你在浏览器中,忘记了曾经的登录密码怎么办......

    当你在浏览器中,忘记了曾经的登录密码怎么办... 前言 你还在为使用浏览器的时候,忘记密码而烦恼吗?今天要分享的不为人知的小技巧,利用前端技术原理来帮助你找回原密码. 在我们使用各种网站登录时,总会勾 ...

  7. python selenium刷新页面_python selenium 解决页面刷新后元素找不到问题

    1,问题: 当我们第一遍找元素是找到了,而你循环后页面已经新刷新,所以不能用第一遍找出的元素了 即:页面刷新后元素的属性是没变,但是element却变了,所有之前定位的元素element都过期了 2, ...

  8. 鼠标聚焦到Input输入框时,按回车键刷新页面原因及解决方法

    参考地址:http://blog.csdn.net/xuezhongsong/article/details/6859037 方式1:全局控制回车,13-回车键,27-ESC,113-F2 docum ...

  9. 前端有关解决Vuex页面刷新之后数据丢失的问题

    问:有关vuex刷新页面之后数据丢失的问题 答:vuex+缓存解决这个问题. 在使用vuex的时候,刷新页面之后在vuex中存储的数据会丢失,而缓存在刷新页面的时候数据是不会丢失的,所以把vuex和缓 ...

最新文章

  1. iOS App跳转权限设置
  2. vue 改变domclass_基于 vue 开发甘特图组件的心路历程(兼设计分享)
  3. java直接对list使用sql语句_Java和SQL语句阶段考试错题集
  4. linux:scp命令
  5. .NET6之MiniAPI(十八):OpenAPI swagger
  6. esc指令检查打印状态_【行业知识分享】八千字解读ESC系统
  7. 读书笔记—《销售铁军》随记7
  8. python龙卷风框架_WEB框架之Tornado
  9. HTML5+css3 的开心网游戏页面
  10. Oracle下载及安装超详细教程
  11. 中国互联网是如何起步的
  12. LOJ 6437 PKUSC2018 PKUSC
  13. [软件笔试] 2014暴风影音校招技术笔试题(长春站)
  14. 支付宝支付与提现转账问题小结
  15. 第12届信息化领袖峰会丨行程安排新鲜出炉
  16. ERP实施设防三大雷区(转载)
  17. Elementui蓝色阴影边框相关问题的解决方案
  18. 基于javaweb的房屋租赁系统(前端+后端)
  19. 教学管理系统-实验四 顺序图
  20. 递归和动态规划的一个区别(递归是自顶向下,然后返回计算;动态规划是自低向上运算)

热门文章

  1. Linux移植随笔 tslib
  2. 使用mvc模式读取服务器上的文件,关于C#:如何使用asp.net MVC应用程序从服务器上的网络路径读取...
  3. java分布式 mq_分布式系统消息中间件—RabbitMQ的使用进阶篇
  4. python try catch 能知道是哪一行代码_能导致3.7亿美元损失的异常,到底是怎么回事?...
  5. 大文件下载及视频点播的CDN加速实践
  6. sqlserver日期dateadd及STUFF等应用
  7. 3D角色设定全析百图斩
  8. 【JavaScript脚本】——T1基本语法
  9. sqli-labs(40)
  10. shell基础09 gawk程序(上)