Knockoutjs 映射不会将 observables 添加到字符串数组中
Posted
技术标签:
【中文标题】Knockoutjs 映射不会将 observables 添加到字符串数组中【英文标题】:Knockoutjs mappings don't add observables to array of strings 【发布时间】:2021-06-03 14:40:37 【问题描述】:我正在从服务器获取此类数据
FirmName: "Firm Name",
Address: "123 Address",
AltNames: [
"First Alt Name",
"Second Alt Name"
]
我正在使用敲除映射插件将数据映射到带有 ko.mapping.fromJS(data, , this); 的 viewModel;
但是,每当我更改任何字符串数组元素时,我的更改都不会传播到 viewModel。我该怎么做才能解决这个问题?
我的js:
function firmModel()
//this is what I get from the server
var data =
FirmName: "Firm Name",
Address: "123 Address",
AltNames: [
"First Alt Name",
"Second Alt Name"
]
;
ko.mapping.fromJS(data, , this);
var em = new firmModel();
ko.applyBindings(firmModel);
我的html:
<div>
<label>Company</label>
<input type="text" data-bind="value: FirmName">
</div>
<div>
<label>Address</label>
<input type="text" data-bind="value: Address">
</div>
<br>
<h3>
Alt Names
</h3>
<ul data-bind="foreach: AltNames">
<li>
<input type="text" data-bind="value: $data">
</li>
</ul>
<br/><br/>
<h2>
Result of the changes where I see whether viewModel picks up my changes above
</h2>
<span>Company: </span><span data-bind="text: FirmName"></span><br/>
<span>Address: </span><span data-bind="text: Address"></span><br/>
<br/>
Alt Names: <br/>
<ul data-bind="foreach: AltNames">
<li data-bind="text: $data"></li>
</ul>
小提琴http://jsfiddle.net/n87esdLv/2/
【问题讨论】:
【参考方案1】:在foreach
中不能使用$data
:
<input type="text" data-bind="value: $data">
正如您在documentation 中看到的那样:
$原始数据
这是当前上下文中的原始视图模型值。通常这与 $data 相同,但如果提供给 Knockout 的视图模型被包装在一个可观察对象中,则 $data 将是未包装的视图模型,而 $rawData 将成为 observable 本身。
那么,你需要改用$rawData
,因为AltNames
数组的内容必须是可观察的,而不是字符串。
AltNames
中的字符串必须是可观察的。您需要使用custom object construction using “create”自定义AltNames
数组的创建:
var mapping =
'AltNames':
create: function(options)
return ko.observable(options.data);
ko.mapping.fromJS(data, mapping, this);
这是一个可运行的示例:
function firmModel()
//this is what I get from the server
var data =
FirmName: "Firm Name",
Address: "123 Address",
AltNames: [
"First Alt Name",
"Second Alt Name"
]
;
//ko.mapping.fromJS(data, , this);
var mapping =
'AltNames':
create: function(options)
return ko.observable(options.data);
ko.mapping.fromJS(data, mapping, this);
var em = new firmModel();
ko.applyBindings(firmModel);
h2
font-weight: bold;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<div>
<label>Company</label>
<input type="text" data-bind="value: FirmName">
</div>
<div>
<label>Address</label>
<input type="text" data-bind="value: Address">
</div>
<br>
<h3>
Alt Names
</h3>
<ul data-bind="foreach: AltNames">
<li>
<input type="text" data-bind="value: $rawData">
</li>
</ul>
<br/><br/>
<h2>
Result of the changes
</h2>
<span>Company: </span><span data-bind="text: FirmName"></span><br/>
<span>Address: </span><span data-bind="text: Address"></span><br/>
<br/>
Alt Names: <br/>
<ul data-bind="foreach: AltNames">
<li data-bind="text: $data"></li>
</ul>
【讨论】:
何塞,非常感谢!我有一个后续问题。如果 AltNames 不是根元素怎么办。例如,` FirmNames: MainName: "Bla", AltNames: ["One", "Two]? I've tried using
"FirmNames.AltNames": create: function(options) return ko.observable(options. data); ` 但它不起作用
你能把这个字符串数组改成一个对象数组吗:FirmNames: MainName: "Bla", AltNames: [name:"One",name: "Two]
然后,插件将完成这项工作,而无需mapping
。我在AltNames
中添加name:
。
在这个小提琴jsfiddle.net/b2L3nmc5/3我使用相同的mapping
,我认为它有效。
谢谢你,何塞!你说得对。我需要在 ko 循环中使用 $rawData 而不是 $data 。再次感谢!以上是关于Knockoutjs 映射不会将 observables 添加到字符串数组中的主要内容,如果未能解决你的问题,请参考以下文章
KnockoutJS 3.X API 第八章 映射(mapping)插件
KnockoutJS 映射插件 (observableArray)