资讯专栏INFORMATION COLUMN

Angular 1.3 one-time binding介绍

antyiwei / 1505人阅读

摘要:本片文章是这个系列的第一篇,将介绍这其中最重要的一个新特性。正是为解决此问题而生的。在介绍之前,先理解一下数据绑定和的的概念。中引入了一种新语法用于表示指令绑定的。注意按钮的作用是把更新为,不过再试试看不会再发生改变原文链接

Angular 1.3 版本终于放出,在更新了许多新特性的同时也修复了许多bug并且带来性能提升。为了帮助自己也帮助别人更早理解这些新特性,接下来将会有一个系列文章去介绍这些主要的新特性和改进。本片文章是这个系列的第一篇,将介绍这其中最重要的一个新特性:one-time bindng。

唉,先别急!我记得Angular的数据绑定是自动保持UI同步更新的啊?没错,这个特点非常重要,但不一定所有地方都需要。这种数据绑定的方式需要框架时刻监视着所有绑定过的数据,这种方式真的很消耗性能。one-time binding 正是为解决此问题而生的。在介绍 one-time binding 之前,先理解一下数据绑定和watcher的的概念。

理解数据绑定和watchers

为了实现数据绑定,Angular 使用了 $watch API去观察 scope 上的数据的改动。其中 scope 具体是什么如何形成的取决于你的代码。如果你没有手动创建一个 child scope ,例如通过 ngController 指令去创建,那么你可能是在和 $rootScope 打交道,这个 $rootScope 是指当前应用的一般通过 ngApp 指令创建的根 scope。

和 scope 打交道并观察其中的变化一般总是要用到所谓的 watcher 。Watchers 通过 DOM 中的 directives 注册。比方说通过直接 interpolation 指令去同步 scope 模型的值:

Hello {{name}}!

这个 interpolation 指令注册了一个用于 $rootScope 上 name 属性的 watcher,从而可以更新绑定了这个属性值的DOM。

我们可以在 socpe 上通过标识符直接定义一个属性并同时给它赋值,这样它就可以直接在DOM中显示:

angular.module("maApp", [])
.run(function($rootScope) {
  $rootScope.name = "Pascal";
});

我们刚刚通过 interpolation 指令在 view 上绑定了一了一个 model 值,如果改变它的值,view 也会同时自动更新。可以通过添加一个按钮实现更新 name 属性值的操作:


点击这个按钮会把 Christoph 赋给 name 属性,这触发了一个 $digest 可以保持 DOM 相应更新的轮询。在这个例子中数据的更新只是单向的(上->下)。如果是在用到 ngModel 的 input 元素的例子中,用户可以输入内容改变这个属性的值,同时改变也实时的返回到实际的 model 上。

这些是因为一个 $digest 轮询被触发才发生的,Angular 负责处理所有当前 scope 和它的 child scope 上注册过的 watchers,并检查 model 是否经过改动,然后直到 model 稳定调用并且没有更多的 listeners 被点燃,对应的 listeners 被调用。
以下是以上描述的代码效果展示:
plnkr

太多watcher的问题

现在我们已经对 Angular 中的数据绑定机制有了一个大致的了解,那么可能想到为什么会需要 one-time binding 这样的特性呢?

鉴于使用 watcher 来实现数据绑定的本质,我们可能会遇到有太多 watcher 时较差性能的问题。正如我们所了解的那样,watch expressions 和他们对应的 callback listeners 都是是注册在 scope 上的,基于此 Angular 可以在 $digest 轮询的时候处理它们也就保持了相应的 view 更行。简单地说,越多 watchers 被注册,Angular 要处理的也就越多。

现在想象一种有许多动态值在 view 中的场景。比如国际化过程是非常常见的一种情况,需要 Angular 的数据绑定去做应用的本地化,尽管语言只在初始设置页才会更改,而在运行时是不会改变的。此情景下每一个字符串都被本地化到 view 中,同时也被写入到 scope 里,并且注册一个对应的 watcher 用于下次 $digest 轮询时可能的更新。如果语言的确不太可能在运行时改变,这样的代价实在是太高了。

one-time binding 来拯救你们了!

终于到了主角登场的时刻了。那么什么是 one-time bindings ?文档里是这么说的:

  

One-time expressions will stop recalculating once they are stable, which happens after the first digest…
第一次 digest 后,One-time 表达式一旦稳定后就不会再更新。

上面提到的场景的确是 Angular 应当处理的问题。Angular 1.3 中引入了一种新语法用于表示 interpolation 指令绑定的 one-time。只需要在表达式前加入 :: 双引号即可。同样是上面的例子,我们只需要把:

Hello {{name}}!

改为:

Hello {{::name}}!

这同样适用于其他 Angular 中典型的表达式。例如在 ng-repeat 表达式中或者仅需要从内部暴露出一个属性值的指令(不会从外部改变),只需要在外部把它设置为 one-time 表达式:


下面是实际例子中的效果,已经把上面例子中的 name 改成了 ::name表示 one-time binding,其他则代码完全一样。注意按钮的作用是把 name 更新为 Christoph,不过再试试看:
plnkr
name不会再发生改变!

原文链接

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85347.html

相关文章

  • Angular 1 深度解析:脏数据检查与 angular 性能优化

    摘要:通常写代码时我们无需主动调用或是因为在外部对我们的回调函数做了包装。类似的不只是这些事件回调函数,还有等。常量依旧会重复检查。会检查中有没有一个名为的成员。 TL;DR 脏检查是一种模型到视图的数据映射机制,由 $apply 或 $digest 触发。 脏检查的范围是整个页面,不受区域或组件划分影响 使用尽量简单的绑定表达式提升脏检查执行速度 尽量减少页面上绑定表达式的个数(单次绑定...

    fasss 评论0 收藏0
  • Angular 1 深度解析:脏数据检查与 angular 性能优化

    摘要:通常写代码时我们无需主动调用或是因为在外部对我们的回调函数做了包装。类似的不只是这些事件回调函数,还有等。常量依旧会重复检查。会检查中有没有一个名为的成员。 TL;DR 脏检查是一种模型到视图的数据映射机制,由 $apply 或 $digest 触发。 脏检查的范围是整个页面,不受区域或组件划分影响 使用尽量简单的绑定表达式提升脏检查执行速度 尽量减少页面上绑定表达式的个数(单次绑定...

    VioletJack 评论0 收藏0
  • angular表单验证2

    摘要:表单验证使用场景在实际的开发中我们可能会有这样的情况。姓名不能为空姓名太短姓名太长姓名不能为空姓名太短姓名太长借助表单本身比之前的更简单了。结尾以上就是关于表单验证的全部内容。 前言 在之前的文章《angular表单验证》中主要介绍了一些关于angular表单验证的基础知识。在此篇中将着重以扩展angular表单验证的相关内容和实际开发中的应用为主。 表单验证使用场景1 在实际的开发...

    darkbug 评论0 收藏0
  • Controller As in Angularjs

    摘要:因为在里面是基于原型进行继承的。事实上注入后,即提供了一个,可以在这个上面绑定属性和方法。当使用语法的时候,事实上是绑定到了的对象上面。注意这个地方执行顺序是从子元素开始再到父元素的。即在执行阶段前确保执行完毕。 Controller As angular .module(app, []) .controller(DemoController, ...

    mo0n1andin 评论0 收藏0
  • MVC MVP MVVM

    摘要:,的事件回调函数中调用的操作方法。以为例调用关系模式实际就是将中的改名为,调用过程基本一致,最大的改良是间的双向绑定。和间,有一个对象,可以操作修改,使用。 参考:MVC,MVP 和 MVVM 的图示 - 阮一峰http://www.ruanyifeng.com/blo...Web开发的MVVM模式http://www.cnblogs.com/dxy198...界面之下:还原真实的MV...

    wushuiyong 评论0 收藏0

发表评论

0条评论

antyiwei

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<