2012-07-29 15 views
5

Tôi đang cố trả lời câu hỏi này: emberjs: add routes after app initialize()Chơi với Ember.Object.reopen(), tại sao tôi có những kết quả này?

Tôi bắt đầu chơi với Ember.Object.reopen(), để hiểu cách hoạt động và có thể tìm cách trả lời câu hỏi trước.

tôi cảm thấy một chút bối rối, và không hiểu hành vi của mã này:

jsfiddle: http://jsfiddle.net/Sly7/FpJwT/

<script type="text/x-handlebars"> 
    <div>{{App.myObj.value}}</div> 
    <div>{{App.myObj2.value}}</div> 
    <div>{{App.myObj3.value}}</div> 
</script> 
App = Em.Application.create({}); 

App.MyObject = Em.Object.extend({value: 'initial'}); 

App.set('myObj', App.MyObject.create()); 

Em.run.later(function(){ 
    App.get('myObj').reopen({ 
    value: "reopenOnInstance"   
    }); // the template is not updated, 'initial' is still diplayed, but 
    console.log(App.get('myObj').get('value')); // print 'reopenOnInstance' 

    App.MyObject.reopen({ 
    value: "reopenOnClass"  
    }); 
    App.set('myObj2',App.MyObject.create()); // the template is updated and 
    console.log(App.get('myObj2').get('value')); //print 'reopenOnClass' 

    App.myObj3 = App.MyObject.create(); // the template is not updated but 
    console.log(App.myObj3.get('value')); // print 'reopenOnClass' 

    Em.run.later(function(){ 
    App.get('myObj').set('value', "setWithSetter"); // the template is updated and 
    console.log(App.get('myObj').get('value')); // print 'setWithSetter' 

    App.get('myObj2').set('value', "setWithSetter"); // the template is updated and 
    console.log(App.get('myObj2').get('value')); // print 'setWithSetter' 

    App.myObj3.set('value', "setWithSetter"); // the template is not updated but 
    console.log(App.myObj3.get('value')); // print 'setWithSetter' 

    }, 2000); 
},2000); 

Nếu ai đó có thể giải thích những gì đang xảy ra, đặc biệt là lý do tại sao các mẫu đôi khi không được cập nhật, đôi khi được cập nhật và cũng có sự khác nhau giữa việc gọi số reopen trên một lớp, gọi nó là gì và trên một cá thể.

Trả lời

5

Không chắc chắn 100%, nhưng tôi sẽ cố gắng trả lời các câu hỏi của bạn.

Trước tiên, hãy xem "myObj3". Các phương thức getter/setter của ember kích hoạt các bản cập nhật trong các khuôn mẫu (chúng kích hoạt các sự kiện nội bộ khiến mọi thuộc tính/người quan sát biết điều gì đó đã xảy ra). Chỉ cần đặt giá trị bằng tay sẽ cập nhật giá trị nhưng sẽ không kích hoạt các sự kiện này và do đó không có gì thay đổi trong giao diện người dùng. Giống như khi bạn sử dụng danh sách Mutable bạn sử dụng pushObject để đảm bảo cập nhật giao diện người dùng.

Bây giờ, hãy xem "mở lại" của bạn. Khi bạn mở lại lớp, nó hoạt động như bạn mong đợi và cập nhật lớp cơ sở. Khi bạn mở lại một thể hiện nó thực sự tạo ra một mixin và shims nó trên đầu trang của đối tượng. Điều này có nghĩa là khi bạn thực hiện "get" ember lặp lại đối tượng mixin & cho giá trị trả về. Nó tìm thấy mixin và nhận giá trị trước đối tượng; bạn thực sự có thể thay thế phương thức bằng một hàm 'return' foo '+ this._super()' trên cá thể bạn sẽ nhận được 'foo initial' (nghĩ về đối tượng của bạn có các layer giống như một onion). Nếu bạn có một nhóm mixin trên đầu của đối tượng của bạn, bạn sẽ có một thời gian khó tìm giá trị chính xác nếu bạn đặt một cái gì đó trực tiếp (nhưng "get" sẽ hoạt động hoàn hảo). Điều này dẫn đến quy tắc chung rằng bạn nên luôn sử dụng "set" thay vì tham chiếu trực tiếp.

Lưu ý phụ: Bạn có thể gọi "getPath" thay vì "get" và bạn có thể sử dụng đường dẫn tương đối hoặc tuyệt đối. Chẳng hạn như App.getPath ('myObj2.value') sẽ làm cho mã dễ quản lý hơn một chút. Đi cho "setPath" cũng.

Cuối cùng: Giá trị cuối cùng in vì bạn đã thay đổi giá trị (nó ở trong đó) nhưng trình kích hoạt cho ember để cập nhật ui không bao giờ bị sa thải vì bạn chưa bao giờ được đặt trên đối tượng "myObj3".

EDIT: Trong phiên bản mới nhất của ember có vẻ như mở lại trên một thể hiện không hợp nhất xuống đối tượng (nếu khóa đó đã tồn tại). Bản mixin sẽ chỉ quấn nếu bạn đang thêm nội dung mới.

+0

Tất cả đều có ý nghĩa. Cảm ơn bạn rất nhiều bạn đã khai sáng cho tôi. Vì vậy, nếu tôi hiểu tốt, mở lại một thể hiện như tôi làm ở đây, có hành vi tương tự như làm 'App.get ('myObj'). Value = 'reopenOnInstance'' phải không? Tôi đã nhận thức được phương thức getPath, và bây giờ với ember mới nhất, get có cùng hành vi, bạn có thể làm 'obj.get ('otherObj.someProperty')'. –

+0

Xem chỉnh sửa. Điều này có nghĩa rằng bạn là chính xác, thiết lập giá trị trực tiếp sẽ giống như một reopen trên một thể hiện. Nhưng nếu bạn có một cái gì đó ràng buộc với giá trị đó (chẳng hạn như giao diện người dùng) Ember sẽ ném một lỗi bởi vì "thiết lập" không được sử dụng (thực hiện một [fiddler] (http://jsfiddle.net/scispear/n5B5d/) để xem lỗi). – SciSpear

+0

Cảm ơn bạn lần nữa vì đã chỉnh sửa :). Tôi nghĩ bây giờ câu trả lời đã hoàn thành vì tôi không còn gì để làm sáng tỏ. –

Các vấn đề liên quan