Javascript 从DOM而不是从ViewModel更新敲除'attr'绑定
我使用Knockout.js来填充一组HTML5Javascript 从DOM而不是从ViewModel更新敲除'attr'绑定,javascript,html,dom,knockout.js,details,Javascript,Html,Dom,Knockout.js,Details,我使用Knockout.js来填充一组HTML5元素。结构如下: <div class="items" data-bind="foreach: Playlists"> <details class="playlist-details" data-bind="attr: {id: 'playlist-details-' + $index(), open: isOpen}"> <summary> <span d
元素。结构如下:
<div class="items" data-bind="foreach: Playlists">
<details class="playlist-details" data-bind="attr: {id: 'playlist-details-' + $index(), open: isOpen}">
<summary>
<span data-bind="text: name"></span> - <span data-bind="text: count"></span> item(s)
<div class="pull-right">
<button data-bind="click: $parent.play, css: {disabled: count() == 0}, attr: {title: playbtn_title}" class="btn"><i class="icon-play"></i> Play</button>
<button data-bind="click: $parent.deleteList" class="btn btn-danger"><i class="icon-trash"></i> Delete</button>
</div>
</summary>
<div class="list" data-bind="with: items" style="padding-top: 2px;">
...
</div>
</details>
</div>
-项目
玩
删除
...
ViewModel中的数据如下所示:
var VM = {
Playlists: [
{
name: "My Playlist1",
count: 3,
items: [<LIST OF SONG ID'S>],
playbtn_title: "Play this playlist",
isOpen: true
},
{
name: "My Playlist2",
count: 5,
items: [<LIST OF SONG ID'S>],
playbtn_title: "Play this playlist",
isOpen: null
},
{
name: "My Playlist3",
count: 0,
items: [],
playbtn_title: "You need to add items to this list before you can play it!",
isOpen: null
}
]
};
var-VM={
播放列表:[
{
名称:“我的播放列表1”,
计数:3,
项目:[],
播放标题:“播放此播放列表”,
等参:空
},
{
名称:“我的播放列表3”,
计数:0,
项目:[],
playbtn_title:“在播放之前,您需要将项目添加到此列表中!”,
等参:空
}
]
};
我已经添加了使用ViewModel的isOpen
属性和attr
绑定(如最初所述)记住详细信息视图的功能
但是,当我单击
展开详细信息时,ViewModel不会得到更新-与值
绑定不同,属性
绑定不是双向的
如何在属性值更改时更新此绑定
我知道当元素打开或关闭时,浏览器会触发
domsubtreemeding
事件,但是我;我不确定我会把什么放在那里-我尝试过的几件事(包括.notifySubscribers()
,if(list.open())…
,等等)会导致循环,其中正在更改的属性会再次触发事件,再次更改属性,再次触发事件,等等。我最后发现的有效方法就是让domsubtreedimmeding
“手动”更新值:
$(document).on('DOMSubtreeModified', 'details.playlist-details', function(e) {
var list = ko.dataFor(this);
list.open(this.getAttribute('open'));
});
(不知何故,这不会导致我尝试过的更复杂的构造所导致的循环。)使用
$
直接播放DOM不是ko
方式:-)
只需为HTML5details
tag创建一个双向绑定,这在ko中很便宜
ko.bindingHandlers.expose={
init:函数(元素、值访问器){
if(element.tagName.toLowerCase()!==“详细信息”){
抛出“\”discover\“绑定只对标签有效!”;
}
var value=valueAccessor();
if(可维护的高值){
$(element).on(“domsubtreemedited”,function(){
值($(element.prop('open'));
});
}
},
更新:函数(元素、值访问器){
$(element.prop('open',ko.unwrap(valueAccessor()));
}
};
ko.bindingHandlers.disclose = {
init: function(element, valueAccessor) {
if (element.tagName.toLowerCase() !== 'details') {
throw "\"disclose\" binding only works on <details> tag!";
}
var value = valueAccessor();
if (ko.isObservable(value)) {
$(element).on("DOMSubtreeModified", function() {
value($(element).prop('open'));
});
}
},
update: function(element, valueAccessor) {
$(element).prop('open', ko.unwrap(valueAccessor()));
}
};