2011-07-01 29 views
37

Tôi muốn đặt câu hỏi này là câu hỏi cho câu trả lời là this nhưng tôi không thể làm như vậy, tôi xin lỗi.Mở rộng các giá trị mặc định của siêu mô hình trong Backbone.js

Mở rộng các giá trị mặc định cho lớp con được phản ánh trong lớp cha. Điều này dường như để đánh bại mục đích và tôi thích hợp hơn để liệt kê rõ ràng các giá trị mặc định của lớp cha trong lớp con để có được cấu trúc mà tôi đang tìm kiếm.

var Inventory = Backbone.Model.extend({ 
    defaults: { 
     cat: 3, 
     dog: 5 
    } 
}); 

var ExtendedInventory = Inventory.extend({ 
}); 

_.extend(ExtendedInventory.prototype.defaults, {rabbit: 25}); 

var i = new Inventory(); 
var ei = new ExtendedInventory(); 
console.log(i.attributes); 
console.log(ei.attributes); 

đầu ra này:

{cat: 3, dog: 5, rabbit: 25} 
{cat: 3, dog: 5, rabbit: 25} 

Not what I (và cũng không, tôi giả sử, các op) muốn:

{cat: 3, dog: 5} 
{cat: 3, dog: 5, rabbit: 25} 

Trả lời

49

Vấn đề là Inventory.prototype.defaultsExtended.prototype.defaults có cùng tham chiếu, vì bạn không ghi đè tham chiếu.

Vì vậy, bạn có thể làm điều này trong 2 cách, có thể nhiều hơn nhưng tôi chỉ tìm thấy 2 này:

Edit: Ví dụ đầu tiên là không chính xác (xem ý kiến); xin vui lòng tham khảo thứ hai.

var ExtendedInventory = Inventory.extend({ 
    defaults: { 
     rabit:25 
    } 
}); 

_.extend(ExtendedInventory.prototype.defaults, Inventory.prototype.defaults); 

hoặc

var ExtendedInventory = Inventory.extend({ 
    defaults: _.extend({},Inventory.prototype.defaults, 
     {rabit:25} 
    ) 
}); 

Tôi nghĩ là người đầu tiên có vẻ sạch hơn.

+1

Cảm ơn, @JCorcuera. Tôi nên xem xét kỹ hơn ở _.extend() để tìm ra điều này. Tuy nhiên, một vấn đề với giải pháp này là nếu tôi thay đổi các giá trị mặc định ExtendedInventory thành '{dog: 15, rabbit: 25}' giá trị của ExtendedInventory của 'dog' được ghi đè trở lại thành' 5'. Tôi đoán tôi sẽ quay lại 'for (a in this.eiDefaults) {this.attributes [a] = this.eiDefaults [a];}' trong phương thức 'initialize' của ExtendedInventory. – mcdoh

+0

@mcdoh mm bạn nói đúng nhưng cái thứ hai hoạt động ok. – JCorcuera

+1

Bạn đúng, vì vậy có vẻ như giải pháp thứ hai của bạn là cách để giải quyết vấn đề này. Cảm ơn bạn đã giúp đỡ! – mcdoh

0

Tôi nghĩ bạn nói đúng mà bạn muốn đảm bảo rằng Inventory.prototype.defaults không thay đổi do thêm thỏ vào ExtendedInventory.defaults. Thừa kế protoypical của tôi là không đủ tốt để giải thích rõ ràng lý do tại sao các công trình dưới đây, nhưng tôi nghĩ rằng điều này không những gì bạn muốn nó làm.

ExtendedInventory.defaults = {} 
_.extend(ExtendedInventory.defaults, ExtendedInventory.prototype.defaults, {rabbit: 25}); 

Một điểm quan trọng cần nhớ về phương pháp _.extend là đối số đầu tiên là destination. Nó lấy tất cả các thuộc tính từ các đối số sau đối số đầu tiên và đặt chúng vào đối số đích. Một điểm khác là ExtendedInventory.prototype.defaults === Inventory.prototype.defaults kết quả là true, nghĩa là chúng là cùng một đối tượng, vì vậy nếu bạn thay đổi nguyên mẫu của ExtendedInventory bạn thay đổi nguyên mẫu của Inventory (I ' m không chắc chắn lý do tại sao họ đang bình đẳng mặc dù ở nơi đầu tiên).

18

Tôi nghĩ cách tốt nhất để giải quyết nó là sử dụng phương thức _.defaults của underscore.js.Điều này sẽ cho phép bạn ghi đè giá trị mặc định trong phân lớp Model của bạn:

_.defaults(ExtendedInventory.prototype.defaults, 
      Inventory.prototype.defaults); 

Xem ví dụ này:

http://jsfiddle.net/mattfreer/xLK5D/

3

Là một phần mở rộng của câu trả lời JCorcuera, nếu sử dụng lớp cơ sở của bạn (hoặc có thể sử dụng) một hàm để xác định các giá trị mặc định thì thao tác này sẽ hoạt động độc đáo:

defaults: function() {          
    return _.extend(_.result(Slot.prototype, 'defaults'),{ 
     kind_id: 6,         
     otherthing: 'yello' 
     // add in your extended defaults here         
    })}              

bit chính là sử dụng funciton trong phương pháp mặc định con và _.result()docs

0
var MoveToolModel = ToolModel.extend({ 
    extendDefaults: { 
     cursor: 'move' 
    }, 
    initialize: function() { 
     ToolModel.prototype.initialize.apply(this, arguments); 
     this.defaults = _.extend({}, this.defaults, this.extendDefaults); 
    }, 
    draw: function(canvasContext, data) { 
     //drag 
    } 
}); 
0

Tôi nghĩ underscore.js không mở rộng giá trị sâu. Bạn nên sử dụng Jquery $ .extend nếu bạn có một số mảng. Bạn có thể thử nó here

var basemodel = Backbone.Model.extend({ 
    defaults:{a:{"1":"1","2":4,"4":5},b:2} 
} 
); 

var model1 = basemodel.extend({ 
    defaults: $.extend(false,basemodel.prototype.defaults,{a:{"1":1,"2":2},b:{"xx":13}}) 
}); 


var model2 = basemodel.extend({ 
    defaults: $.extend(false,basemodel.prototype.defaults,{a:{"1":1,"2":2},z:13}) 
}); 



var m1 = new model1(); 
var m2 = new model2(); 


alert(JSON.stringify(m1.toJSON())); 
alert(JSON.stringify(m2.toJSON())); 

Ngoài ra, bạn nên cung cấp thông số đầu tiên "sai" để thực hiện công việc của mình một cách chính xác. khi nó là sự thật, chỉ cần xen kẽ nhau.

0

Tuy nhiên, một cách khác là sử dụng chức năng gạch dưới của _.extend để thực hiện điều này:

var SuperClass = Backbone.Model.extend({ 
    baseDefaults: { 
    baseProp1: val, 
    baseProp2: val2 
    } 
}); 

var SubClass = SuperClass.extend({ 
    defaults: _.extend({ 
    prop1: val, 
    prop2: val2 
    }, SuperClass.prototype.baseDefaults) 
}) 
Các vấn đề liên quan