我正在尝试使用Knockout.js在javascript对象和一些DOM元素之间创建双向绑定。我希望我的对象能够反映DOM元素的变化,反之亦然。我成功实现了第一个目标,反之亦然,我无法开始工作。
myPerson = {
firstName : "",
lastName : "",
age : null,
test : function() {alert('Testing');}
};
myViewModel = function myViewModel(obj) {
this.firstName = ko.observable();
this.lastName = ko.observable();
this.age = ko.observable();
this.fullName = ko.computed(function() {
obj.firstName = (this.firstName() || '');
obj.lastName = (this.lastName() || '');
obj.age = (this.age() || '');
return (this.firstName() || '') + ' ' + (this.lastName() || '');
}, this);
};
ko.applyBindings(new myViewModel(myPerson));
//How to get property changes reflected in the DOM inputs?
当我在DOM输入中进行更改时,myPerson对象的属性会相应地更改。下一步是手动更改这些属性,并自动查看de DOM输入中反映的这些更改。我试图搞乱地图插件但到目前为止还没有雪茄。
答案 0 :(得分:2)
仅使用KO,只更改myPerson
对象的属性不会更改您的viewmodel,因此不会更新DOM。
“KO方式”是将视图模型与myPerson
分开,并通过将observables作为函数调用来更新该视图模型,例如:
myViewModel.firstName("TheNewFirstName");
在现代浏览器上,您可以使用访问者函数在myPerson
上定义您的属性,然后可以引发视图模型会观看的事件或类似事件for,但这需要ECMAScript5(~2009)中添加的功能,这些功能存在于现代浏览器中,但不是IE8及更早版本。它也意味着有效地拥有双视图模型(myPerson
和myViewModel
)。
因此,在使用KO时,您通常只拥有viewmodel本身,并调用observable来更新它们。
这是一个简单的例子“KO方式”:
var vm = {
counter: ko.observable(0)
};
ko.applyBindings(vm, document.querySelector('div'));
var timer = setInterval(function() {
if (vm.counter() >= 20) {
clearInterval(timer);
} else {
vm.counter(vm.counter() + 1);
}
}, 1000);
<div>
<span data-bind="text: counter"></span>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
如果你只是想支持现代浏览器,并希望像你的myPerson
那样使用类似KO的普通对象,你可能会看RivetsJS,它会将getter / setter应用于你的对象对你而言。
这是与铆钉相同的简单示例 - 但它不适用于ECMAScript5之前的引擎:
var obj = {
counter: 0
};
rivets.bind(document.querySelector('div'), obj);
var timer = setInterval(function() {
if (obj.counter >= 20) {
clearInterval(timer);
} else {
++obj.counter;
}
}, 1000);
<div>
{counter}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rivets/0.8.1/rivets.bundled.min.js"></script>
(这不是推荐,只是注意到了选项。我很高兴在正确的项目中使用KO;从未有机会对Rivets做同样的事情。)