zoukankan      html  css  js  c++  java
  • 数据绑定

    AngularJS应用开发思维之2:数据绑定

    在声明式模板中显示数据

    因为不能像jQuery一样将DOM操作混在模板里,声明式模板很快让我们变得束手束脚。

    一个典型的问题:在声明式模板里怎么显示数据?

    假设我们有某人的基本信息,保存在一个json对象里:

    1. var sb = {
    2. name : 'somebody',
    3. gender : 'male',
    4. age : 28
    5. };

    我们定义一个指令ez-namecard,希望它经过编译后会展开成这样:

    1. <div>
    2. <div>name : somebody </div>
    3. <div>gender : male </div>
    4. <div>age : 28</div>
    5. </div>

    那么,怎么把sb这个json对象指定给ez-namecard这个指令?

    将数据传递给指令

    一个容易想到的方法,就是给指令ez-namecard增加一个属性,用这个属性的值 指定数据对象的变量名称。

    这相当于,用属性向指令(解释器)传递参数:

    1. <ez-namecard data="window.sb"></ez-namecard>

    这样的话,ez-namecard的解释器只要检查data属性,然后执行一个eval()就可以获得sb的值, 从而将其内容填充到展开的div片段中。

    BINGO!

    示例:http://www.hubwiz.com/course/54f3ba65e564e50cfccbad4b/

    作用域/Scope

    不过,请注意,前面定义的sb变量,默认是挂在window对象(命名空间)上的,即window.sb。 如果所有的数据都挂在window上,保不齐哪天就会出现变量的命名冲突。

    AngularJS引入了一个自用的命名空间,也就是$rootScope对象,这样sb变量就可以 挂在$rootScope上了,即$rootScope.sb。

    引入了scope的代码参见→_→。

    在HTML模板中,我们用了两个内置指令:

    • ng-app指令会在启动引导时创建一个$rootScope对象。
    • ng-init指令用来在作用域上初始化变量,这个指令将在$rootScope上建立sb对象。

    在指令的实现代码中,与之前使用eval函数进行表达式估值不同,我们直接使用scope的$eval方法获 得sb变量的值。

    你可能注意到,这个scope是link函数传入的参数,它和我们说的$rootScope是一个东西吗?

    层级的作用域

    在AngularJS中,ng-app开始的DOM子树上,每个DOM对象都有一个对应的scope对象。 比如,在我们的示例中,body对象对应一个scope对象(因为body元素有ng-app属性,所以 这个scope就是$rootScope对象),ez-namecard对象也对应一个scope对象......

    scope hierarchy

    在默认情况下,一个DOM子元素不会创建新的作用域,也就是说,这个子元素所对应的 scope对象,其实就是它的最近一级的祖先对象对应的scope对象。比如,在我们的例子中, ez-namecard对应的scope对象,就是它的父对象即body对象的scope对象,恰好也就是 $rootScope对象;而ez-namecard有3个div子元素对应的scope对象,也是$rootScope对象。

    有些指令会导致创建新的作用域,比如ng-controller。如果在一个DOM对象上创建了新 的作用域,那么这个scope对象的原型是其最近一级的组件对象的scope对象。

    比如在我们的例子中,如果在ez-namecard上使用ng-controller指令,那么ez-namecard 对应的scope对象就不再是body对应的$rootScope对象,但是由于是原型继承,所以通过 这个scope依然可以访问到sb变量。

    示例:http://www.hubwiz.com/course/54f3ba65e564e50cfccbad4b/

    监听数据的变化

    我们已经实现了将数据显示到界面上,不过这还不够。

    由于编译仅仅在启动引导时执行一次,这意味着我们的link函数只会被调用一次,那么, 如果数据变化,在界面上将不会有任何反馈,即界面和数据将变得不同步了。

    这需要持续监听数据的变化。

    好在AngularJS的scope对象可以使用$watch()方法,对建立在其上的变量的变化进行监听:

    1. $watch(watchExpression, listener, [objectEquality]);

    $watch方法要求传入三个参数:

    • watchExpression - 要监听的表达式,比如:"sb"
    • listener - 变化发生时的回调函数,AngularJS将向这个函数传入新值和旧值
    • objectEquality - 如果监听表达式的值是一个对象,应当将这个参数置为true。

    →_→是经过改进后的代码,当数据被改变时,界面会自动得到更新。这时,我们称,建立了从 数据到界面的单向绑定。为了验证这一点,在代码中我们追加了一个定时器自动 更新数据的age值。

    你可以试着去掉监听部分代码,看有什么效果。

    如何修改数据

    一旦在指令的实现代码中可以访问数据模型,那么使用声明式模板实现数据 修改也非常简单了。

    我们定义一个新的指令:ez-namecard-editor,意图让其展开成这样:

    1. <ul>
    2. <li>name : <input type="text"> </li>
    3. <li>gender : <input type="text"> </li>
    4. <li>age : <input type="text"></li>
    5. </ul>

    在ez-namecard-editor的指令实现中,为了用input中的值自动更新 sb变量中的值,我们需要在给input对象挂接上监听函数(示例中使用keyup事件), 在监听函数中实现对sb变量的修改。

    最终的效果是,用户在界面上进行的操作,自动地同步到了我们的数据。这时,我们称, 已经建立了从界面到数据的单向绑定。

    →_→的示例代码中,为了验证绑定的效果,我们增加了一个ez-logger指令。这个指令 将一个DOM元素的内容绑定到指定的变量上。

    这样,当我们通过ez-namecard-editor修改数据时,可以同步地看到变化后的内容。

    参考资料:http://www.hubwiz.com/course/54f3ba65e564e50cfccbad4b/

     
     
    标签: angularjsangularnodejs
  • 相关阅读:
    NET 泛型,详细介绍
    docker(5):数据的管理
    docker(4)docker的网络,自定义网桥
    docker(3)容器管理命令
    docker (2) 通用/镜像命令
    docker(1)应用场景以及安装
    AspNetCoreapi 使用 Docker + Centos 7部署
    AspNetCore 中使用 InentityServer4(2)
    AspNetCore中使用Ocelot之 IdentityServer4(1)
    Win7下无法启动sql server fulltext search (mssqlserver)的问题
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4345105.html
Copyright © 2011-2022 走看看