在上一章中,我们看到了 Quinch . js 的控制流绑定如何为视图代码提供一个基本的模板系统。控制流绑定为应用提供了可视化结构,但是一个成熟的模板系统需要的不仅仅是结构。knockout. js 的外观绑定让您可以精确控制单个元素的样式和格式。
在撰写本文时,knockout. js 附带了六个绑定来控制 HTML 元素的外观:
text: <value>
—设置元素的内容。html: <value>
—设置元素的 HTML 内容。visible: <condition>
-根据特定条件显示或隐藏元素。css: <object>
—向元素添加 CSS 类。style: <object>
—定义元素的style
属性。attr: <object>
—向元素添加任意属性。
像所有的 knockout. js 绑定一样,外观绑定总是出现在 HTML 元素的data-bind
属性内部。但是与前一章的控制流绑定不同,外观绑定只影响它们相关的元素——它们不改变模板块或绑定上下文。
text
绑定是敲除的基础。正如我们已经看到的,text
绑定显示了 HTML 元素内部的属性值:
<td data-bind='text: name'></td>
您应该只在文本级元素上使用text
绑定(例如,<a>
、<em>
、<span>
等)。),尽管从技术上讲,它可以应用于任何 HTML 元素。作为其参数,text
绑定采用任何数据类型,并在呈现之前将其转换为字符串。text
绑定将转义 HTML 实体,因此可以用来安全地显示用户生成的内容。
图 16:视图中自动转义的 HTML 实体的text
绑定
还值得指出的是,knockout. js 在幕后管理跨浏览器问题。对于 IE,它使用innerText
属性,对于火狐和相关浏览器,它使用textContent
。
html
绑定允许您将字符串呈现为 HTML 标记。如果您想要在视图模型中动态生成标记并在模板中显示它,这将非常有用。例如,您可以在我们的Product
对象上定义一个名为formattedName
的计算可见性,它包含一些 HTML:
function Product(name, price, tags, discount) { ... this.formattedName = ko.computed(function() { return "<strong>" + this.name() + "</strong>"; }, this); }
然后,您可以使用html
绑定呈现格式化名称:
<span data-bind='html: featuredProduct().formattedName'></span>
虽然这违背了将内容与呈现分开的目标,但是html
绑定如果使用得当,可以证明是一个通用的工具。
图 17:视图中html
绑定呈现 HTML 实体
无论何时渲染动态 HTML——无论是通过html
绑定还是 ASP。NET—始终确保标记已经过验证。如果需要显示不可信的内容,应该使用text
绑定,而不是html
。
在前面的片段中,还要注意featuredProduct
是一个可观测的对象,所以底层对象必须用空的函数调用来引用,而不是直接用featuredProduct.formattedName
访问属性。同样,这是 knockout 初学者的常见错误。
很像if
和ifnot
绑定,visible
绑定允许您根据特定条件显示或隐藏元素。但是,visible
绑定并没有将元素从 DOM 中完全移除,而是简单地将一个display: none
声明添加到元素的style
属性中。例如,我们可以将现有的if
绑定更改为visible
绑定:
<td data-bind='visible: discount() > 0' style='color: red'>
下面的代码示例显示了if
和visible
版本的结果 HTML。本例假设条件评估为false
:
<!-- Using if binding: --> <td data-bind="if: discount() > 0" style="color: red"></td>
<!-- Using visible binding: --> <td data-bind='visible: discount() > 0' style='color: red; display: none'>
You saved <span data-bind='text: formattedDiscount'></span>!!! </td>
决定何时使用visible
对if
很大程度上取决于上下文。在这种情况下,实际上最好使用if
绑定,这样空的<td>
会为每行创建相同数量的列。
该绑定采用与if
和ifnot
绑定相同的参数。条件可以是视图模型的属性、JavaScript 表达式或返回布尔值的函数。
css
绑定允许您根据特定条件为 HTML 元素定义 CSS 类。它不是将条件作为参数,而是将包含 CSS 类名的对象作为属性名,将应用该类的条件作为值。这最好用一个例子来解释。
比方说,当一个产品的折扣超过 15%时,你想引起额外的注意。一种方法是在显示所有购物车商品的<table>
中添加一个css
绑定到“您保存 __%”消息:
样本代码:item016.htm
<td data-bind='if: discount() > 0' style='color: red'>
You saved <span data-bind='text: formattedDiscount, css: {supersaver: discount() > .15}'></span>!!!
</td>
首先,您会注意到,通过用逗号分隔,可以向单个data-bind
属性添加多个绑定。第二,css
绑定以{supersaver: discount() > .15}
对象为论据。这就像一个映射,定义了什么时候应该将一个 CSS 类添加到元素中。在这种情况下,只要产品的折扣大于 15%,就会增加.supersaver
类,否则会删除。定义.supersaver
规则的实际 CSS 可以在页面的任何地方定义(即外部或内部样式表)。
.supersaver {
font-size: 1.2em;
font-weight: bold; }
如果你给第二个产品加 10%的折扣,你应该会看到我们的css
绑定在起作用:
图 18:discount() > .15
时css
绑定应用类
对象属性中包含的条件与if
、ifnot
和visible
绑定的参数相同。它可以是属性、JavaScript 表达式或函数。
style
绑定提供了与css
绑定相同的功能,除了它操纵元素的style
属性,而不是添加或移除类。由于内联样式需要键值对,因此该绑定参数的语法也略有不同:
You saved <span data-bind='text: formattedDiscount, style: {fontWeight: discount() > .15 ? "bold" : "normal"}'></span>!!!
如果产品的折扣大于 15%,knockout. js 将把这个元素呈现如下:
<td style='color: red; font-weight: bold'>
但是,如果低于 15%,就会有normal
的font-weight
。请注意,style
绑定可以与元素现有的style
属性结合使用。
attr
绑定允许您使用视图模型属性动态定义 HTML 元素的属性。例如,如果我们的Product
类有一个permalink
属性,我们可以通过以下方式生成到各个产品页面的链接:
<p><a data-bind='attr: {href: featuredProduct().permalink}'>View details</a></p>
这将向<a>
标签添加一个href
属性,指向存储在permalink
属性中的任何内容。当然,如果permalink
是一个可观测的,你可以利用 Denuke . js 的自动依赖跟踪的所有好处。由于永久链接通常与数据对象一起存储在永久存储器(例如,博客条目)中,因此以这种方式动态生成链接非常方便。
但是,attr
绑定不仅仅是创建链接。它允许你在一个 HTML 元素中添加任何属性。这为将您的 knockout. js 模板与其他 DOM 库集成打开了各种各样的大门。
这一章介绍了 knockout. js 的外观绑定。当满足特定条件时,这些绑定中的许多会更改 HTML 元素。直接在绑定中定义这些条件是设计模板的一种直观方式,它将视图为中心的代码保持在视图模型之外。
请记住,knockout. js 的目标是通过在数据发生变化时自动同步视图,让您专注于应用背后的数据。一旦定义了绑定,就再也不用担心它们了(当然,除非您改变视图模型的结构)。
本章中展示的外观绑定提供了您需要的所有工具来显示您的数据,但是它们不允许我们向视图组件添加任何用户交互。在下一章中,我们将看一下 Dellow . js 是如何管理表单域的。