knockoutjs foreach array绑定 表格 下拉框绑定

动态表格使用observable arrays and the foreach
ko.observableArray: 观察者模式,根据array动态更新表格

ko中的流程控制标签:foreach, if, ifnot, and with
在foreach的数据源发生变化时,ko并不会重新生成整个table, [color=red]更高效地,ko会找到viewmodel中变化的部分, 然后更新数据变化对应的最小DOM集合。[/color]

data-bind="foreach: seats":foreach表格循环
meal().price: meal属性是一个被观察对象,在尝试取得子属性之前要使用meal()函数,即注意是meal().price, 不是 meal.price

data-bind="click: addSeat, enable: seats().length < 5":表示按钮绑定到click事件addSeat,并且按钮只在表格数据小于5时可用,删错或者增加表格数据,由于ko的自动依赖追踪机制,按钮的可用状态会自动变化。

data-bind="visible: totalSurcharge() > 0":用来控制控件是否显示,对应css的display 属性

[color=red]$root.[/color]前缀代表Knockout去viewmodel的顶层查询相应属性,而不是绑定表格seats数组中的实例变量SeatReservation中查询。

[color=red]必须是引用方法的形式(带括号)引用observable变量[/color],这与ko的自动依赖追踪相对象(如果是属性的话,就仅仅引用变量的值,做不到其他效果)


// 下拉框绑定到$root.availableMeals数组,下拉框显示的文字内容由optionsText: 'mealName'决定,下拉框的值绑定到seats数组中对象SeatReservation的meal属性!
<select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select>


viewmodel(控制器)

// Class to represent a row in the seat reservations grid
function SeatReservation(name, initialMeal) {
var self = this;
self.name = name;
self.meal = ko.observable(initialMeal);

self.formattedPrice = ko.computed(function() {
var price = self.meal().price;
return price ? "$" + price.toFixed(2) : "None";
});
}

// Overall viewmodel for this screen, along with initial state
function ReservationsViewModel() {
var self = this;

// Non-editable catalog data - would come from the server
self.availableMeals = [
{ mealName: "Standard (sandwich)", price: 0 },
{ mealName: "Premium (lobster)", price: 34.95 },
{ mealName: "Ultimate (whole zebra)", price: 290 }
];

// Editable data
self.seats = ko.observableArray([
new SeatReservation("Steve", self.availableMeals[0]),
new SeatReservation("Bert", self.availableMeals[0])
]);

// Operations
self.addSeat = function() {
self.seats.push(new SeatReservation("", self.availableMeals[0]));
}
self.removeSeat = function(seat) { self.seats.remove(seat) }

self.totalSurcharge = ko.computed(function() {
var total = 0;
for (var i = 0; i < self.seats().length; i++)
total += self.seats()[i].meal().price;
return total;
});
}

ko.applyBindings(new ReservationsViewModel());

view视图

<h2>Your seat reservations</h2>

<table>
<thead><tr>
<th>Passenger name</th><th>Meal</th><th>Surcharge</th><th></th>
</tr></thead>
<!-- Todo: Generate table body -->
<tbody data-bind="foreach: seats">
<tr>
<td><input data-bind="value: name" /></td>
<td><select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select></td>
<td data-bind="text: meal().price"></td>
<td data-bind="text: formattedPrice"></td>
<td><a href="#" data-bind="click: $root.removeSeat">Remove</a></td>
</tr>
</tbody>
</table>
<h3 data-bind="visible: totalSurcharge() > 0">
Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span>
</h3>
<h2>Your seat reservations (<span data-bind="text: seats().length"></span>)</h2>

<button data-bind="click: addSeat, enable: seats().length < 5">Reserve another seat</button>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值