我有一个非常基本的动态表单,我在其中使用 Knockout.js 框架。我可以根据需要实时添加或删除联系人。我在将 json 对象保存在文本区域内时遇到了一些困难。在下面的函数中,self.save
获取值并将它们放入 json 对象中。然后textarea保存属性data-bind=’value:lastSavedJson’
,它保存json对象。我正在努力解决的棘手问题是每次在输入字段、复选框或选择菜单上触发 keyup,change
时都要执行此操作。最初,这是通过触发按钮来完成的。每次触发按键、复选框、选择菜单时,如何将值保存在 json 对象中? JSFIDDLE
var initialData = [{
firstName: "Jenny",
lastName: "LaRusso",
phone: "(555) 121-2121",
alt_phone: "(555) 123-4567",
main1: false,
main2: true
}, {
firstName: "Sensei",
lastName: "Miyagi",
phone: "(555) 444-2222",
alt_phone: "(555) 999-1212",
main1: true,
main2: false
}];
var ContactsModel = function (contacts) {
var self = this;
self.contacts = ko.observableArray([]);
ko.utils.arrayForEach(contacts, function (contact) {
self.contacts.push({
firstName: contact.firstName,
lastName: contact.lastName,
phone: contact.phone,
alt_phone: contact.alt_phone,
main1: ko.observable(contact.main1),
main2: ko.observable(contact.main2)
});
});
$.getJSON("functions/getPerson.php", function(allData) {
var initialData = $.map(allData, function(person) { return new ContactsModel(person) });
console.log(self.contacts(initialData));
});
self.addContact = function () {
self.contacts.push({
firstName: "",
lastName: "",
phone: "",
alt_phone: "",
main1: false,
main2: false
});
};
self.removeContact = function (contact) {
self.contacts.remove(contact);
};
self.addPhone = function (contact) {
contact.phones.push({
number: ""
});
};
self.removePhone = function (phone) {
$.each(self.contacts(), function () {
this.phones.remove(phone)
})
};
$("input,checkbox,selct").bind('change keyup', function() {
self.save = function () {
self.lastSavedJson(JSON.stringify(ko.toJS(self.contacts), null, 2));
};
});
self.lastSavedJson = ko.observable("");
};
ko.applyBindings(new ContactsModel(initialData));
最佳答案
我对您的 View 模型做了一些更改,因此它们的布局更好了一些。另外,您会注意到我删除了 jQUery 位...这就是原因。 1) 一般来说,如果您发现自己使用 jQuery 并引用 knockout View 模型中的 dom,那么您就做错了/有一种更好的方法可以惯用来实现,即 knockout 方式。这使您的 View 模型与模板分开。
2) 这永远不会按照你想要的方式工作。 Knockout 将根据需要添加和删除 dom 部分,而 jQuery 将仅绑定(bind)到运行查询时页面上存在的事件。有一种技术可以发挥作用,但 knockout 实际上会干扰事件冒泡,这就是为什么上面的原因#1 非常相关。有关更多信息,如果您好奇,请查看 jQuery on 并找出 $("input,select").change(changeHandler)
和 $("body"之间的行为差异).on('更改','输入,选择',changeHandler);
var initialData = [{
firstName: "Jenny",
lastName: "LaRusso",
phone: "(555) 121-2121",
alt_phone: "(555) 123-4567",
main1: false,
main2: true
}, {
firstName: "Sensei",
lastName: "Miyagi",
phone: "(555) 444-2222",
alt_phone: "(555) 999-1212",
main1: true,
main2: false
}];
var ContactModel = function(contact) {
var self = this;
self.firstName = ko.observable(contact.firstName);
self.lastName = ko.observable(contact.lastName);
//what is the point of the phone observable when there is an array of phones?
//the data structure doesn't match either - self.phone contains a phone number, and
//self.phones contains objects with a 'number' property
self.phone = ko.observable(contact.phone);
//array for all the phones, initialize it with the passed in data or an empty array
self.alt_phone = ko.observable(contact.alt_phone);
self.phones = ko.observableArray(contact.phones || []);
self.main1 = ko.observable(contact.main1);
self.main2 = ko.observable(contact.main2);
}
var ContactsModel = function (contacts) {
var self = this;
self.contacts = ko.observableArray(ko.utils.arrayMap(contacts || [], function(contact) { return new ContactModel(contact)}));
//this ajax call is going to override the default data passed in via the contacts parameter...Is that what's supposed to happen?
$.getJSON("functions/getPerson.php", function(allData) {
var initialData = $.map(allData, function(person) { return new ContactModel(person) });
console.log(self.contacts(initialData));
});
self.addContact = function () {
self.contacts.push(new ContactModel());
};
self.removeContact = function (contact) {
self.contacts.remove(contact);
};
//your contacts didn't have a phone array, so I added one to make this function work.
self.addPhone = function (contact) {
contact.phones.push({
number: ""
});
};
self.removePhone = function (phone) {
$.each(self.contacts(), function () {
this.phones.remove(phone)
})
};
};
var mainModel = new ContactsModel(initialData);
var modelWithSerializedData = {
MainModel:mainModel,
mainModelSerialized: ko.computed(function() {
return ko.toJSON(mainModel);
})
}
ko.applyBindings(modelWithSerializedData);
然后在您的 View 中,使用“with”访问主模型,并仅将输入包装在您提交的表单中,或者避免在模板输入上放置名称,这样它们就不会与 json 数据一起提交。 另外,请确保在输入上使用 valueUpdate 绑定(bind),以便立即序列化。
<div data-bind="with:MainModel">
<!--the rest of your template -->
<ul data-bind="foreach:contacts">
<li>
<label>First Name:
<input data-bind="value:firstName, valueUpdate:'afterkeydown'" />
</label>
</li>
</ul>
</div>
<form>
<textarea name="data" data-bind='value: serializedModel' rows='25' cols='60'></textarea>
<input type="hidden" name="serializedModel" data-bind="value:mainModelSerialized" />
</form>
关于javascript - 当触发按键、复选框或选择时将值保存到 json 对象中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22136156/