如何将父函数添加到 KnockOut 双嵌套映射?
How to add parent function to KnockOut double-nested mapping?
我正在使用来自 JS 的 KnockOut 映射从 JSON 对象创建我的视图模型,如下所示:
{
"cats": [{
"name": "fluffy",
"color": "brown",
"kittens": [{
"name": "spot",
"color": "brown"
}, {
"name": "rascal",
"color": "grey"
}, {
"name": "trouble",
"color": "white"
}]
}, {
"name": "kitty",
"color": "red",
"kittens": [{
"name": "lady",
"color": "red"
}, {
"name": "skat",
"color": "striped"
}]
}]
}
html:
<div data-bind="foreach:cats">
<span data-bind="text:name"></span>
<table>
<tr data-bind="foreach: kittens">
<td data-bind="text:name"></td>
<td data-bind="text:color"></td>
<td><a data-bind="click: $parent:showParentColor" href="#">Parent Color</a></td>
</tr>
</table>
</div>
Javascript:
var KittenModel = function (data) {
ko.mapping.fromJS(data, {}, this);
// ... various computed values added to this
}
var mapping = {
'kittens': {
create: function(options) {
return new KittenModel(options.data);
}
},
'otherItem': {
create: function(options) {
return ('otherStuff');
}
}
}
var data = { ... }; // the JSON above
var CatsViewModel = ko.mapping.fromJS(data, mapping);
问题:
在哪里以及如何放置 showParentColor() 函数,以便数据绑定在小猫中工作 table?例如:
function showParentColor(cat) {
alert(cat.color);
}
谢谢!
您可以根据您的视图模型层次结构使用以下其中一项:
- $root :这指向根 context.The 最顶层 parent 上下文中的主视图模型 object。
$parents 数组: 这是一个包含所有视图模型的数组。
$parents[0] : parent 视图模型上下文。(也与 $parent
)
$parents[1]:第二个parent视图模型上下文。(grand parent)
$parents[2]:第三个parent查看模型上下文。 (great-grand parent)
- 等等....
更新:
如果你想在 CatsViewModel
级别添加一个函数,你只需将你的函数添加到创建的模型中。
示例:https://jsfiddle.net/kyr6w2x3/87/
JS:
CatsViewModel.showParentColor = function(item){
console.log(item.name());
console.log(item.color());
}
查看:
<a data-bind="click: $parents[1].showParentColor">
以下是您的模型的层次结构
- CatsViewModel
- cats : observableArray
- name : observable
- color : observable
- kittens : observableArray
- name : observable
- color : observable
- showParentColor : function
备选方案: 您可以自己完成这项工作并创建您的 models.Would 更容易根据您的内容进行修改和维护 want.You 也可以添加 click
在你想要的任何模型中运行。
示例:http://jsfiddle.net/kyr6w2x3/91/
HTML :
<div data-bind="foreach:cats">
<span data-bind="text:name"></span>
<table>
<tbody data-bind="foreach: kittens">
<tr>
<td data-bind="text:name"></td>
<td data-bind="text:color"></td>
<td><a data-bind="click: $parent.showParentColor" href="#">Parent Color</a></td>
</tr>
</tbody>
</table>
</div>
JS:
var data = {
"cats": [{
"name": "fluffy",
"color": "brown",
"kittens": [{
"name": "spot",
"color": "brown"
}, {
"name": "rascal",
"color": "grey"
}, {
"name": "trouble",
"color": "white"
}]
}, {
"name": "kitty",
"color": "red",
"kittens": [{
"name": "lady",
"color": "red"
}, {
"name": "skat",
"color": "striped"
}]
}]
}
var CatsViewModel = function (data){
var self = this;
self.cats = ko.observableArray($.map(data.cats, function (item) {
return new CatItemViewModel(item);
}));
}
var CatItemViewModel = function (data){
var self = this;
self.name = ko.observable(data.name);
self.color = ko.observable(data.color);
self.kittens = ko.observableArray($.map(data.kittens, function (item) {
var newData = Object.assign({}, item, { parent: self.name()});
return new KittenModel(newData);
}));
self.showParentColor = function (item){
console.log("Parent Name: " , self.name());
console.log("Name: " , item.name());
console.log("Color: " , item.color());
}
}
var KittenModel = function (data) {
var self = this;
self.name = ko.observable(data.name);
self.color = ko.observable(data.color);
self.parent = ko.observable(data.parent);
}
var vm = new CatsViewModel(data);
ko.applyBindings(vm);
注意:我更喜欢其他答案的方法而不是这个方法,但是为了有多个选项,我确实想提出一个替代解决方案。
备选方案 1
您可以在 KittenModel
中创建一个 "static" 方法来记录它通过的任何猫的颜色:
var KittenModel = function (data) {
ko.mapping.fromJS(data, {}, this);
};
KittenModel.logCatColor = function(cat) {
console.log(cat.color);
};
现在,因为您的视图可以访问父子结构,所以您可以使用任何您想要的父级调用此方法:
<!-- to log the parent's color -->
<div data-bind="click: logCatColor.bind(null, $parent)"></div>
<!-- knockout automatically passes `$data` as a first argument,
so you won't need to bind the method to log your own color -->
<div data-bind="click: logCatColor"></div>
一个例子:
ko.applyBindings({
name: "parent",
child: {
name: "child",
logName: function(entity) {
console.log(entity.name);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<h1 data-bind="text: name"></h1>
<div data-bind="with: child" style="border: 1px solid black">
<h2 data-bind="text: name">
</h2>
<button data-bind="click: logName">
log my name
</button>
<button data-bind="click: logName.bind(null, $parent)">
log my parent's name
</button>
</div>
备选方案 2
在作为选项传递的工厂函数中,data
和 parent
都可用:options.data
包含当前映射的项目。 options.parent
在这种情况下将引用父级 cat
。我还没有测试过这个,但这可能有效:
'kittens': {
create: function(options) {
var dataWithParent = Object.assign({},
options.data,
{ parent: options.parent });
return new KittenModel(dataWithParent);
}
},
我正在使用来自 JS 的 KnockOut 映射从 JSON 对象创建我的视图模型,如下所示:
{
"cats": [{
"name": "fluffy",
"color": "brown",
"kittens": [{
"name": "spot",
"color": "brown"
}, {
"name": "rascal",
"color": "grey"
}, {
"name": "trouble",
"color": "white"
}]
}, {
"name": "kitty",
"color": "red",
"kittens": [{
"name": "lady",
"color": "red"
}, {
"name": "skat",
"color": "striped"
}]
}]
}
html:
<div data-bind="foreach:cats">
<span data-bind="text:name"></span>
<table>
<tr data-bind="foreach: kittens">
<td data-bind="text:name"></td>
<td data-bind="text:color"></td>
<td><a data-bind="click: $parent:showParentColor" href="#">Parent Color</a></td>
</tr>
</table>
</div>
Javascript:
var KittenModel = function (data) {
ko.mapping.fromJS(data, {}, this);
// ... various computed values added to this
}
var mapping = {
'kittens': {
create: function(options) {
return new KittenModel(options.data);
}
},
'otherItem': {
create: function(options) {
return ('otherStuff');
}
}
}
var data = { ... }; // the JSON above
var CatsViewModel = ko.mapping.fromJS(data, mapping);
问题:
在哪里以及如何放置 showParentColor() 函数,以便数据绑定在小猫中工作 table?例如:
function showParentColor(cat) {
alert(cat.color);
}
谢谢!
您可以根据您的视图模型层次结构使用以下其中一项:
- $root :这指向根 context.The 最顶层 parent 上下文中的主视图模型 object。
$parents 数组: 这是一个包含所有视图模型的数组。
$parents[0] : parent 视图模型上下文。(也与
$parent
)$parents[1]:第二个parent视图模型上下文。(grand parent)
$parents[2]:第三个parent查看模型上下文。 (great-grand parent)
- 等等....
更新:
如果你想在 CatsViewModel
级别添加一个函数,你只需将你的函数添加到创建的模型中。
示例:https://jsfiddle.net/kyr6w2x3/87/
JS:
CatsViewModel.showParentColor = function(item){
console.log(item.name());
console.log(item.color());
}
查看:
<a data-bind="click: $parents[1].showParentColor">
以下是您的模型的层次结构
- CatsViewModel
- cats : observableArray
- name : observable
- color : observable
- kittens : observableArray
- name : observable
- color : observable
- showParentColor : function
备选方案: 您可以自己完成这项工作并创建您的 models.Would 更容易根据您的内容进行修改和维护 want.You 也可以添加
click
在你想要的任何模型中运行。
示例:http://jsfiddle.net/kyr6w2x3/91/
HTML :
<div data-bind="foreach:cats">
<span data-bind="text:name"></span>
<table>
<tbody data-bind="foreach: kittens">
<tr>
<td data-bind="text:name"></td>
<td data-bind="text:color"></td>
<td><a data-bind="click: $parent.showParentColor" href="#">Parent Color</a></td>
</tr>
</tbody>
</table>
</div>
JS:
var data = {
"cats": [{
"name": "fluffy",
"color": "brown",
"kittens": [{
"name": "spot",
"color": "brown"
}, {
"name": "rascal",
"color": "grey"
}, {
"name": "trouble",
"color": "white"
}]
}, {
"name": "kitty",
"color": "red",
"kittens": [{
"name": "lady",
"color": "red"
}, {
"name": "skat",
"color": "striped"
}]
}]
}
var CatsViewModel = function (data){
var self = this;
self.cats = ko.observableArray($.map(data.cats, function (item) {
return new CatItemViewModel(item);
}));
}
var CatItemViewModel = function (data){
var self = this;
self.name = ko.observable(data.name);
self.color = ko.observable(data.color);
self.kittens = ko.observableArray($.map(data.kittens, function (item) {
var newData = Object.assign({}, item, { parent: self.name()});
return new KittenModel(newData);
}));
self.showParentColor = function (item){
console.log("Parent Name: " , self.name());
console.log("Name: " , item.name());
console.log("Color: " , item.color());
}
}
var KittenModel = function (data) {
var self = this;
self.name = ko.observable(data.name);
self.color = ko.observable(data.color);
self.parent = ko.observable(data.parent);
}
var vm = new CatsViewModel(data);
ko.applyBindings(vm);
注意:我更喜欢其他答案的方法而不是这个方法,但是为了有多个选项,我确实想提出一个替代解决方案。
备选方案 1
您可以在 KittenModel
中创建一个 "static" 方法来记录它通过的任何猫的颜色:
var KittenModel = function (data) {
ko.mapping.fromJS(data, {}, this);
};
KittenModel.logCatColor = function(cat) {
console.log(cat.color);
};
现在,因为您的视图可以访问父子结构,所以您可以使用任何您想要的父级调用此方法:
<!-- to log the parent's color -->
<div data-bind="click: logCatColor.bind(null, $parent)"></div>
<!-- knockout automatically passes `$data` as a first argument,
so you won't need to bind the method to log your own color -->
<div data-bind="click: logCatColor"></div>
一个例子:
ko.applyBindings({
name: "parent",
child: {
name: "child",
logName: function(entity) {
console.log(entity.name);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<h1 data-bind="text: name"></h1>
<div data-bind="with: child" style="border: 1px solid black">
<h2 data-bind="text: name">
</h2>
<button data-bind="click: logName">
log my name
</button>
<button data-bind="click: logName.bind(null, $parent)">
log my parent's name
</button>
</div>
备选方案 2
在作为选项传递的工厂函数中,data
和 parent
都可用:options.data
包含当前映射的项目。 options.parent
在这种情况下将引用父级 cat
。我还没有测试过这个,但这可能有效:
'kittens': {
create: function(options) {
var dataWithParent = Object.assign({},
options.data,
{ parent: options.parent });
return new KittenModel(dataWithParent);
}
},