[Step-By-Step Angular2](2)数据绑定之插入符和单向绑定

在mvc/mvvm类框架出现之前,开发者通常需要手动更新html并维护html与数据之间的关系。随着mvc思想在前端社区的普及和发展,view层和model层的解耦和分离机制已经是各框架的标配了。
令人欣喜的是,angular2在现有各框架的理论基础上对数据绑定重新进行了抽象,在架构上进行了革新,很有借鉴意义。从本文起我们就将开始讨论angular2中的数据绑定。

angular2中有四种数据绑定:插入符(interpolation)、单向绑定(one-way binding)、事件绑定(event binding)和双向绑定(two-way binding)。今天我们先介绍前两种:插入符和单向绑定。

说到数据绑定就不得不提到模板层和数据。在angular1中,以scope属性的形式存在的数据会通过watch机制来和模板进行绑定。具体操作中,既可以手动调用scope上的$watch方法,也可以在模板层中使用相关的绑定指令或大括号绑定语法。然而,direcitve和scope的关系却错综复杂:directive既可以复用父级的scope,也可以拥有自己的scope;当它拥有自己的scope时,这个scope既可以和父级scope没有继承关系,也可以通过prototype链来继承父级scope上的属性……总之,这种盘根错节的数据关系使得angular1对于开发者并不那么友好。自然,简化数据关系和数据结构就成了Google在angular2开发中的重要任务之一。

在angular2中,component和数据有了清晰的对应关系:模板层中绑定的数据就是当前组件的实例属性,scope的概念消失了。

我们先通过一些简单的例子来帮助大家认识一下这种关系:

@Component({
    // selector告知angular在哪里初始化AppComponent这个组件
    selector: ‘hello-world‘,
    // AppComponent组件的具体模板
    template: `
        <h1 class="{{color}}">hello world, from {{name}}</h1>
    `
})
export class AppComponent {
    public name: string = ‘Ralph‘;
};

我们在AppComponent类中添加了string类型的name属性,并赋值为"Ralph";相应地,为了使name属性能够在模板中被显示出来,我们在<h1>标签中增加了{{name}},这就是angular2模板的插入符语法。

插入符语法不仅能用到html标签的内容上,也可以用到属性上:

import {Component} from ‘@angular/core‘;

@Component({
    styles: [`
        .blue{
            background: blue;
        }
    `],
    // selector告知angular在哪里初始化AppComponent这个组
    selector: ‘hello-world‘,
    // AppComponent组件的具体模板
    template: `
        <h1 class="{{classNames}}">hello world, from {{name}}</h1>
    `
})
export class AppComponent {
    public name: string = ‘Ralph‘;
    public classNames: string = ‘blue‘;
};

在上面的例子中,我们在Component装饰器上增加了styles属性,styles属性的值是一个字符串数组,编译后将作为当前组件的css;同时,我们还使用了es6中的反引号语法来包裹整块字符串,省去了拼接的麻烦。h1上的class属性和AppComponent上的classNames属性进行了绑定,classNames被赋值为了blue,正好适配了class中的.blue选择器。

在进行属性绑定时,我们也可以使用单向绑定的语法:

import {Component} from ‘@angular/core‘;

@Component({
    styles: [`
        .blue{
            background: blue;
        }
    `],
    // selector告知angular在哪里初始化AppComponent这个组
    selector: ‘hello-world‘,
    // AppComponent组件的具体模板
    template: `
        <h1 [class]="classNames">hello world, from {{name}}</h1>
    `
})
export class AppComponent {
    public name: string = ‘Ralph‘;
    public classNames: string = ‘blue‘;
};

请注意class两端的括号[]不能省略,否则只会在初始值时赋值,而不会对变化进行监听。

单向绑定语法还有一种较少使用的形式,把中括号换为bind-前缀,功能和上例等价:

import {Component} from ‘@angular/core‘;

@Component({
    styles: [`
        .blue{
            background: blue;
        }
    `],
    // selector告知angular在哪里初始化AppComponent这个组
    selector: ‘hello-world‘,
    // AppComponent组件的具体模板
    template: `
        <h1 bind-class="classNames">hello world, from {{name}}</h1>
    `
})
export class AppComponent {
    public name: string = ‘Ralph‘;
    public classNames: string = ‘blue‘;
};

除了引入组件属性并放弃scope外,angular2在框架思想上还有一个比较有价值的贡献:彻底区分dom node属性(property)和html标签属性(attribute)。

由于中文表述上property和attribute都翻译为“属性”,国内的开发者对于这两个截然不同的概念可能相对缺少关注;然而在国外,如何区分property和attribute是最高频出现的前端基础面试题之一。既然大家都知道他们不同,那博主为什么还说这是angular2的贡献呢?angular2之前的框架,在遇到property和attribute相关的问题时,都只是“头痛医头,脚痛医脚”,只解决具体问题而没有抽象到框架层面上去。以react为例,在文档的forms章节中(https://facebook.github.io/react/docs/forms.html),认为input控件的value property和value attribute之间的不同步是传统html的一种缺失(absent when writing traditional form HTML);而angular2的态度相对更宏观一些:property和attribute不是同一个概念,二者之间没有绝对的对应关系,它们可以同步,也可以不同步,一些property在attribute中找不到对应,也有一些attribute在property中找不到对应;但是要记住一点,angular2的绑定是针对dom node property的绑定,而非针对HTML标签attribute的绑定。
在这样的设计之上,对于value、disabled、checked等属性的处理就很清晰了;更为重要的是,它也为指令间、组件间的数据传递打下了良好的基础。

以checked属性的绑定为例:

import {Component} from ‘@angular/core‘;

@Component({
    // selector告知angular在哪里初始化AppComponent这个组件
    selector: ‘hello-world‘,
    // AppComponent组件的具体模板
    template: `
        <h1 class="{{color}}">hello world</h1>
        checked属性绑定测试:<input type="checkbox" [checked]="checked" /><br />
        <button (click)="onClick()">click me</button>
    `
})
export class AppComponent {
    public checked: boolean = false;
    public onClick() {
        this.checked = !this.checked;
    }
};

上面的例子中出现了对click事件的监听,暂时不是本节的重点,大家可以先忽略细节。input[type="checkbox"]上的checked属性和AppComponent上的checked属性进行了绑定。AppComponent上的checked属性初始值为false,用户每次点击按钮时,onClick方法被触发,checked的值会相对于上一个值取反,从而实现选中/反选多选框的效果。

style和class是两个比较特殊的属性:style作为行内属性时,其值依然是键值对的组合;class经常需要对某一个值进行添加和删除,以完成toggle的操作。angular2对style和class的绑定有进一步的封装。
对style进行绑定:

import {Component} from ‘@angular/core‘;

@Component({
    // selector告知angular在哪里初始化AppComponent这个组件
    selector: ‘hello-world‘,
    // AppComponent组件的具体模板
    template: `
        <h1 class="{{color}}">hello world</h1>
        <button (click)="onClick()" [style.background]="color">更改背景色</button>
    `
})
export class AppComponent {
    public color: string = ‘blue‘;
    public onClick() {
        this.color = this.color === ‘blue‘ ? ‘green‘ : ‘blue‘;
    }
};

对class进行绑定:

import {Component} from ‘@angular/core‘;

@Component({
    styles: [`
        .selected{
            background: blue;
        }
    `],
    // selector告知angular在哪里初始化AppComponent这个组件
    selector: ‘hello-world‘,
    // AppComponent组件的具体模板
    template: `
        <h1 class="{{color}}">hello world</h1>
        <button (click)="onClick()" [class.selected]="open">更改背景色</button>
    `
})
export class AppComponent {
    public open: boolean = false;
    public onClick() {
        this.open = !this.open;
    }
};

需要对style和class进行操作时,除了使用数据绑定以外,也可以使用相应的指令,稍后的章节中会有所涉及。

既然angular2的数据绑定通常是对dom node property的绑定,那么需要绑定一个不具有property对应项的attribute属性怎么操作呢?作为一个例外,angular2为此提供了attr.attribute-name的绑定方式,以绑定aria-label属性为例:

import {Component} from ‘@angular/core‘;

@Component({
    // selector告知angular在哪里初始化AppComponent这个组件
    selector: ‘hello-world‘,
    // AppComponent组件的具体模板
    template: `
        <h1 class="{{color}}">hello world</h1>
        <button [attr.aria-label]="type">help</button>
    `
})
export class AppComponent {
    public type: string = ‘help‘;
};

对angular2的插入符和单向绑定的介绍就先到这里,事件绑定、双向绑定将放到后续的章节中。

时间: 2024-12-12 14:38:12

[Step-By-Step Angular2](2)数据绑定之插入符和单向绑定的相关文章

Git Step by Step – (8) Git的merge和rebase

前面一篇文章中提到了"git pull"等价于"git fetch"加上"git merge",然后还提到了pull命令支持rebase模式,这篇文章就介绍一下merge和rebase之间有什么差别. 由于我们主要是想看看merge跟rebase之间的区别,这里就是用本地仓库的分支进行演示了. merge 其实在介绍分支的那篇文章中已经介绍过了一些分支merge的内容,这里就进行一些补充和总结. 下面我们基于本地一个仓库开始介绍,当前仓库的分支情

数据库设计 Step by Step (1)——扬帆启航

引言:一直在从事数据库开发和设计工作,也看了一些书籍,算是略有心得.很久之前就想针 对关系数据库设计进行整理.总结,但因为种种原因迟迟没有动手,主要还是惰性使然.今天也算是痛下决心开始这项卓绝又令我兴奋的工作.这将是一个系列的文 章,我将以讲座式的口吻展开讨论(个人偷懒,这里的总结直接拿去公司培训新人用). 系列的第一讲我们先来回答下面几个问题 数据库是大楼的根基 大多数程序员都很急切,在了解基本需求之后希望很快的进入到编码阶段(可能只有产出代码才能反映工作量),对于数据库设计思考得比较少. 这

数据库设计 Step by Step (2)——数据库生命周期

引言:数据库设计 Step by Step (1)得到这么多朋友的关注着实出乎了我的意外.这也坚定了我把这一系列的博文写好的决心.近来工作上的事务比较繁重,加之我期望这个系列的文章能尽可能的系统.完整,需要花很多时间整理.思考数据库设计的各种资料,所以文章的更新速度可能会慢一些,也希望大家能够谅解. 系列的第二讲我们将站在高处俯瞰一下数据库的生命周期,了解数据库设计的整体流程 数据库生命周期 大家对软件生命周期较为熟悉,数据库也有其生命周期,如下图所示. 图(1)数据库生命周期 数据库的生命周期

WPF Step By Step 自定义模板

WPF Step By Step 自定义模板 回顾 上一篇,我们简单介绍了几个基本的控件,本节我们将讲解每个控件的样式的自定义和数据模板的自定义,我们会结合项目中的具体的要求和场景来分析,给出我们实现的方案和最终的运行效果. 本文大纲 1.控件模板及数据模板 2.ListBox深度定制模板. 3.TreeView高级模板使用实例. 控件模板及数据模板 控件模板 什么是控件模板,指定可以在控件的多个实例之间共享 Control 的可视结构和性能方面的方面.控件模板其实就是我们在可视方面的自定义模板

WPF Step By Step 控件介绍

WPF Step By Step 控件介绍 回顾 上一篇,我们主要讨论了WPF的几个重点的基本知识的介绍,本篇,我们将会简单的介绍几个基本控件的简单用法,本文会举几个项目中的具体的例子,结合这些 例子,希望我们可以对WPF的掌握会更深刻.本文涉及的内容可能较多.请大家慢慢看看.错误之处,还请指出. 本文大纲 1.基本控件介绍与用法. 基本控件介绍与用法 文本控件 Label控件 label控件:一般用户描述性文字显示. 在Label控件使用时,一般给予用户提示.用法上没有什么很特殊的,label

HDU 2815 扩展baby step giant step 算法

题目大意就是求 a^x = b(mod c) 中的x 用一般的baby step giant step 算法会超时 这里参考的是http://hi.baidu.com/aekdycoin/item/236937318413c680c2cf29d4 map平衡树查找值 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #include <

Program for Linux USB-devices driver step by step (ONE)

Program for Linux USB-devices driver 开始啃硬骨头~ 这里我打算一步步给出USB device driver 的demo,希望有心能能够共同交流学习. 希望认识更多对Linux有兴趣的geek. 目前由于环境和自身能力方面原因还没能做实物的测试,篇章的最后打算给出一个在x86上模拟USB读写的driver,以后能够做实物测试之后再更新this blog 我的联系方式: [email protected](由于偶不能登QQ,所以thunder bird的邮件只要

HDU 2815 Mod Tree 离散对数 扩展Baby Step Giant Step算法

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2815 题意: 思路:与上题不同,这道题不要求m是素数,是利用扩展Baby Step Giant Step算法求离散对数. 以下转载自:AekdyCoin [扩展Baby Step Giant Step] [问题模型] 求解 A^x = B (mod C) 中 0 <= x < C 的解,C 无限制(当然大小有限制--) [写在前面] 这个问题比较麻烦,目前网络上流传许多版本的做法,不过大部分已近被证明

精通initramfs构建step by step

http://hi.baidu.com/jonathan2004/blog/item/db7bf38aad11759ea4c2721d.html 精通initramfs构建step by step (1)--hello world 2009-12-08 19:19 一.initramfs是什么 在2.6版本的linux内核中,都包含一个压缩过的cpio格式的打包文件.当内核启动时,会从这个打包文件中导出文件到内核的rootfs文件系统, 然后内核检查rootfs中是否包含有init文件,如果有则