我是这样开启列表定时刷新的
前言
什么是设计原则,这是个需要靠领悟的东西!——接下来,分享一下我前段时间实现的定时刷新列表代码 [链接]!(注:项目使用 vue2.x 框架)
通常的做法
定时更新数据,核心是 setInterval 创建一个定时器,通常我们是这么做的:
1、当组件加载时创建一个定时器,定期调用请求接口;当组件销毁时清理掉这个定时器。这是两个不同的 hook,需要一个状态变量 timmer 记录定时器 id 。
2、由于用户可能点击搜索等 主动触发页面更新,所以我们需要做一个防抖,需要一个变量 lastReqTime 记录上次的更新时间,然后基于这个时间在定时刷新。
3、外界需要选择是否开启定期刷新,所以有一个boolean类型的prop
核心代码如下:
props: {
other code ... ... // 其他代码省略 autoRefresh: { type: Boolean, default: false } }, data() { return {
other code ... ... // 其他代码省略 lastReqTime: 0, timmer: null }; }, methods: {
other code ... ... // 其他方法省略 // 分页请求数据的method: async initPage(pageNo = 1) { this.lastReqTime = Date.now(); other code ... ... // 其他代码省略 this.lastReqTime = Date.now(); } }, mounted() { if (this.autoRefresh) { this.timmer = setInterval(() => { if (Date.now() >= this.lastReqTime + 30000) { // 每30秒更新一次列表 this.initPage(this.pageNo); } }, 1000); // 每秒中确定一次 }
other code ... ... // 其他代码省略 }, beforeDestroy() { clearInterval(this.timmer); }
这段代码的最大问题是逻辑分散,而且为了一个定期更新数据,产生了两个状态(lastReqTime 和 timmer ),还污染了initPage方法 ( 额外维护lastReqTime),甚至timmer的维护也分散在了mounted和beforeDestory两个方法。
别人要想看懂你是怎么实现的,要到处找逻辑,很不容易理解。如果这个组件只有一个功能还好,毕竟就一个功能,问题是还有很多其他功能,想象一下标红的 other code ... ... 吧。
更好的做法
代码是写给人看的(尽管是给机器执行的,但维护的还是人) 把逻辑尽可能放在一起(即所谓的内聚)很重要:
(注意:下方代码中加粗的注释)
props: {
other code ... ... // 其他props省略 autoRefresh: { type: Boolean, default: false } }, mounted() { if (this.autoRefresh) {
// 所有逻辑都在一起,其他人阅读时不用到处找代码了(整体抽取 或 移除都很方便)
// 下面lastReqTime 和 timmer 就是一个普通的局部变量了,不是data中的状态了 let lastReqTime = 0; const cycleTime = 30000; const tickTime = 1000;
// 使用代理模式 来记录lastReqTime 而非污染原来的 initPage : const oldFn = this.initPage; this.initPage = function(...params) { lastReqTime = Date.now(); // 必须return,保持一致 return oldFn(...params).then(res => { lastReqTime = Date.now(); return res; }); };
// 定时器的创建 与销毁 : const timmer = setInterval(() => { if (Date.now() >= lastReqTime + cycleTime) { this.initPage(this.pageNo); } }, tickTime); this.$once('hook:beforeDestroy', () => { // 通过这样监听!运用好框架的“冷技术”,避免逻辑分散 clearInterval(timmer); }); }
other code ... ... // if结束后 的其他代码省略 }
注意标红的 other code ... ... 想象一下代码的结构! 对比一下,内聚后的代码是不是更好理解了呢 ?你 get到了吗……
窥见vue3的编码之道
本节补充于:2020年9月25日12:45:36
正如vue官方所言:vu2中代码逻辑被分散到了多个地方(data,props,methods,computed,watch,lifecycle hooks……),我们组织代码的方式就像这样:
本篇案例的核心思想就是说明一个技巧:同一个功能的代码应当集中在一起,这样便具有更强的可读性和可维护性,而非分散到各处。
在vue2中,要实现这种目的,我们需要借助各种非主流的 hack api ,如$data,$watch,Vue.observable等,这需要较深的技术积累!
在vue3中,灵活的 也是官方推荐的composition api,让我们可以轻松实现下面的这种转变:
vue3 我爱了!
composition api 有缺点吗?当然,缺点就是它太灵活了,对于一些初级开发或者那些不擅长写出优雅代码的coder而言,很容易写出“意大利面条”式的代码。在vue2中,我们必须要把reactivity写在data中,把计算属性写在computed中,生命周期必须写在对应的hooks中;但在composition api中似乎一切限制都没有了。我认为用好composition api需要较多的设计经验,也许这仅对于高级一点的程序员而言是好事!