不同于双向绑定,单向绑定更多的是从性能优化的角度出发的。

我们知道,模板依赖于数据才能渲染,当数据更新时,模板理应得到更新,但这里存在一个问题,模板是全量更新还是局部更新呢?

如果没有单向绑定,毫无疑问,模板只能全量更新,因为它不知道变化的数据对应模板的什么部分。当模板比较复杂时,比如渲染一个大列表,全量更新的性能消耗非常严重,甚至可能带来明显的丢帧。

因此,我们特地设计了单向绑定指令,绑定方式有三种:

  1. 绑定 DOM 元素的 Attribute
  2. 绑定 DOM 元素的 Property
  3. 绑定组件的 Property

绑定 DOM 元素的 Attribute

<div class="{{className}}">
    绑定 className 数据到 class 属性
</div>

当 DOM 元素的 attribute value 有且只有一个表达式,并且这个表达式支持预分析 keypath 时,会自动生成一个属性绑定。

如示例中的 className 会绑定到 class 这个 attribute,当 className 变化时,仅会带来一次 setAttribute 操作,代价非常小。

绑定 DOM 元素的 Property

目前仅支持两种 property,即 innerHTMLinnerText

<!-- html 绑定到 innerHTML -->
<div>
    {{{html}}}
</div>

<!-- text 绑定到 innerText -->
<div>
    {{text}}
</div>

需要注意的是,元素的子元素有且只能有一个表达式,并且这个表达式支持预分析 keypath

绑定组件的 Property

组件和元素很类似,因此绑定组件的 Property 和绑定 DOM 元素的 Attribute 条件是相同的。

此外,组件还支持延展属性传值,延展出来的属性,同样会自动生成属性绑定,但有一个前提,延展的表达式支持预分析 keypath

预分析 Keypath 的表达式

以上三种绑定方式的前提都是表达式支持预分析 keypath。简单的说,支持预分析 keypath 的表达式只有以下两种:

  1. 标识符,或者说变量
  2. 属性访问,或者说访问对象的属性或数组的下标
// 标识符
{{user}}
{{name}}

// 属性访问
{{user.name}}
{{users.0.name}}

// 举一个反例
{{users[ index ].name}}

如果表达式在编译阶段就能分析出 keypath,我们认为它是可绑定的,否则不能绑定。

反例中,keypath 还依赖于运行时的 index,因此我们无法确定 keypathusers.0.name 还是 users.1.name

支持预分析 keypath的表达式,换句话说,这个表达式是静态的,因此我们可以监听 keypath 的变化。

如果表达式不是静态的,在运行时会充满各种可能性,增加不可预知的风险,为了保持简单,我们就这么愉快的决定了。

results matching ""

    No results matching ""