现代 JavaScript 框架存在的主要起因

作者 : 开心源码 本文共3147个字,预计阅读时间需要8分钟 发布时间: 2022-05-12 共104人阅读

简评:现代 JavaScript 框架的出现最主要是处理哪个问题?这篇文章很好的解释了这个问题。

我见过许多人盲目地用像 React,Angular 或者 Vue.js 这样的现代框架。这些框架提供了许多有趣的东西,通常人们会忽略这些框架存在最主要的起因,这些起因不是

  • 它们基于组件;
  • 它们有一个强大的社区;
  • 它们有很多第三方库;
  • 它们有很多有使用的第三方组件;
  • 它们有浏览器插件,可以帮助调试;
  • 它们适使用于单页面应使用程序。

这些都不是最本质的起因,最本质的起因是保持 UI 和状态同步并不容易。

UI 和 状态同步难在哪?

如果,您正在构建一个 Web 应使用程序,使用户可以填写他人的 email 地址来发起邀请。并且邀请列表有两种状态:

  1. 空状态,我们在这个状态下提醒使用户填写邮箱。
  2. 非空状态,这种状态我们需要列出出等待被邀请的使用户,并且提供删除按钮。

尝试用纯 JavaScript 实现这种功能

源码和效果可以到参考:codepen。

index.html 代码

<html>  <body>    <div id="addressList">      <form>        <input>        <p class="help">Type an email address and hit enter</p>        <ul>        </ul>      </form>    </div>  </body></html>

JS 代码

class AddressList {  constructor(root) {    // state variables    this.state = []    // UI variables    this.root = root    this.form = root.querySelector('form')    this.input = this.form.querySelector('input')    this.help = this.form.querySelector('.help')    this.ul = root.querySelector('ul')    this.items = {} // id -> li element    // event handlers    this.form.addEventListener('submit', e => {      e.preventDefault()      const address = this.input.value      this.input.value = ''      this.addAddress(address)    })    this.ul.addEventListener('click', e => {      const id = e.target.getAttribute('data-delete-id')      if (!id) return // user clicked in something else            this.removeAddress(id)    })  }  addAddress(address) {    // state logic    const id = String(Date.now())    this.state = this.state.concat({ address, id })    // UI logic    this.updateHelp()    const li = document.createElement('li')    const span = document.createElement('span')    const del = document.createElement('a')    span.innerText = address    del.innerText = 'delete'    del.setAttribute('data-delete-id', id)    this.ul.appendChild(li)    li.appendChild(del)    li.appendChild(span)    this.items[id] = li  }  removeAddress(id) {    // state logic    this.state = this.state.filter(item => item.id !== id)    // UI logic    this.updateHelp()    const li = this.items[id]    this.ul.removeChild(li)  }  // utility method  updateHelp() {    if (this.state.length > 0) {      this.help.classList.add('hidden')    } else {      this.help.classList.remove('hidden')    }  }}const root = document.getElementById('addressList')new AddressList(root)

这段代码很好地说明了用纯 JavaScript 实现一个有点小复杂的 UI 所需要的工作量。

在示例中,静态结构在 HTML 中创立,动态内容用 JavaScript 来创立。这种方式有几个问题:

构建 UI 的 JavaScript 代码可读性不高,我们使用两个不同的部分来定义 UI。我们可以用 innerHTML来让代码更容读,但是这样效率不高,而且容易引发跨站脚本漏洞。我们也可以用模板引擎,但是假如重新生成大的 DOM 的子节点又会遇到两个问题:效率不高,通常需要重新连接 event handler。

但这都是小问题,最主要的问题是:我们需要在状态变更的时候升级 UI。每一次状态出现变更我们都需要用大量的代码来升级 UI。上面的例子我们升级状态是使用了两行的代码,但是升级 UI 却耗费了 13 行代码(虽然这个 UI 并不复杂)。

它不仅编写起来复杂而且还很脆弱。想象一下,我们需要实现将列表于服务器同步的功能。我们需要将本地数据和服务器发来的数据进行比较。并且需要点对点的对每个变更同步到 DOM 节点中。假如这个过程中有每一步出现差错都直接导致 UI 同步失败。

因而,维护 UI 与数据同步需要编写大量繁琐,脆弱和脆弱的代码。

公告式 UI 处理方案

它是不是社区,它不是工具,也不是生态系统,也不是第三方库……

到目前为止,这些框架提供的最大的改进是实现应使用状态和 UI 同步。

我们只要要定义一次 UI,不必编写为每一次动作编写 UI。相同的状态总能得到相同的 UI 输出(状态和 UI 同步,状态变更后会自动升级 UI)。

原理

有两个基本策略:

  • 重新渲染整个组件: React。当组件的状态发送变化时,它会在内存中渲染一个 DOM,并和现有 DOM 进行比较。但是为了降低成本,实际上它会渲染一个虚拟 DOM,来和之前的虚拟 DOM 进行比较,而后计算更改并对真实 DOM 进行修改。
  • 用观察者来监听变化: Angular 和 Vue.js 观察你的状态变化,并且只会升级关联的 DOM 元素。

和 Web Component 比较?

很多时候人们将 React,Angular 和 Vue.js 和 Web 组件进行比较。很多人不了解这些框架提供的最大好处:保持 UI 和状态同步。而 Web 组件并不提供内容,它是一套规范,以便开发者可以自由创立可重使用的元素。所以单纯用 Web Component + 纯 JavaScript 依然需要手动保证状态同步,要实现高效易维护的 UI 还需要用 现代 JavaScript 框架。

自己实现

自己实现一个相似的功能,能够加深对原理的了解。我们尝试用 虚拟DOM (而不是直接使用第三方框架)实现一个相似 React 的框架,来重写刚刚的 demo。

下面是我们 Framework 的核心部分,代表所有组件的基类:

下面是基于 Component 重写的邮箱邀请的应使用(借助 babel 变换来支持 JSX)这里是源码:

现在的 UI 是公告性的,而且我们没有直接用任何框架。我们可以实现以任何方式更改状态的逻辑,并且不需要额外编写 UI 同步的代码。


原文链接:The deepest reason why modern JavaScript frameworks exist
推荐阅读:Level UP! 提升你的编程技能

上一篇 目录 下一篇

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 现代 JavaScript 框架存在的主要起因

发表回复