[英]Backbone.js - How to create a collection that has bindable properties
這是一個人為的例子,但我相信它可以解決這個問題。
讓我們說我有一個骨干車系列。 對於集合,我想要一個名為isValid的屬性。 我希望其他對象能夠綁定到isValid並在isValid更改時觸發函數。 集合isValid屬性將根據集合中的模型進行更改。
例如,如果所有車門都鎖定在每輛車上,那么isValid應該更改為true。 當isValid更改時,應觸發綁定到isValid change事件的所有函數。
我的問題是,如何創建一個具有與模型屬性類似的可綁定屬性的集合?
這是我想要工作的代碼。
var Car = Backbone.Model.extend({});
var Cars = Backbone.Collection.extend({
model: Car,
url: "Cars",
isValid: false, //Here's the property that I want bindable
//but do not know how to accomplish this.
});
var cars = new Cars();
//Call a function when cars.isValid changes
cars.bind("change:isValid", carsIsValidChanged, cars)
//Not sure if this what the function would look like
//but would need access to cars.isValid or just the car collection
function carsIsValidChanged(isValid){
console.log(isValid);
}
請在下面查看我的完整解決方案。
因此,沒有“內置”方式來響應Collection上的屬性更改,因為實際上沒有支持的方式(我知道)在集合上具有屬性。 但是,我估計它仍然完全可能。 (未經測試,但應該相當接近)
var Car = Backbone.Model.extend({});
var Cars = Backbone.Collection.extend({
model: Car,
url: "Cars",
initialize: function() {
var self = this;
this.isValid = false;
this.bind('add', function() {
var curValid = true;
self.each(function(car) {
if(car.get('is_locked') != true) {
curValid = false;
}
});
if(curValid != self.isValid) {
self.isValid = curValid;
self.trigger('change:isValid', self.isValid, self);
}
});
}
});
// instantiate a new Cars collection
var cars = new Cars();
function carsIsValidChanged(isValid){
console.log(isValid);
}
//Call a function when cars.isValid changes
cars.bind("change:isValid", carsIsValidChanged)
一個注意事項:您不希望isValid:列為屬性,就像您建模或網址一樣。 這似乎使骨干很奇怪,你的isValid可能會跨越集合的所有實例。 最好將它們定義為初始化程序,然后每次實例化該集合時,您都可以通過this.isValid正確地訪問isValid的實例。
你可以使用這樣的東西;
Backbone.Collection.prototype.bindableProperty = function (key, val) {
var self = this;
Object.defineProperty(this, key, {
configurable: false,
get: function () { return val; },
set: function (v) {
val = v;
self.trigger('change:'+key, val)
}
});
};
只需這樣做即可添加屬性;
var Cars = Backbone.Collection.extend({
model: Car,
url: "Cars",
initialize: function () {
this.bindableProperty('isValid', false);
}
});
但警告; 舊版本的IE不支持Object.defineProperty。
這是我對這個問題的完整解決方案: jsFiddle完整示例
@spotmat讓我走向正確的方向,但我需要添加其他功能。 這里有一些需要解決的問題:
我不確定是否將一個綁定屬性添加到一個集合是一個好主意,但是這很有趣,我學到了很多東西。
var log = {};//this is for debugging
_.extend(log, Backbone.Events);
var Car = Backbone.Model.extend({});
var Cars = Backbone.Collection.extend({
model: Car,
url: "scripts/data/Cars.json",
initialize: function () {
var _this = this;
this.isValid = false; //user should bind to "change:isValid"
this._isPending = false; //This is so that
this.bind("add", this.modelAdded, this);
this.bind("reset", this.modelsAdded, this);
if (this.length > 0) {
//Model passed in though the constructor will not be binded
//so call modelsAdded
this.modelsAdded(this);
}
},
modelsAdded: function (collection) {
this._isPending = true
log.trigger("log", ["modelsAdded: " + collection.length]);
collection.each(this.modelAdded, this); //Do nut remove "this" param. It need when modelAdded gets called
this._isPending = false
this._validate();
},
modelAdded: function (model) {
log.trigger("log", ["modelAdded: " + model.get("Model") + "; IsLocked: " + model.get("IsLocked")]);
//!!!for each model added to the colleciton bind
//its IsLocked property to the collection modelIsLockedChange function
model.bind("change:IsLocked", this.modelIsLockedChanged, this);
if (this._isPending == false) {
this._validate();
}
},
modelIsLockedChanged: function (model) {
log.trigger("log", ["modelIsLockedChanged:" + model.get("Model") + "; IsLocked: " + model.get("IsLocked")]);
this._validate();
},
_validate: function () {
var isValid = true;
this.each(function (model) {
if (model.get("IsLocked") == false) {
isValid = false
}
});
if (this.isValid != isValid) {
this.isValid = isValid
cars.trigger("change:isValid", [this.isValid])
}
},
});
此視圖僅用於調試目的
var Logger = Backbone.View.extend({
el: $("#output"),
initialize: function(){
log.bind("log", this.logMessage, this)
},
render: function(){
return $(this.el).html("");
},
logMessage: function(message){
$(this.el).find("ul").append("<li>" + message[0] + "</li>");
}
})
以下代碼用於測試集合
var logger = new Logger();
log.bind("log", function(message){
console.log(message[0]);
});
var carsData = [
{ "Model": "Chevy Camero", "Year": 1982, "IsLocked": true },
{ "Model": "Ford F-150", "Year": 2011, "IsLocked": false }
]
var cars = new Cars(carsData);
cars.bind("change:isValid", function(isValid){
log.trigger("log", ["change:isValid: " + isValid]);
});
cars.add({ "Model": "Toyota Tacoma", "Year": 2006, "IsLocked": true });
cars.at(1).set({ "IsLocked": true });
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.