十年过去了,UI 框架还停滞在原地……
<div style="color: black; text-align: left; margin-bottom: 10px;">
<div style="color: black; text-align: left; margin-bottom: 10px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-axegupay5k/53c16e3a2ef140bebce85b79ce939dba~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1728111566&x-signature=52%2BnsPFDVd5wGAVAqc4DMxHX3bk%3D" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">【CSDN 编者按】<span style="color: black;">这篇<span style="color: black;">文案</span>是一位前端<span style="color: black;">研发</span>者揭示了主流 UI 框架的局限性,认为它们都在误导<span style="color: black;">研发</span>者,<span style="color: black;">隐匿</span>了 DOM 节点的真实<span style="color: black;">繁杂</span>性。作者指出 HTML 语法并不是描述 UI 的最佳抽象,而是 DOM 树的一种投影。HTML <span style="color: black;">没法</span>有效地表达 DOM 节点的七类属性,而只能将它们混合在<span style="color: black;">一块</span>。作者认为开发者应该面对并理解 DOM 节点的自然<span style="color: black;">繁杂</span>性,而不是被框架所迷惑。作者<span style="color: black;">亦</span><span style="color: black;">说到</span>了 Svelte 5 的 runes 特性,<span style="color: black;">暗示</span>对其有<span style="color: black;">必定</span>的期待。</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">原文链接:<span style="color: black;">https://moonthought.github.io/posts/all-your-mainstream-ui-frameworks-are-lying-to-you/</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">未经<span style="color: black;">准许</span>,禁止转载!</span></p><span style="color: black;">作者 | <span style="color: black;">moonthought.github.io</span> </span><span style="color: black;">译者</span><span style="color: black;"> | 明明如月 </span><span style="color: black;">责编 | 夏萌</span><span style="color: black;">出品 | CSDN(ID:CSDNnews)</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-tjoges91tu/d733415aa4200b5d75418b2d35bb4088~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1728111566&x-signature=%2BCb6RMBsDAoX0r6xia9CYZLb3YY%3D" style="width: 50%; margin-bottom: 20px;"></p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><strong style="color: blue;"><span style="color: black;">Svelte 的全新篇章</span></strong></span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">几天前,Svelte 5 的预览版本随着对 runes 的<span style="color: black;">仔细</span>介绍 被公<span style="color: black;">研发</span>布。该<span style="color: black;">信息</span>令<span style="color: black;">包含</span>我在内众多人士激动不已。</span><span style="color: black;">$props</span><span style="color: black;">、</span><span style="color: black;">$derived</span><span style="color: black;">、</span><span style="color: black;">$effects</span><span style="color: black;">、</span><span style="color: black;">$state</span><span style="color: black;">、信号等概念,我并非<span style="color: black;">第1</span>次接触,我在 5-6 年前就见过<span style="color: black;">这般</span>的响应式处理机制。我认为 Svelte 正沿着正确的方向演进。虽然 Svelte 仍然<span style="color: black;">运用</span>了<span style="color: black;">有些</span>主流但不太适合<span style="color: black;">处理</span><span style="color: black;">繁杂</span> Web 问题的<span style="color: black;">方法</span>,我仍然期望<span style="color: black;">她们</span>能够克服这些困难。<span style="color: black;">不外</span>,这并非本文今天要探讨的核心议题。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">令我不解的是,人们在<span style="color: black;">处理</span> UI 问题时仍采用<span style="color: black;">一样</span>的权宜之计。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">为何</span>组件的响应性<span style="color: black;">处理</span><span style="color: black;">方法</span>仍然需要编译<span style="color: black;">周期</span>?<span style="color: black;">为么</span><span style="color: black;">咱们</span>还在<span style="color: black;">运用</span>非标准的 HTML 语法和一系列自定义指令?<span style="color: black;">为么</span> UI 的描述仍然是以命令式的方式进行?<span style="color: black;">为何</span>技术界还在<span style="color: black;">奋斗</span>模仿 HTML?</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">让<span style="color: black;">咱们</span>从最后一个问题<span style="color: black;">起始</span>探讨。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-tjoges91tu/9cc696d4316f1426631857c88ba7e709~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1728111566&x-signature=t1IhGqnjxCSjzIXH5pE%2FnUXGyA8%3D" style="width: 50%; margin-bottom: 20px;"></p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><strong style="color: blue;"><span style="color: black;">HTML <span style="color: black;">到底</span>是不是合适的抽象层?</span></strong></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这个问题可能会<span style="color: black;">诱发</span>不少争议,但事实上,HTML 仅仅是 DOM(文档对象模型)树的一种表现形式,而这种表现形式并非<span style="color: black;">必定</span>是最优的。确切地说,浏览器处理的不是 HTML,而是 DOM 节点。一个完整的 DOM 节点应该<span style="color: black;">包含</span>以下七类属性:</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">属性(Attributes)</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">事件处理器(Event Handlers)</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">样式(Styles)</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">自定义数据属性(Data-* Attributes)</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">可见性(Visibility)</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">文本内容(Text Content)</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">子节点(Children)</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">遗憾的是,许多<span style="color: black;">研发</span>者要么<span style="color: black;">无</span><span style="color: black;">认识</span>到这种<span style="color: black;">繁杂</span>性是不可避免的,要么<span style="color: black;">便是</span>不愿承认。几乎所有现有的 UI <span style="color: black;">处理</span><span style="color: black;">方法</span>都在<span style="color: black;">运用</span>一种过于简化的方式试图把这种<span style="color: black;">繁杂</span>性忽略掉,这是不可取的。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这些<span style="color: black;">处理</span><span style="color: black;">方法</span>都试图把 DOM 节点属性的多样性简化为一个扁平的属性列表,这种做法显然不切<span style="color: black;">实质</span>。即便将七大类 DOM 节点属性简化为一张扁平的属性列表,这些属性的多样性仍然会存在,只是变<span style="color: black;">成为了</span>一堆难以管理的碎片信息。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">复杂性<span style="color: black;">重点</span>有两类:人为引入的<span style="color: black;">繁杂</span>性和自然存在的<span style="color: black;">繁杂</span>性。人为引入的<span style="color: black;">繁杂</span>性<span style="color: black;">一般</span>来自库、框架、编程语言和设计范式等。而自然<span style="color: black;">繁杂</span>性则是平台本身固有的,用于<span style="color: black;">处理</span>特定<span style="color: black;">行业</span>的基本问题。优秀的工程师会<span style="color: black;">奋斗</span>减少人为引入的<span style="color: black;">繁杂</span>性,<span style="color: black;">同期</span>积极面对和<span style="color: black;">处理</span>自然<span style="color: black;">繁杂</span>性。<span style="color: black;">咱们</span>应当<span style="color: black;">再也不</span>回避这种自然存在的<span style="color: black;">繁杂</span>性,而是应更加尊重和理解<span style="color: black;">咱们</span>所<span style="color: black;">运用</span>的平台。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Rich Harris <span style="color: black;">发布</span>了一则精彩的视频,<span style="color: black;">仔细</span>解释了 getter 和 setter 的<span style="color: black;">实质</span>运作原理,并<span style="color: black;">回复</span>了公众对 Svelte 新响应机制的疑惑。然而,他<span style="color: black;">无</span>对“需要编写<span style="color: black;">更加多</span>代码”这一观点进行充分解释。<span style="color: black;">最后</span><span style="color: black;">目的</span><span style="color: black;">不仅</span>是编写更少的代码,而是用最少量的代码<span style="color: black;">知道</span>地表达应用的意图。<span style="color: black;">倘若</span>某项技术所强调或<span style="color: black;">独一</span><span style="color: black;">供给</span>的<span style="color: black;">便是</span>“简单性”,<span style="color: black;">那样</span>你可能就<span style="color: black;">忽略</span>了<span style="color: black;">有些</span>关键的细节。这些问题迟早会从其他<span style="color: black;">方向</span><span style="color: black;">显现</span>。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">实质</span>上,<span style="color: black;">选取</span> </span><span style="color: black;">onClick={...}</span><span style="color: black;">, </span><span style="color: black;">on:click={...}</span><span style="color: black;">和 </span><span style="color: black;">@click="..."</span><span style="color: black;"> 并<span style="color: black;">无</span>多少差异。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这种<span style="color: black;">处理</span><span style="color: black;">方法</span>之<span style="color: black;">因此</span>存在,某种程度上是<span style="color: black;">能够</span>理解的:</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">技术栈<span style="color: black;">运用</span>起来简单,但设计困难。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">初期</span>应用<span style="color: black;">一般</span>较为简单,<span style="color: black;">因此呢</span><span style="color: black;">基本</span>的模板<span style="color: black;">就可</span>满足 DOM API 的<span style="color: black;">需要</span>。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这种代码的性能直到近几年(约 4-5 年)才真正达到了足够好的水平。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">重点</span><span style="color: black;">原由</span><span style="color: black;">实质</span>上是:</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">你需要投入<span style="color: black;">海量</span>时间进行<span style="color: black;">实验</span>,并愿意接受新的现实和当前<span style="color: black;">办法</span>的不足。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">令人遗憾的是,大<span style="color: black;">都数</span>人几乎<span style="color: black;">无</span>多余的时间来做这些事情。我不怪罪于<span style="color: black;">她们</span>,<span style="color: black;">每一个</span>人都有自己的局限性。但这种局面每年令我感到越发<span style="color: black;">懊丧</span>。难道你们不觉得<span style="color: black;">针对</span> HOCs、render-props、<span style="color: black;">持续</span>变化的自定义语法以及其它<span style="color: black;">有些</span><span style="color: black;">火速</span>就被<span style="color: black;">咱们</span>遗弃的技术,浪费的时间太可惜了?</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">我越来越认为这其中有直接的联系:应用程序的<span style="color: black;">研发</span>和<span style="color: black;">守护</span>仍然是一项困难和成本<span style="color: black;">昂贵</span>的任务。而<span style="color: black;">咱们</span>却在消耗精力进行<span style="color: black;">各样</span>妥协,而非学习如何更有效地利用<span style="color: black;">最少</span>一个平台。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-tjoges91tu/b1a415f92533c6f44f68fd0415fcdb31~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1728111566&x-signature=7yKsm%2FjS6GuCJsbGqXB6h69w2tQ%3D" style="width: 50%; margin-bottom: 20px;"></p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><strong style="color: blue;"><span style="color: black;">被“篡改”的语法</span></strong></span></h2>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">人们常对 React 的 JSX 语法、Vue 的模板语法,<span style="color: black;">或</span> Svelte 的组件方式有不少批评。这些批评并非<span style="color: black;">无</span>道理,但更重要的一点是:它们受到质疑并不是<span style="color: black;">由于</span>缺乏<span style="color: black;">优良</span>。而是<span style="color: black;">由于</span>这些<span style="color: black;">方法</span>本质上是不准确的编程抽象。各框架之间的差异远非表面上看起来<span style="color: black;">那样</span>简单。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">下面我将<span style="color: black;">经过</span>代码示例来阐明我的观点:</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">React</span></strong></p><span style="color: black;"><span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">Component</span>() </span>{</span><span style="color: black;"> <span style="color: black;">return</span> (</span><span style="color: black;"> <span style="color: black;"><span style="color: black;"><<span style="color: black;">div</span>></span></span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;"><<span style="color: black;">h1</span>></span>Hey there<span style="color: black;"></<span style="color: black;">h1</span>></span></span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;"></<span style="color: black;">div</span>></span></span></span><span style="color: black;"> );</span><span style="color: black;">}</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">Vue</span></strong></p><span style="color: black;"><span style="color: black;"><<span style="color: black;">template</span>></span></span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">div</span>></span></span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">h1</span>></span>Hey there<span style="color: black;"></<span style="color: black;">h1</span>></span></span><span style="color: black;"> <span style="color: black;"></<span style="color: black;">div</span>></span></span><span style="color: black;"><span style="color: black;"></<span style="color: black;">template</span>></span></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">Svelte</span></strong></p><span style="color: black;"><span style="color: black;"><<span style="color: black;">div</span>></span></span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">h1</span>></span>Hey there<span style="color: black;"></<span style="color: black;">h1</span>></span></span><span style="color: black;"><span style="color: black;"></<span style="color: black;">div</span>></span></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">实质</span>上,它们看起来都不错。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">此刻</span>,让<span style="color: black;">咱们</span>尝试添加<span style="color: black;">有些</span><span style="color: black;">要求</span>渲染:</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">React</span></strong></p><span style="color: black;"><span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">ConditionalComponent</span>(<span style="color: black;">{ showMessage }</span>) </span>{</span><span style="color: black;"> <span style="color: black;">return</span> (</span><span style="color: black;"> <span style="color: black;"><span style="color: black;"><<span style="color: black;">div</span>></span></span></span><span style="color: black;"><span style="color: black;"> {showMessage ? (</span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;"><<span style="color: black;">h1</span>></span>Hey there<span style="color: black;"></<span style="color: black;">h1</span>></span></span></span><span style="color: black;"><span style="color: black;">) : }</span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"></<span style="color: black;">div</span>></span></span></span><span style="color: black;">);</span><span style="color: black;">}</span><span style="color: black;">...</span><span style="color: black;"><ConditionalComponent showMessage={<span style="color: black;">true</span>} /></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">Vue</span></strong></p><span style="color: black;"><span style="color: black;"><<span style="color: black;">template</span>></span></span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">div</span>></span></span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">h1</span> <span style="color: black;">v-if</span>=<span style="color: black;">"showMessage"</span>></span>Hey there<span style="color: black;"></<span style="color: black;">h1</span>></span></span><span style="color: black;"> <span style="color: black;"></<span style="color: black;">div</span>></span></span><span style="color: black;"><span style="color: black;"></<span style="color: black;">template</span>></span></span><span style="color: black;"><span style="color: black;"><<span style="color: black;">script</span>></span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;">export</span> <span style="color: black;">default</span> {</span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;">name</span>: <span style="color: black;">ConditionalComponent</span>,</span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;">props</span>: {</span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;">showMessage</span>: <span style="color: black;">Boolean</span></span></span><span style="color: black;"><span style="color: black;"> }</span></span><span style="color: black;"><span style="color: black;"> }</span></span><span style="color: black;"><span style="color: black;"></<span style="color: black;">script</span>></span></span><span style="color: black;">...</span><span style="color: black;"><span style="color: black;"><<span style="color: black;">ConditionalComponent</span> <span style="color: black;">:showMessage</span>=<span style="color: black;">"true"</span> /></span></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">Svelte</span></strong></p><span style="color: black;"><span style="color: black;"><!-- Svelte --></span></span><span style="color: black;"><span style="color: black;"><<span style="color: black;">div</span>></span></span><span style="color: black;">{#if showMessage}</span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">h1</span>></span>Hey there<span style="color: black;"></<span style="color: black;">h1</span>></span></span><span style="color: black;"> {/if}</span><span style="color: black;"><span style="color: black;"></<span style="color: black;">div</span>></span></span><span style="color: black;">...</span><span style="color: black;"><span style="color: black;"><<span style="color: black;">ConditionalComponent</span> <span style="color: black;">showMessage</span>=<span style="color: black;">{true}</span> /></span></span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">首要</span>,让<span style="color: black;">咱们</span>聊聊视图树(View Tree)内部的 </span><span style="color: black;">if</span><span style="color: black;">语句。<span style="color: black;">是不是</span><span style="color: black;">能够</span>用空值或某种插件组件<span style="color: black;">做为</span>回退呢?这是一种指令还是模板块?需要<span style="color: black;">知道</span>的是,这种设计在 DOM API 中是不存在的,只能<span style="color: black;">叫作</span>其为一种权宜之计。问题不仅在于命名,更在于<span style="color: black;">全部</span>概念的设立。例如,</span><span style="color: black;">v-if</span><span style="color: black;"> 和 </span><span style="color: black;">{#if ...}</span><span style="color: black;"> <span style="color: black;">便是</span><span style="color: black;">这般</span>的表现。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Vue 无疑是这一现象的重要<span style="color: black;">表率</span>。你有两种<span style="color: black;">选取</span>:要么频繁地创建和销毁组件,要么简单地<span style="color: black;">隐匿</span>组件(<span style="color: black;">经过</span> </span><span style="color: black;">display: none</span><span style="color: black;">等)。在 2023 年,这种实践<span style="color: black;">已然</span>过时,是对浏览器和 DOM API 的一种不尊重。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">当然,问题并非仅存在于 Vue。以 React 为例,其函数组件<span style="color: black;">因为</span> hooks 机制的特性,内容经常充满副<span style="color: black;">功效</span>。这<span style="color: black;">引起</span>了即使<span style="color: black;">无</span>必要,<span style="color: black;">亦</span>会过度依赖重新渲染来重新计算副<span style="color: black;">功效</span>和更新数据。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">平常</span>的观点是:“React 会<span style="color: black;">引起</span>额外的重新渲染,但其核心机制目的是优化性能并保持 UI 与应用数据的同步。”然而,<span style="color: black;">实质</span>操作中,大<span style="color: black;">都数</span><span style="color: black;">研发</span>者都在<span style="color: black;">奋斗</span>减少重新渲染。像</span><span style="color: black;">useMemo</span><span style="color: black;"> <span style="color: black;">这般</span>的优化<span style="color: black;">办法</span>,并<span style="color: black;">不可</span><span style="color: black;">保准</span>避免额外的渲染。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">显然,这些都是权宜之计和不必要的妥协。快速和优化的重新渲染并<span style="color: black;">不可</span><span style="color: black;">处理</span><span style="color: black;">基本</span>问题。真正的<span style="color: black;">处理</span><span style="color: black;">方法</span>应在于消除重新渲染这一现象。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这<span style="color: black;">能够</span><span style="color: black;">经过</span><span style="color: black;">全部</span>界面树的静态初始化来达到。简言之,<span style="color: black;">每一个</span>元素(或更准确地说,堆栈内元素的回调函数)应只计算和调用一次,以实现响应式值和节点的绑定。此后,只需<span style="color: black;">按照</span> DOM 结构图来处理流程和事件。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">当然,其他技术<span style="color: black;">一样</span>存在不足,但这是另一个<span style="color: black;">专题</span>。<span style="color: black;">那样</span>,渲染列表呢?</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">React</span></strong></p><span style="color: black;"><span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">UserList</span>() </span>{</span><span style="color: black;"> <span style="color: black;">return</span> (</span><span style="color: black;"> <span style="color: black;"><span style="color: black;"><<span style="color: black;">div</span>></span></span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;"><<span style="color: black;">ul</span>></span></span></span><span style="color: black;"><span style="color: black;"> {users.map(user => (</span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;"><<span style="color: black;">li</span> <span style="color: black;">key</span>=<span style="color: black;">{user.id}</span>></span>{user.name}<span style="color: black;"></<span style="color: black;">li</span>></span></span></span><span style="color: black;"><span style="color: black;"> ))}</span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"></<span style="color: black;">ul</span>></span></span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;"></<span style="color: black;">div</span>></span></span></span><span style="color: black;">);</span><span style="color: black;">}</span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">Vue</span></strong></p><span style="color: black;"><span style="color: black;"><<span style="color: black;">template</span>></span></span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">div</span>></span></span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">ul</span>></span></span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">li</span> <span style="color: black;">v-for</span>=<span style="color: black;">"user in users"</span> <span style="color: black;">:key</span>=<span style="color: black;">"user.id"</span>></span>{{ user.name }}<span style="color: black;"></<span style="color: black;">li</span>></span></span><span style="color: black;"> <span style="color: black;"></<span style="color: black;">ul</span>></span></span><span style="color: black;"> <span style="color: black;"></<span style="color: black;">div</span>></span></span><span style="color: black;"><span style="color: black;"></<span style="color: black;">template</span>></span></span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">Svelte</span></strong></p><span style="color: black;"><span style="color: black;"><<span style="color: black;">div</span>></span></span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">ul</span>></span></span><span style="color: black;"> {#each users as user (user.id)}</span><span style="color: black;"> <span style="color: black;"><<span style="color: black;">li</span>></span>{user.name}<span style="color: black;"></<span style="color: black;">li</span>></span></span><span style="color: black;"> {/each}</span><span style="color: black;"> <span style="color: black;"></<span style="color: black;">ul</span>></span></span><span style="color: black;"><span style="color: black;"></<span style="color: black;">div</span>></span></span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">各样</span>自定义语法、模板和指令显现眼前。然而,谁能<span style="color: black;">保证</span>这些实<span style="color: black;">此刻</span><span style="color: black;">将来</span>不会<span style="color: black;">出现</span>变化呢?事实上,这种<span style="color: black;">状况</span>在过去<span style="color: black;">已然</span><span style="color: black;">显现</span>过,如 React 和 Vue。<span style="color: black;">倘若</span>这些技术一旦失去主流地位,又将<span style="color: black;">怎样</span>防止它们沦为难以<span style="color: black;">守护</span>的遗留系统?</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这<span style="color: black;">诱发</span>出一个新的问题:<span style="color: black;">为何</span>无论是<span style="color: black;">研发</span>者还是框架的创造者,都<span style="color: black;">连续</span>地采用与平台习惯相违背的技术?</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-tjoges91tu/d3287d250906a77557ad9f9f21c6a32c~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1728111566&x-signature=%2FVeaxETM49v6wfiKkA9oIilrOPk%3D" style="width: 50%; margin-bottom: 20px;"></p><h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><strong style="color: blue;"><span style="color: black;">深入探索 DOM API</span></strong></span></h2><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">继续讨论现有问题的潜在<span style="color: black;">处理</span><span style="color: black;">方法</span>,让<span style="color: black;">咱们</span>将目光转向 DOM API。这是一个历经<span style="color: black;">数年</span>精研且功能丰富的库。有些功能<span style="color: black;">实质</span>上是你<span style="color: black;">不可</span>仅<span style="color: black;">经过</span>属性(props)来规避的。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">当面对<span style="color: black;">要求</span>渲染的<span style="color: black;">需要</span>时,DOM API <span style="color: black;">供给</span>了多个<span style="color: black;">处理</span><span style="color: black;">方法</span>,如 node.append() 和 node.appendChild() <span style="color: black;">办法</span>,还有 node.remove() <span style="color: black;">办法</span>以及 node.isConnected 属性。这些 API 让<span style="color: black;">咱们</span>能够随时向 DOM 树添加或移除节点,并检测节点<span style="color: black;">是不是</span>与 DOM 树连接。React <span style="color: black;">便是</span>基于<span style="color: black;">这般</span>的原理进行操作的。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">这儿</span>需要指出的是,许多框架或库在组件设计时,<span style="color: black;">无</span>给予 DOM 节点状态管理足够的<span style="color: black;">注重</span>。<span style="color: black;">实质</span>上,组件<span style="color: black;">自己</span>应当负责管理与 DOM 树连接的节点以及这些节点的子节点的状态,而<span style="color: black;">不该</span>该由<span style="color: black;">外边</span>模块来进行。<span style="color: black;">思虑</span>以下代码示例:</span></p><span style="color: black;"><span style="color: black;">export</span> <span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">Component</span>(<span style="color: black;">{ showMessage }</span>) </span>{</span><span style="color: black;"> h(<span style="color: black;">div</span>, <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> h(<span style="color: black;">h1</span>, {</span><span style="color: black;"> text: <span style="color: black;">Hey there</span>,</span><span style="color: black;"> visible: showMessage,</span><span style="color: black;"> })</span><span style="color: black;"> })</span><span style="color: black;">}</span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">这儿</span>并<span style="color: black;">无</span><span style="color: black;">运用</span>任何特殊的语法或扩展,<span style="color: black;">亦</span><span style="color: black;">无</span>试图<span style="color: black;">隐匿</span>任何<span style="color: black;">基本</span><span style="color: black;">规律</span>。它仅仅是一个用于<span style="color: black;">方便</span> DOM 操作的普通 JavaScript 函数。在应用程序中,<span style="color: black;">这般</span>的组件依然<span style="color: black;">能够</span>像普通函数<span style="color: black;">同样</span><span style="color: black;">运用</span>:</span></p><span style="color: black;">using(body, <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> Component({ showMessage: <span style="color: black;">true</span> })</span><span style="color: black;">})</span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这种设计思路受到了 SwiftUI 和 Flutter 的影响。其中,第二个回调参数是 SwiftUI 的嵌套组件块的替代品,而</span><span style="color: black;">visible</span><span style="color: black;"> 属性则与 Flutter 中的同名属性相对应。值得<span style="color: black;">重视</span>的是,<span style="color: black;">这儿</span>的 </span><span style="color: black;">visible</span><span style="color: black;"> 并非 Vue 的“hack”,而是用于直接<span style="color: black;">插进</span>或移除 DOM 子树的属性。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">总而言之,<span style="color: black;">咱们</span>无需额外发明抽象语法来模拟<span style="color: black;">咱们</span>需要的<span style="color: black;">行径</span>。JavaScript <span style="color: black;">做为</span>前端<span style="color: black;">研发</span>的“本土”语言,<span style="color: black;">持有</span>其独特的<span style="color: black;">优良</span>和功能。试图用替代<span style="color: black;">方法</span>来规避它,<span style="color: black;">最后</span>只会使问题变得更加<span style="color: black;">繁杂</span>。这一点在以往的<span style="color: black;">研发</span>实践中<span style="color: black;">已然</span>得到了充分的证明。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">在当然,</span><span style="color: black;">visible</span><span style="color: black;"> 属性的应用<span style="color: black;">规律</span>相当直观。接着要解释<span style="color: black;">怎样</span>渲染一个组件列表。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">首要</span>,让<span style="color: black;">咱们</span>看一下<span style="color: black;">关联</span>的代码实现:</span></p><span style="color: black;"><span style="color: black;">export</span> const function User({ key, name, isRestricted }) {</span><span style="color: black;"> h(<span style="color: black;">li</span>, {</span><span style="color: black;"> attr: { id: key },</span><span style="color: black;"> text: name,</span><span style="color: black;"> visible: isRestricted,</span><span style="color: black;"> classList: [<span style="color: black;">"border-gray-200"</span>]</span><span style="color: black;"> })</span><span style="color: black;">}</span><span style="color: black;">using(<span style="color: black;">document</span>.body, <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> h(<span style="color: black;">ul</span>, <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> list(users, <span style="color: black;"><span style="color: black;">({ store: user, key: idx })</span>, <span style="color: black;">()</span> =></span> {</span><span style="color: black;"> User({ key: idx, name: user.name, isRestricted: user.isRestricted })</span><span style="color: black;"> })</span><span style="color: black;"> })</span><span style="color: black;">})</span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这种实现方式在某种程度上借鉴了 SwiftUI 的设计:</span></p><span style="color: black;"><span style="color: black;">List</span>(users) { <span style="color: black;">user</span> <span style="color: black;">in</span></span><span style="color: black;"> <span style="color: black;">// <span style="color: black;">运用</span> user</span></span><span style="color: black;"><span style="color: black;">}</span></span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">更值得<span style="color: black;">重视</span>的是,代码中所有用到的变量或属性都支持响应式更新。这<span style="color: black;">寓意</span>着,当用户列表<span style="color: black;">或</span>其<span style="color: black;">关联</span>属性有所改变,这些改变会即时反映在<span style="color: black;">最后</span>的布局中。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">另外</span>,这种 </span><span style="color: black;">list</span><span style="color: black;"><span style="color: black;">办法</span>实现并不像表面上看起来<span style="color: black;">那样</span>简单。系统会预生成用于该应用的模板(<span style="color: black;">这儿</span>的模板指的是 JS 模板,与 Vue 或其他框架的模板<span style="color: black;">区别</span>)。<span style="color: black;">因此</span>,每当响应式变量</span><span style="color: black;">users</span><span style="color: black;"> <span style="color: black;">出现</span>变化时,<span style="color: black;">咱们</span>只需利用<span style="color: black;">已然</span>预设好的模板生成一个新的实例,而不是在运行时重新计算所有元素。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">但不幸的是,许多现代<span style="color: black;">处理</span><span style="color: black;">方法</span>利用虚拟 DOM 和调和(Reconciliation),引入了<span style="color: black;">周期</span>来双重<span style="color: black;">检测</span>从组件返回的结构的变化。这就<span style="color: black;">引起</span>了重绘和性能问题。以及<span style="color: black;">有些</span>人为的约束。不得不说,Svelte 做得很好。Svelte 不依赖于虚拟 DOM,而是<span style="color: black;">运用</span>编译器将组件转换为 JavaScript。这个 JS 代码会非常<span style="color: black;">有效</span>,<span style="color: black;">然则</span>,遗憾的是,其他问题<span style="color: black;">亦</span><span style="color: black;">显现</span>了:不必要的构建<span style="color: black;">过程</span>,Svelte 特有的代码并<span style="color: black;">无</span>真正从<span style="color: black;">最后</span>的包中移除。<span style="color: black;">况且</span><span style="color: black;">咱们</span>仍然有重渲染的问题。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">针对</span>事件处理器和属性规范,该<span style="color: black;">怎样</span>优雅地管理呢?以下是一个实用的代码示例:</span></p><span style="color: black;"><span style="color: black;">using</span>(document.body, () => {</span><span style="color: black;"> <span style="color: black;">h</span>(<span style="color: black;">section</span>, () => {</span><span style="color: black;"> <span style="color: black;">spec</span>({ <span style="color: black;">style</span>: {<span style="color: black;">width</span>: <span style="color: black;">15em</span>} });</span><span style="color: black;"> <span style="color: black;">h</span>(<span style="color: black;">form</span>, () => {</span><span style="color: black;"> <span style="color: black;">spec</span>({</span><span style="color: black;"> <span style="color: black;">handler</span>: {</span><span style="color: black;"> <span style="color: black;">config</span>: { <span style="color: black;">prevent</span>: true },</span><span style="color: black;"> <span style="color: black;">on</span>: { submit },</span><span style="color: black;"> },</span><span style="color: black;"> <span style="color: black;">style</span>: {</span><span style="color: black;"> <span style="color: black;">display</span>: <span style="color: black;">flex</span>,</span><span style="color: black;"> <span style="color: black;">flexDirection</span>: <span style="color: black;">column</span>,</span><span style="color: black;"> },</span><span style="color: black;"> });</span><span style="color: black;"> <span style="color: black;">h</span>(<span style="color: black;">input</span>, {</span><span style="color: black;"> <span style="color: black;">attr</span>: { <span style="color: black;">placeholder</span>: <span style="color: black;">Username</span> },</span><span style="color: black;"> <span style="color: black;">handler</span>: { <span style="color: black;">input</span>: changeUsername },</span><span style="color: black;"> });</span><span style="color: black;"> <span style="color: black;">h</span>(<span style="color: black;">input</span>, {</span><span style="color: black;"> <span style="color: black;">attr</span>: { <span style="color: black;">type</span>: <span style="color: black;">password</span>, <span style="color: black;">placeholder</span>: <span style="color: black;">Password</span> },</span><span style="color: black;"> <span style="color: black;">classList</span>: [<span style="color: black;">w-full</span>, <span style="color: black;">py-2</span>, <span style="color: black;">px-4</span>],</span><span style="color: black;"> <span style="color: black;">handler</span>: { <span style="color: black;">input</span>: changePassword },</span><span style="color: black;"> });</span><span style="color: black;"> <span style="color: black;">h</span>(<span style="color: black;">button</span>, {</span><span style="color: black;"> <span style="color: black;">text</span>: <span style="color: black;">Submit</span>,</span><span style="color: black;"> <span style="color: black;">attr</span>: {</span><span style="color: black;"> <span style="color: black;">disabled</span>: fields.map(</span><span style="color: black;"> fields => !(fields.username && fields.password),</span><span style="color: black;"> ),</span><span style="color: black;"> },</span><span style="color: black;"> });</span><span style="color: black;"> });</span><span style="color: black;"> });</span><span style="color: black;">});</span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">在这段代码中,</span><span style="color: black;">changeUsername</span><span style="color: black;"> 和 </span><span style="color: black;">changePassword</span><span style="color: black;"> 是用于响应用户输入并动态更新相应值的事件处理器。而 </span><span style="color: black;">fields</span><span style="color: black;"> 是一个<span style="color: black;">包括</span><span style="color: black;">关联</span>属性的响应式对象。<span style="color: black;">实质</span>上,这个 </span><span style="color: black;">fields</span><span style="color: black;"> 对象<span style="color: black;">便是</span>一个数据存储,不论个人<span style="color: black;">爱好</span><span style="color: black;">怎样</span>。<span style="color: black;">咱们</span>还采用了 </span><span style="color: black;">map()</span><span style="color: black;"> <span style="color: black;">办法</span>来创建一个派生属性,这在 Svelte 中对应 </span><span style="color: black;">$derived</span><span style="color: black;">。这个派生属性会在用户名或<span style="color: black;">秘码</span><span style="color: black;">出现</span>变更时同步更新,从而改变提交按钮的状态。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">针对</span>这段代码,你初次浏览可能会有以下几种看法:</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这种写法不太<span style="color: black;">平常</span></span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">代码过于繁琐</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">需要手动处理 DOM API 的各个细节</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">然而,事实真的是<span style="color: black;">这般</span>吗?</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">首要</span>,代码中并<span style="color: black;">无</span>什么<span style="color: black;">反常</span>的内容,这些都是<span style="color: black;">基本</span>的 JavaScript 函数。<span style="color: black;">详细</span><span style="color: black;">来讲</span>:</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">attr </span><span style="color: black;">- 用于定义节点属性的对象。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">style</span><span style="color: black;"> - 用于设置节点样式的对象。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">classList</span><span style="color: black;"> - 一个<span style="color: black;">包括</span>节点类名的数组,该名<span style="color: black;">叫作</span>与 DOM API 的官方命名 一致。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">handler</span><span style="color: black;"> - 节点事件处理器的配置对象,如你所见 </span><span style="color: black;">config: { prevent: true }</span><span style="color: black;">。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">spec</span><span style="color: black;">- 实质上是一个包装函数,用于描述节点属性类别。当组件的回调函数内有子元素时,你<span style="color: black;">能够</span>在组件的最外层(<span style="color: black;">或</span>回调函数中的任何<span style="color: black;">地区</span>,尽管这并不是重点)设定一组属性。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">确实,相比于 React、Vue、Svelte、Solid 等,这种方式更显繁琐。但<span style="color: black;">这般</span>的设计方式不会让你对前端的<span style="color: black;">繁杂</span>性有所误解,<span style="color: black;">亦</span>不会给你一个<span style="color: black;">所说</span>的“简单<span style="color: black;">处理</span><span style="color: black;">方法</span>”。事实上,你应该面对这些现实,而不是逃避。这会让你更清晰地<span style="color: black;">认识</span>应用是<span style="color: black;">怎样</span>构建的。虽然这种<span style="color: black;">办法</span>比较繁琐,但它真的<span style="color: black;">繁杂</span>到让你难以理解吗?我相信你完全能够理解每一行代码的<span style="color: black;">功效</span>。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">其次,你并不需要直接操作 DOM API。你真正需要的是一个简洁的 JavaScript API 用于与 DOM 进行交互。我坚信,视图树的管理应该由原生工具来完成。<span style="color: black;">哪些</span>需要手动添加、删除、更新树结构的操作都<span style="color: black;">能够</span>由底层技术来完成。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">我要再次强调,我的目的不是推崇某个特定的新技术<span style="color: black;">处理</span><span style="color: black;">方法</span>。相反,我<span style="color: black;">期盼</span>能指<span style="color: black;">显现</span>有<span style="color: black;">方法</span>中存在的问题,并讨论<span style="color: black;">怎样</span>用原生工具来<span style="color: black;">处理</span>这些问题,而无需重新发明轮子。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">最后,我想提醒<span style="color: black;">大众</span>,尊重你所<span style="color: black;">运用</span>的平台是很重要的。其他平台的<span style="color: black;">研发</span>人员都<span style="color: black;">已然</span>学会了<span style="color: black;">怎样</span>与<span style="color: black;">她们</span>的平台和谐共处。与此<span style="color: black;">区别</span>,前端<span style="color: black;">研发</span>人员有时会尝试用新的、还<span style="color: black;">不足</span>成熟的<span style="color: black;">处理</span><span style="color: black;">方法</span>来<span style="color: black;">处理</span>问题。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-tjoges91tu/b9f6990fbedf87070fbcfd52383245b1~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1728111566&x-signature=NCZg7ar3c%2B0fxv3yj0mdtvqhD%2Fs%3D" style="width: 50%; margin-bottom: 20px;"></p><h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><strong style="color: blue;"><span style="color: black;">事情并没<span style="color: black;">那样</span>简单</span></strong></span></h2><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">用简单的例子来展示<span style="color: black;">实质</span>场景是有难度的,<span style="color: black;">由于</span>某些问题在简单的例子中可能不会显现。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">例如</span>,在一个真实应用中,你可能会<span style="color: black;">这般</span>描述一个表单:</span></p><span style="color: black;"><span style="color: black;">export</span> <span style="color: black;">const</span> Auth = <span style="color: black;"><span style="color: black;">()</span>=></span> {</span><span style="color: black;"> h(<span style="color: black;">"div"</span>, <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> spec({</span><span style="color: black;"> classList: [<span style="color: black;">"mt-10"</span>, <span style="color: black;">"max-w-sm"</span>, <span style="color: black;">"w-full"</span>],</span><span style="color: black;"> });</span><span style="color: black;"> h(<span style="color: black;">"form"</span>, <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> Input({</span><span style="color: black;"> <span style="color: black;">type</span>: <span style="color: black;">"email"</span>,</span><span style="color: black;"> label: <span style="color: black;">"电子邮件"</span>,</span><span style="color: black;">inputChanged: authForm.fields.email.changed,</span><span style="color: black;"> errorText: authForm.fields.email.$errorText,</span><span style="color: black;"> errorVisible: authForm.fields.email.$errors.map(<span style="color: black;">Boolean</span>),</span><span style="color: black;"> });</span><span style="color: black;"> Input({</span><span style="color: black;"> <span style="color: black;">type</span>: <span style="color: black;">"password"</span>,</span><span style="color: black;"> label: <span style="color: black;">"<span style="color: black;">秘码</span>"</span>,</span><span style="color: black;">inputChanged: authForm.fields.password.changed,</span><span style="color: black;"> errorText: authForm.fields.password.$errorText,</span><span style="color: black;"> errorVisible: authForm.fields.password.$errors.map(<span style="color: black;">Boolean</span>),</span><span style="color: black;">});</span><span style="color: black;"> Button({</span><span style="color: black;"> text: <span style="color: black;">"创建"</span>,</span><span style="color: black;"> event: authForm.submit,</span><span style="color: black;"> size: <span style="color: black;">"base"</span>,</span><span style="color: black;"> prevent: <span style="color: black;">true</span>,</span><span style="color: black;"> variant: <span style="color: black;">"default"</span>,</span><span style="color: black;"> });</span><span style="color: black;"> ErrorHint($authError, $authError.map(<span style="color: black;">Boolean</span>));</span><span style="color: black;"> });</span><span style="color: black;"> });</span><span style="color: black;">};</span><span style="color: black;">...</span><span style="color: black;">export<span style="color: black;">const</span> Input = <span style="color: black;">(<span style="color: black;">{</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> value,</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> <span style="color: black;">type</span>,</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> label,</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> required,</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> inputChanged,</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> errorVisible,</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> errorText,</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;">}: {</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> value?: Store<<span style="color: black;">string</span>>;</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> <span style="color: black;">type</span>: <span style="color: black;">string</span>;</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> label: <span style="color: black;">string</span>;</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> required?: <span style="color: black;">boolean</span>;</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;">inputChanged: Event<<span style="color: black;">any</span>>;</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> errorVisible?: Store<<span style="color: black;">boolean</span>>;</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> errorText?: Store<<span style="color: black;">string</span>>;</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;">}</span>) =></span> {</span><span style="color: black;"> h(<span style="color: black;">"div"</span>, <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> spec({</span><span style="color: black;"> classList: [<span style="color: black;">"mb-6"</span>],</span><span style="color: black;"> });</span><span style="color: black;"> h(<span style="color: black;">"label"</span>, <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> spec({</span><span style="color: black;">classList: [<span style="color: black;">"block"</span>, <span style="color: black;">"mb-2"</span>, <span style="color: black;">"text-sm"</span>, <span style="color: black;">"font-medium"</span>, <span style="color: black;">"text-gray-900"</span>, <span style="color: black;">"dark:text-white"</span>],</span><span style="color: black;"> text: label,</span><span style="color: black;"> });</span><span style="color: black;"> });</span><span style="color: black;"> h(<span style="color: black;">"input"</span>, <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> <span style="color: black;">const</span>localInputChanged = createEvent<<span style="color: black;">any</span>><span style="color: black;"><span style="color: black;">()</span>;</span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;">sample</span>(<span style="color: black;">{</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> source: localInputChanged,</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> fn: (<span style="color: black;">event</span>) => event.target.value,</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> target: inputChanged,</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> }</span>);</span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;">spec</span>(<span style="color: black;">{</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> classList: [</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "bg-gray-50",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "border",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;">"border-gray-300",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "text-gray-900",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "text-sm",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "rounded-lg",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "focus:ring-blue-500",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "focus:border-blue-500",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "block",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "w-full",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "p-2.5",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "dark:bg-gray-700",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;">"dark:border-gray-600",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "dark:placeholder-gray-400",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "dark:text-white",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "dark:focus:ring-blue-500",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> "dark:focus:border-blue-500",</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> ],</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> attr: { <span style="color: black;">type</span>: <span style="color: black;">type</span>, required: <span style="color: black;">Boolean</span>(<span style="color: black;">required</span>), value: value || createStore(<span style="color: black;">""</span>) },</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> handler: { on: { input: localInputChanged } },</span></span></span><span style="color: black;"><span style="color: black;"><span style="color: black;"> }</span>);</span></span><span style="color: black;"><span style="color: black;"> });</span></span><span style="color: black;"><span style="color: black;"> <span style="color: black;">ErrorHint</span>(<span style="color: black;">errorText, errorVisible</span>);</span></span><span style="color: black;"><span style="color: black;"> });</span></span><span style="color: black;"><span style="color: black;">};</span></span><span style="color: black;"><span style="color: black;">...</span></span><span style="color: black;"><span style="color: black;"><span style="color: black;">export</span> <span style="color: black;">const</span> <span style="color: black;">ErrorHint</span> = (<span style="color: black;">text: Store<<span style="color: black;">string</span>> | <span style="color: black;">string</span> | <span style="color: black;">undefined</span>, visible: Store<<span style="color: black;">boolean</span>> | <span style="color: black;">undefined</span></span>) =></span> {</span><span style="color: black;"> h(<span style="color: black;">"p"</span>, {</span><span style="color: black;"> classList: [<span style="color: black;">"mt-2"</span>, <span style="color: black;">"text-sm"</span>, <span style="color: black;">"text-red-600"</span>, <span style="color: black;">"dark:text-red-400"</span>],</span><span style="color: black;"> visible: visible || createStore(<span style="color: black;">false</span>),</span><span style="color: black;"> text: text || createStore(<span style="color: black;">""</span>),</span><span style="color: black;"> });</span><span style="color: black;">};</span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">运用</span>带有标签、属性和动态内容的预定义卡片来描述<span style="color: black;">有些</span>日志列表怎么样?</span></p><span style="color: black;"><span style="color: black;">export</span> const LogsList = <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;">h(<span style="color: black;">"div"</span>, <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> spec({</span><span style="color: black;"> classList: [<span style="color: black;">"flex"</span>, <span style="color: black;">"flex-col"</span>, <span style="color: black;">"space-y-6"</span>, <span style="color: black;">"mt-2"</span>],</span><span style="color: black;"> });</span><span style="color: black;"> list(logModel.$logsGroups, <span style="color: black;"><span style="color: black;">({ store: group })</span> =></span> {</span><span style="color: black;"> CardHeaded({</span><span style="color: black;"> tags: group.map(<span style="color: black;"><span style="color: black;">(g)</span>=></span> g.tags),</span><span style="color: black;"> href: group.map(<span style="color: black;"><span style="color: black;">(g)</span> =></span> `<span style="color: black;">${g.schema_name}/${g.group_hash}</span>`),</span><span style="color: black;"> content: <span style="color: black;"><span style="color: black;">()</span> =></span> {</span><span style="color: black;"> LogsTable(group.map(<span style="color: black;"><span style="color: black;">(g)</span> =></span> g.logs));</span><span style="color: black;"> },</span><span style="color: black;"> withMore: <span style="color: black;">true</span>,</span><span style="color: black;"> });</span><span style="color: black;"> });</span><span style="color: black;"> });</span><span style="color: black;">};</span><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">无需深究<span style="color: black;">这儿</span>的 </span><span style="color: black;">createStore</span><span style="color: black;"> 和 </span><span style="color: black;">createEvent</span><span style="color: black;">,</span><span style="color: black;">Store</span><span style="color: black;"> 本质上是一个响应式数据结构,而 </span><span style="color: black;">Event</span><span style="color: black;"> 则是用于修改这些数据或触发某种效果的信号,这些都<span style="color: black;">能够</span>从任何库中获取。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">这儿</span>的关键点是<span style="color: black;">怎样</span>描述视图和视图<span style="color: black;">规律</span>。即使视图描述存在差异,<span style="color: black;">亦</span>不<span style="color: black;">寓意</span>着<span style="color: black;">必定</span>要寻求全新的<span style="color: black;">处理</span><span style="color: black;">方法</span>。你<span style="color: black;">是不是</span>确信现有<span style="color: black;">方法</span><span style="color: black;">已然</span>是最优的?<span style="color: black;">倘若</span>不是,你能<span style="color: black;">知道</span>指出<span style="color: black;">原由</span>吗?</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-tjoges91tu/751d43f744ecde8529da76992b12614d~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1728111566&x-signature=toIEd%2FHMY6bG%2B%2Bi5cgpJiqxsZpY%3D" style="width: 50%; margin-bottom: 20px;"></p><h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><strong style="color: blue;"><span style="color: black;"><span style="color: black;">为何</span><span style="color: black;">咱们</span>需要改变思维方式</span></strong></span></h2><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">你<span style="color: black;">亦</span>许会误以为我对现有的主流<span style="color: black;">处理</span><span style="color: black;">方法</span>持批判态度,但事实并非如此。我相信这些技术在<span style="color: black;">必定</span>程度上都是必要的。<span style="color: black;">或</span>说,曾经是必要的,<span style="color: black;">最少</span><span style="color: black;">针对</span><span style="color: black;">通常</span>的前端<span style="color: black;">研发</span>而言。但我不<span style="color: black;">爱好</span>的是,<span style="color: black;">咱们</span>似乎陷入了过去十年的思维模式,<span style="color: black;">无</span>人在主流中试图提醒<span style="color: black;">研发</span>者<span style="color: black;">重视</span>这个问题。结果,<span style="color: black;">咱们</span>的应用程序仍然<span style="color: black;">无</span>可重现性,<span style="color: black;">况且</span>即使是简单的任务,<span style="color: black;">亦</span>需要很高的劳动强度。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">我并不<span style="color: black;">意见</span><span style="color: black;">咱们</span>抛弃所有现有的<span style="color: black;">处理</span><span style="color: black;">方法</span>,<span style="color: black;">这般</span>做是愚蠢的。我<span style="color: black;">亦</span>不<span style="color: black;">意见</span>每次都自己手动操作 DOM。这些工作应由库 / 框架 / 技术 / API / 或其他何种形式来完成。我只想说,<span style="color: black;">亦</span>许是时候停止实施存在严重设计缺陷的独特的“雪花”类型解决<span style="color: black;">方法</span>了?并<span style="color: black;">起始</span>利用<span style="color: black;">咱们</span>自己的平台<span style="color: black;">供给</span>给<span style="color: black;">咱们</span>的东西,发挥其<span style="color: black;">功效</span>。<span style="color: black;">亦</span>许不是以之前呈现的形式,但以某种其他形式。<span style="color: black;">最少</span>在我看来,存在潜在的可能性。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">然而,<span style="color: black;">非常多</span>人并<span style="color: black;">无</span>认识到当前做法的局限性,反而继续在<span style="color: black;">有些</span>独特的但有严重设计缺陷的<span style="color: black;">处理</span><span style="color: black;">方法</span>中做<span style="color: black;">选取</span>。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">前端<span style="color: black;">研发</span>者应该尊重自己的平台,不要被过时的技术所<span style="color: black;">捆绑</span>,而要勇于面对现实和进行技术创新。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">你认为 UI 架构在过去十年停滞的<span style="color: black;">原由</span>是什么?你认为应该从<span style="color: black;">那些</span>方面进行创新性突破?欢迎在评论区留言讨论。</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">参考链接</p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">runes 的<span style="color: black;">仔细</span>介绍:https://svelte.dev/blog/runes</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">node.append():https://developer.mozilla.org/en-US/docs/Web/API/Element/append</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">node.appendChild():https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">node.remove():https://developer.mozilla.org/en-US/docs/Web/API/Element/remove</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">node.isConnected:https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">DOM API 的官方命名:https://developer.mozilla.org/en-US/docs/Web/API/Element/classList</span></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://p26-sign.toutiaoimg.com/tos-cn-i-tjoges91tu/1ce8925ef6864e3868bd6acc301e472c~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1728111566&x-signature=0IZ0ppJHiSC7p3udgjirWL7OfTY%3D" style="width: 50%; margin-bottom: 20px;"></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">欢迎参与 CSDN 重磅发起的《2023 AI <span style="color: black;">研发</span>者生态调查问卷》,分享您真实的 AI <span style="color: black;">运用</span>体验,更有精美好礼等你拿!</span></strong></p><p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://p3-sign.toutiaoimg.com/tos-cn-i-tjoges91tu/7b9207424fcac0f7467fdd6a37f8d6f9~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1728111566&x-signature=a3rVt9I%2FPM8zPS8dLiYPrlGX4Z4%3D" style="width: 50%; margin-bottom: 20px;"></p></div></div> 回顾历史,我们不难发现:无数先辈用鲜血和生命铺就了中华民族复兴的康庄大道。
页:
[1]