我是 KnockoutJS 的新手。我想知道是否有更好的方法来完成以下功能。
对象的属性在表格行中显示为文本。我可以单独单击每个文本范围以显示一个文本框,以便我可以编辑文本。请务必注意,与对象相关的其他属性不会变为可编辑的。一次只能编辑一个属性。为了实现这一点,在 KO 映射期间,我实际上用一个具有两个属性的对象覆盖了每个属性:一个保存原始属性值的“value”属性,以及一个用于跟踪文本框可见性的“hasFocus”属性.
这是一个JSFiddle来展示我目前是如何对其进行编程的。请务必单击项目名称和价格以查看出现的文本框。
进一步说明
我有一个表,其中每一行代表一个 TransactionItem。
在开始状态下,每个字段都是文本。单击时,文本消失并出现一个文本框。当文本框失去焦点时,文本框消失,修改后的文本重新出现。
以下步骤显示了我为完成此任务所做的工作:
使用 KO Mapping 插件(本例中为“myData”)从服务器映射数据,
var myData = [ { TransactionItems: [ { Name: "Item1", Price: "1.00" }, { Name: "Item2", Price: "2.00" }, { Name: "Item3", Price: "3.00" }, ]}, ]; var mappingOptions = { 'TransactionItems': { create: function (options) { return new TransactionItem(options.data); } } } var viewModel = {}; var self = viewModel; viewModel.transactions = ko.mapping.fromJS(myData, mappingOptions); ko.applyBindings(viewModel);
在 TransactionItems 构造函数中,获取 TransactionItem 属性('name'、'price')的当前值,并将它们存储在临时变量中。用新对象覆盖属性。这些新对象包含两个值:原始属性的“值”和新的“hasFocus”属性
//Grab the current values of the properties var itemValue = this.Name(); var priceValue = this.Price(); //Recreate properties as objects, give them a 'hasFocus' property this.Name = { value: itemValue, hasFocus: ko.observable(false)}; this.Price = { value: priceValue, hasFocus: ko.observable(false) };
例如,'name' 属性变为对象 Name: { value: 'Item1', hasFocus: false }。
在 HTML 中,数据绑定每个属性的“hasFocus”以控制何时显示/隐藏文本/文本框。
单击文本时,'hasFocus' 属性设置为 true,这将隐藏文本并显示文本框。
- 当文本框模糊时,'hasFocus' 属性设置为 false,这会隐藏文本框并显示文本。
我想知道是否有更好的方法来完成此功能。我是不是偏离轨道了?谢谢!
更大的代码片段:
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<!-- ko foreach: transactions -->
<!-- ko template: { name: 'listItems', foreach: TransactionItems } -->
<!-- /ko -->
<!-- /ko -->
</tbody>
</table>
<script type="text/html" id="listItems">
<tr>
<td>
<!-- Either show this -->
<span data-bind="visible: !Name.hasFocus(),
text: Name.value,
click: editItem.bind($data, Name)"></span>
<!-- Or show this -->
<input data-bind="visible: Name.hasFocus,
value: Name.value,
hasfocus: Name.hasFocus,
event: {
focus: editItem.bind($data, Name),
blur: hideItem.bind($data, Name)
}"
/><!-- end input -->
</td>
<td>
<!-- Either show this -->
<span data-bind="visible: !Price.hasFocus(),
text: Price.value, click: editItem.bind($data, Price)"></span>
<!-- Or show this -->
<input data-bind="visible: Price.hasFocus,
value: Price.value,
hasfocus: Price.hasFocus,
event: {
focus: editItem.bind($data, Price),
blur: hideItem.bind($data, Price)
}"
/><!--input end -->
</td>
</tr>
</script>
<!-- END OF HTML -->
<script >
function TransactionItem(data) {
ko.mapping.fromJS(data, {}, this);
this.editable = ko.observable(false);
this.hasFocus = ko.observable(false);
//Grab the current values of the properties
var itemValue = this.Name();
var priceValue = this.Price();
//Recreate properties as objects, give them a 'hasFocus' property
this.Name = { value: itemValue, hasFocus: ko.observable(false)};
this.Price = { value: priceValue, hasFocus: ko.observable(false) };
this.editItem = function (objProperty) {
this.editable(true);
objProperty.hasFocus(true);
}
this.hideItem = function (objProperty) {
this.editable(false);
objProperty.hasFocus(false);
}
}
//MAPPING
var mappingOptions = {
'TransactionItems': {
create: function (options) {
return new TransactionItem(options.data);
}
}
}
//DATA
var myData = [
{
TransactionItems: [
{
Name: "Item1",
Price: "1.00"
},
{
Name: "Item2",
Price: "2.00"
},
{
Name: "Item3",
Price: "3.00"
},
]},
];
//VIEWMODEL
var viewModel = {};
var self = viewModel;
viewModel.transactions = ko.mapping.fromJS(myData, mappingOptions);
ko.applyBindings(viewModel);
</script>