业务前端的本质--数据维护

Vue/React 将前端开发从 jQuery 命令式的编程风格带到了声明式的编程风格,开发者只需要描述界面应该是什么样子,Vue/React 就会根据数据的变化自动更新界面。

因此对于业务页面只需要关心数据有什么 以及引起数据的变化有什么。

数据

数据主要有两大类,ui 相关非 ui 相关

ui 相关

前端本质上就是将数据可视化,因此定义的变量中一部分就是供页面展示使用的,在 Vue 中会把这些数据定义在 data 中变为响应式,在 React 中会调用 SetState 来更新这些变量以便更新视图。

前端自闭环

一些变量仅在前端记录进行 ui 的更新,后端不会感知到。

比如页面的 loading 态:

点击态,是否打开展示更多:

来自后端

页面数据是存在数据库中,后端会把这些数据给前端,供前端展示,这类数据又分为两种:

  • 将数据直接赋值给某个前端变量进行展示,比如昵称、标题等。
  • 将数据转换后再进行展示,比如钱相关字段因为精度问题,后端存储的是分,给到前端以后需要转换成元进行展示。

来自底层

设备信息:通过屏幕宽高来设置弹窗的宽高。

localStorage:一些模块可能一天只需要展示一次,前端将标志存到 localStorage 中自行进行判断。

非 ui 相关

这些变量和 ui 无关也不会和页面后端交互,举几个例子:

前端自闭环

请求锁:一些提交请求,为了防止用户多次提交,可以在接口请求前设置一个标志位,类似于下边这样。

js 复制代码
// 用于保存请求状态的标志位
let isSubmitting = false;
​
// 模拟一个异步请求
function sendRequest() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("请求成功");
        }, 2000); // 模拟2秒的请求时间
    });
}
​
// 处理按钮点击事件
function handleSubmit() {
    // 检查标志位
    if (isSubmitting) {
        console.log("请求正在进行中,请稍后...");
        return;
    }
​
    // 设置标志位
    isSubmitting = true;
    console.log("开始请求...");
​
    // 发送请求
    sendRequest().then(response => {
        console.log(response);
    }).catch(error => {
        console.error(error);
    }).finally(() => {
        // 请求完成后重置标志位
        isSubmitting = false;
        console.log("请求完成,可以再次提交");
    });
}

埋点数据:模块曝光或者用户点击的时候进行埋点,相关数据会提前存到一个对象中。

定时器引用:页面中创建定时器后用一个变量保存定时器实例,用户可能离开页面的时候还未执行到定时器,因此需要在离开页面的时候进行清除。

js 复制代码
Page({
  data: {
    // 其他数据
  },
  
  // 用于保存定时器实例的变量
  timer: null,
​
  // 页面加载时创建定时器
  onLoad: function() {
    this.createTimer();
  },
​
  // 创建定时器的方法
  createTimer: function() {
    this.timer = setTimeout(() => {
      console.log('定时器执行中...');
    }, 5000); // 5秒后执行
  },
​
  // 页面卸载时清除定时器
  onUnload: function() {
    this.clearTimer();
  },
​
  // 清除定时器的方法
  clearTimer: function() {
    if (this.timer) {
      clearTimeout(this.timer);
      console.log('页面即将卸载,定时器已清除');
    }
  },
​
  // 其他页面方法和事件处理函数
});

来自后端

埋点数据:模块曝光或者用户点击的时候进行埋点,一些数据会由后端给到。

来自底层

localStorage:比如存储用户的点击次数,进行相应的限频。

引起数据的变化

数据变化的根源就是用户操作,用户的操作可能直接引起数据变化,也可能触发某些全局事件或者定时器,又触发新一轮的页面数据变化。

用户操作

大部分的数据变化都是由于用户的操作,比如点击、滑动。

根据点击的位置不同,可能触发不同的动作。比如去请求后端接口拿数据、进入新页面、离开当前页面,在小程序中会触发 onHideonShow 生命周期,在这些周期中会做一些动作更新数据。

还有经常遇到的表单逆向操作,当用户依次填了 A 项、B 项、C 项,由于 B、C 依赖于 A 项的选择,当用户再修改 A 项的时候需要清空 B、C 之前的选择。

监听数据变化

Vue 中通过 watch 监听变量,在 React 中通过 useEffect 监听变量。一般情况监听的是组件的 prop,当父组件变化时,子组件进行相应的更新。

定时器

定时器时间结束后,会触发定时器注册的回调函数。

常用于页面上的倒计时的更新。也用于解决 ui 更新的时序问题,直接给 setTimeout 事件设置为 0,让回调函数到下一个宏任务周期去执行。

全局事件

主要用于跨模块之间的通信,常用的比如 eventbus、vuex、redux 等。

常见的比如全局的登录事件,各个页面需要监听登录成功才去触发后续的业务逻辑。

关联

理想状态,用户动作 => 更新数据 => 页面自动更新。

但实际上,当数据变化的时候,由于全局事件、定时器的存在,还会继续触发新一轮的数据更新。

此外,数据变化每次也不止变更一个数据,数据之间又会有相应的联动关系。

这也是为什么框架都在倡导单一数据流的原因,全局事件第一个人用起来会很方便,但在一个上百人的前端项目中,后续页面继续迭代或者重构的时候,漏改或者影响面评估错误的风险也会增高。

当增加一个数据变量的时候也要考虑清楚,是否有必要新增,因为每增一个都会增加页面的内部复杂度。当然有时候也不是变量越少越好,当各个地方共用一个变量,也意味着这个变量赋予了多重含义,有悖「单一职责」。

业务前端看起来简单,就是维护一些数据。但当页面数据变量越来越多,交互越来越多,数据更新会变得错综复杂,后续迭代的心智负担会越来越重。

此时能做的就是明确当前数据(ui/非 ui 数据)有什么,引起数据的变化有什么(用户动作、数据之间的关联等) ,这些理清之后出现 bug 的概率也会极大降低。

最根本的还是降低函数和函数之间、模块与模块之间的依赖关系,也就是常说的高内聚、低耦合,保证后续改动的影响面足够小且明确。

最终看到的页面不再是页面,而是数据的变化和流动。

相关推荐
让开,我要吃人了1 小时前
HarmonyOS开发实战(5.0)实现二楼上划进入首页效果详解
前端·华为·程序员·移动开发·harmonyos·鸿蒙·鸿蒙系统
Passion不晚1 小时前
Vue vs React vs Angular 的对比和选择
vue.js·react.js·前端框架·angular.js
everyStudy2 小时前
前端五种排序
前端·算法·排序算法
甜兒.3 小时前
鸿蒙小技巧
前端·华为·typescript·harmonyos
她似晚风般温柔7895 小时前
Uniapp + Vue3 + Vite +Uview + Pinia 分商家实现购物车功能(最新附源码保姆级)
开发语言·javascript·uni-app
Jiaberrr6 小时前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
everyStudy7 小时前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
城南云小白7 小时前
web基础+http协议+httpd详细配置
前端·网络协议·http
前端小趴菜、7 小时前
Web Worker 简单使用
前端
web_learning_3217 小时前
信息收集常用指令
前端·搜索引擎