2013-07-18 24 views
7

Tôi đang cố gắng triển khai một hoạt ảnh nơi một mục hoạt hình ở bên trái sau khi nó được chọn. Mã sau hoạt động. Nhưng chỉ khoảng 80% thời gian.Hình động Meteor

JS

//myItem 
Template.myItem.rendered = function(){ 
    if(Session.get("selected_item") === this.data._id){ 
    $(this.firstNode).addClass("selected"); 
    } else { 
    $(this.firstNode).removeClass("selected"); 
    } 
}; 

Template.myItem.events({ 
    "click .myItem": function(evt, template){ 
    Session.set("selected_item", this._id); 
    } 
}); 


//myItemList 
Template.myItemList.helpers({ 
    items: function(){ 
    return Items.find(); 
    } 
}); 

Templates

<template name="myItem"> 
    <div class="myItem">{{name}}</div> 
</template> 

<template name="myItemList"> 
    {{#each items}} 
    {{> myItem}} 
    {{/each}} 
</template> 

CSS

.myItem { transition: all 200ms 0ms ease-in; } 
.selected { left: -20px; } 

Tôi cũng đã cố gắng để bọc các mã vào một Meteor.defer() để đảm bảo rằng thực sự tất cả mọi thứ đã sẵn sàng để làm phim hoạt hình .

Template.myItem.rendered = function(){ 
    Meteor.defer(function() { 
    if(Session.get("selected_item") === this.data._id){ 
     $(this.firstNode).addClass("selected"); 
    } else { 
     $(this.firstNode).removeClass("selected"); 
    } 
    }); 
}; 

Nhưng mà kết quả trong loại lỗi:

Exception from defer callback: TypeError {} 

Nó sẽ là tuyệt vời để xem bất kỳ ý tưởng làm thế nào để làm cho công việc hoạt hình mọi lúc.

CẬP NHẬT

Krab có câu trả lời đúng. Ngoại lệ đến từ tham chiếu this. Tôi muốn thêm một số chi tiết. Vì vậy, đây là hai phiên bản làm việc trên như thế nào để làm hoạt hình:

với Meteor.defer()

Template.myItem.rendered = function(){ 
    var instance = this; 
    if(Session.get("selected_item") === this.data._id){ 
    Meteor.defer(function() { 
     $(instance.firstNode).addClass("selected"); //use "instance" instead of "this" 
    }); 
    } 
}; 

(Chúng tôi không thực sự cần những khối khác ở đây vì sao băng sẽ loại bỏ các lớp selected nếu nó vẽ lại mặt hàng đó.)

hoặc với $().animate()

Template.myItem.rendered = function(){ 
    if(Session.get("selected_item") === this.data._id){ 
    $(this.firstNode).animate({ 
     left: "-20px" 
    }, 300); 
    } 
}; 

Nếu bạn sử dụng phương pháp jQuery bạn cần phải loại bỏ các mã CSS.

.myItem { transition: all 200ms 0ms ease-in; } 
.selected { left: -20px; } 

+0

Vì vậy, trả lại gọi lại được gọi khi một cái gì đó được trả lại, vậy tại sao nó nên được gọi khi một cái gì đó được chọn? Chúng ta sẽ nhận được nhiều mã hơn. – Krab

+0

Lệnh gọi lại được gọi trên mọi 'Session.set (" selected_item ", id);'. Tôi đã thêm một số mã để làm cho bối cảnh tổng thể rõ ràng hơn. –

Trả lời

3

thử điều này, bởi vì this con trỏ trong Hoãn callback là không giống như nếu mã được thực hiện trực tiếp trong callback render

Template.myItem.rendered = function(){ 
    var self = this; 
    Meteor.defer(function() { 
    if(Session.get("selected_item") === self.data._id){ 
     $(self.firstNode).addClass("selected"); 
    } else { 
     $(self.firstNode).removeClass("selected"); 
    } 
    }); 
}; 
+0

Xin cảm ơn! Tôi hoàn toàn bỏ qua 'this'in chức năng trì hoãn. Sau khi thay thế 'this' mọi thứ hoạt động tốt. –