ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

基于事件的前端编程

2022-06-06 20:05:19  阅读:153  来源: 互联网

标签:基于 const todoList 前端 编程 click 事件 addEventListener button


基于事件的前端编程

本文写于 2022 年 5 月 17 日。

如果我们需要一个 TODO list 应用,你会怎么样去设计它?

最简单直接的方法:

  1. UI 层创建一个按钮、一个输入框,用一个 ul 嵌套 li 做展示,每个 li 上都有一个删除按钮;
  2. 在 JS 中创建一个数组;
  3. 设置监听事件:
    • 每次点击提交按钮就往数组里 push 东西,然后根据新的数组重新渲染 HTML;
    • 每次点击删除就删除数组中的一项,然后根据数组重新渲染 HTML。

如果按照这种写法,一旦项目复杂了,我们将难以新增功能与维护。

例如,我希望让用户一秒内最多提交 1 次(节流);或者我们有多处可以修改储存 todoList 数组的手段,我希望集中这些操作,不要每修改一次数组就修改一次 DOM……

按照刚刚的思路,代码可能会变得比较“脏”。

其根本原因就是我们没有解耦 UI 和状态。

那么接下来,我们将尝试利用基于”事件“的思想来优化代码。

对于前端来说,事件化是解耦模块与模块之间业务逻辑的手段,也是大型前端项目构筑的一味良药。

什么是事件

只要你使用 JavaScript 操作过 DOM,就一定接触过事件。

window.addEventListener("resize", () => {});

button.addEventListener("click", (e) => {});

当我们的窗口被缩放的时候,触发函数;当一个按钮被点击的时候,触发函数。这就是事件。

并且事件往往是多播的,也就是说不论你往函数中添加多少个函数,在事件触发的时候,所有的函数都会被调用。

button.addEventListener("click", (e) => console.log(1));
button.addEventListener("click", (e) => console.log(2));
button.addEventListener("click", (e) => console.log(3));
button.addEventListener("click", (e) => console.log(4));

button.click();
// 1
// 2
// 3
// 4

如何使用“事件”的思想改善我们的代码

回到我们文章开头的例子。

在基于事件的思想下,我们可以得到如下的分析结论:

  1. 我们有一套 UI,这套 UI 需要根据某一个变量进行渲染,所以这个变量发生变化就是一个事件
  2. 我们有一些按钮,这些按钮触发后会对数据进行操作,每种操作都是一个事件

那么我们的伪代码就可以这么写:

const todoListData = 创建一个可以被监听的数据([]);

const todoList新增事件 = 创建一个事件源();
const todoList删除事件 = 创建一个事件源();

todoList新增事件.监听触发((新增的todo) => todoListData.新增一项(新增的todo));

todoList删除事件.监听触发((要删除的todo) =>
  todoListData.删除一项(要删除的todo)
);

todoListData.监听变化((此时的todoList) => {
  // 修改 HTML
});

瞬间我们的代码就变得简洁了。如果要继续添加其他的代码逻辑也很简单,因为我们将修改数据和修改视图进行了分离。

这里你可以选择自己喜欢的库进行事件的编写,例如 RxJS、node 自带的 EventEmitter 等等……

如果你用的是 React,那么 Redux 也是这种思路。

RxJS 示例

接下来我将使用 RxJS 做一个简单的范例。

const todoListSource$ = BehaviorSubject([]);
export const todoList$ = todoListSource$.pipe(debounceTime(0));

const createItemEventSource$ = Subject();
const createItemEvent$ = createItemEventSource$.pipe(throttleTime(200));

const deleteItemEventSource$ = Subject();
const deleteItemEvent$ = deleteItemEventSource$.asObservable();

export function createItem(newItem) {
  createItemEventSource$.next(newItem);
}

export function deleteItem(targetItem) {
  deleteItemEventSource$.next(targetItem);
}

function onTodoItemCreate(newItem) {
  todoListSource$.next([...todoListSource$.current, newItem]);
}

function onTodoItemDelete(targetItem) {
  todoListSource$.next(
    todoListSource$.current.filter((item) => item !== targetItem)
  );
}

createItemEvent$.subscribe(onTodoItemCreated);

deleteItemEvent$.subscribe(onTodoItemDelete);

简简单单几行代码,却实现了较为复杂的功能。我们来分析看看。

首先第二行。我们在监听数据源的同时做了一个防抖操作。

这里是为了防止当我们订阅了数据源,去做别的操作时,数据源被频繁的修改导致的多次触发订阅,就像 Vue 为什么会有 nextTick 一样。

后面第五行。我们为增加事件添加了节流,这样用户就没办法在短时间内多次新增新项,避免误触。

总结

事件化的编程,让事件成为了模块之间的消息中介,我们不再简单粗暴的互相调用函数、引用变量,而是经由“事件系统”这样一个中介人。

中介人可以帮我们处理很多事情,例如防抖、节流。进一步优化我们的代码。

因此,对于前端来说,事件化是解耦业务逻辑与视图层的重要手段,也是大型前端项目构筑的一味良药。

(完)

标签:基于,const,todoList,前端,编程,click,事件,addEventListener,button
来源: https://www.cnblogs.com/xhyccc/p/16349479.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有