数据绑定最早是被 Angular、Backbone 和 Ember 等框架推广而流行开来的,现在则在某种程度上是编写视图的标准途径 。它能让“视图作为数据的函数”,意味着每当某些数据发生变化时,相关视图将“自动”更新 。
不需要冗长的 DOM 操作来保持数据和视图同步,只需更新数据,视图就会随之变化 。这是一项杀手级功能,如今但凡理智的开发人员就会用它 。所以很容易理解为什么开发人员会使用提供了数据绑定功能的框架,就算框架对于应用来说太大材小用也无所谓:既然框架打理好了一切,何必要费心费力处理那些麻烦的 DOM 操作呢?
但数据绑定并不是什么魔法,你用不着为了用它而动用整个框架 。在 Web 组件里只需要几行代码就能轻松搞定数据绑定了,没什么特殊的 。
如何实现
就像我上面说的那样 , 数据绑定并没有那么神奇 。当基础数据发生变化时,你的视图不是凭空“神奇”地更新的 。在框架深处,不为人知的某个角落里的设置代码负责在数据更改时调用并更新视图 。
AngularJS 使用了所谓的“摘要循环”:这是一种粗暴的检查机制 , 不断检查哪些数据已更改,以便随时更新对应的视图 。
React 面世时提供了另一种据称性能更好的解决方案,称为虚拟 DOM:它是一种 DOM 的 JavaScript 表示,只更新已更改的 DOM 部分 。这对列表来说很合适——列表的少数项目发生变化时无需重新渲染整个列表,只需更新已更改的项目 。
哪种工具最合适?
图源:https://xkcd.com/974/
这对于具有复杂 UI 的较大应用程序来说非常有用 , 但对于大多数应用程序来说实在有些杀鸡用牛刀了 。编写一些监视数据的代码并在数据发生变化时更新相关视图并不是什么难事 。问题是这些数据通常需要传递给也需要数据绑定的子组件,所以最后往往会有很多 DOM 操作 。
你需要的是一种在数据被推送到子组件时触发子组件中相同的数据绑定操作的方法 。只要父组件的数据发生更改并且某些数据绑定到子组件的视图,该子组件的视图也需要更新 。
一种方法是利用所有组件的基类,因为 Web 组件是使用 JavaScript 类创建的,所以这是一个很好的选择 。默认情况下 Web 组件扩展 HTMLElement,但我们也可以创建自己的基类来扩展 HTMLElement,如下所示:
我们将 CustomElement 的内部 state 属性绑定到视图来实现数据绑定:
通过标准 data 属性将值绑定到视图上,在本例中为 data-bind:
例如下面这样:
this.state.user.address.city,并将数据对象中的键转换为 user.address.city , 然后使用它来查找这个数据绑定的元素:
每当数据绑定到元素的特定属性(如 data-bind=“name:user.address.city”)时,组件将检查该元素是否也是扩展 CustomElement 的 Web 组件;如果是,则通过它的 setState 方法更新该属性 。这样,数据绑定就能一直传播到所有子组件上 。
如果绑定数据的元素是常规 HTML 元素,那么将简单地更新其 textContent 。在这两种情况下,只需几行代码即可有效实现 DOM 的更新 。
列表该怎么处理?
像虚拟 DOM 这样的解决方案真正的用武之地是渲染列表 。例如只更改列表的一部分时,虚拟 DOM 将仅更新已更改的部分,而不是重新渲染整个列表 。
其机制是在第一次渲染列表时创建 DOM 节点 , 然后在列表更改时只更新这些现有节点(textContent、属性等) 。复用已经创建的节点比重新渲染整个列表重建所有节点的开销小得多,因此对于非常大的列表来说这种方法效率更高 。
但如果你的列表平均只有 25 个项目时,你可能会想知道重新渲染整个列表能比虚拟 DOM 的方法慢多少 。当你渲染 250 个项目时可能会变得很慢,但理智的开发人员在这种情况下就应该分页了 。
我不是说大家就应该抛弃虚拟 DOM,因为它的确是很棒的技术 。如果遇到真正需要虚拟 DOM 的情况,自然一定要使用它 。我只是希望大家遇到比较轻量的问题时先思考一下能不能找到一个比较轻量的解决方案,而不是上来就动用重量级的杀手锏 。
customElement 演示的 Github 仓库包含一个 Web 组件,它在 li 标签内渲染任何设置为其 items 属性的字符串数组 。只要将 items 设置为新数组它就会重新渲染整个列表,但是复用现有的 li 标记也很简单 。
结论
答案很清楚了,只需几行代码即可对 Web 组件进行声明式数据绑定 。我觉得自己已经清楚地证明了数据绑定很容易实现,并且你不需要动用整个框架也能使用它 。
上面提到的 Github 仓库中的代码不是 React 或 Vue.js 等框架的替代品,本来也没这个意思 。框架提供的并不只有数据绑定,本文和涉及的代码是为了证明你不一定需要一个框架来实现声明式数据绑定 。
【详解dropdownlist控件用法 dropdownlist绑定数据库怎么用 - 秒懂生活 www.miaodongshenghuo.com】
除了数据绑定之外,customElement 还提供了一些方便的方法来选择元素以及显示和隐藏元素 。