Ractivejs 装饰器初始化不一致
Ractivejs decorator inconsistently initialized
参考:http://jsfiddle.net/ffmqd0zz/
html:
<div id='books_container'/>
<script type='ractive/template' id="books">
{{#books}}
<div decorator='decoration' id="{{id}}">
<span> title: {{ title }}</span>
<span> id: {{ id }}</span>
</div>
{{/books}}
</script>
javascript:
var MyDecorator = function(node) {
console.log("init MyDecorator for id: " + $(node).attr('id'));
return { teardown: function() {}};
};
var books = new Ractive({
el: '#books_container',
template: '#books',
data: {books: [{"id": 1174,"title": "franny and zoey"},
{"id": 1175,"title": "moby duck"}]},
decorators: { decoration: MyDecorator }
});
console.log("init complete")
books.set('books', [{"id": 1176,"title": "life, the universe and stuff"},
{"id": 1177,"title": "yellowbrick road"},
{"id": 1178,"title": "grapes of wrath"} ]);
注意装饰器初始化记录到控制台。
当 Ractive 初始化时,"books" 列表中的两个初始项被正确修饰,如 console.log 消息所示。然而,当列表被更改为 "books.set()" 时,Ractive 只装饰列表中的第三项,而 id 为 1176 和 1177 的书籍的装饰器没有被初始化。
它似乎通过在第三个添加的项目上初始化装饰器来优化性能,跳过前两个,即使它们已被替换。
我是不是做错了,或者这是一个错误?请有人建议解决方法。
提前致谢
作为一种变通方法,您可以一次弹出和压入一个数组元素。 See full example。相关代码:
books.pop('books');
books.pop('books');
books.push('books', {"id": 1176,"title": "life, the universe and stuff"});
books.push('books', {"id": 1177,"title": "yellowbrick road"});
books.push('books', {"id": 1178,"title": "grapes of wrath"});
我不确定您看到的行为是否是由于错误造成的。就像你说的,可能是 Ractive 优化了性能。来自 Ractive docs 的一则趣闻:"Directives are just instructions to Ractive - they don't actually get added to the element as attributes."
Ractive 只会更新有变化的东西。对于节点列表 ({{each}}
),有两种用于更新的策略:
- 推送或拼接(或合并)等显式数组修改会产生相同的 DOM 节点修改 - 这意味着 DOM 节点如果未修改则保持原样,否则将被删除或插入。
- 设置数组重用 DOM 节点,但即使在这种情况下,也只有已更改的内容会随着每个列表项的结构而更新。
所以对于装饰器来说,如果它们没有参数,Ractive 将不会更新它们。一种更改此设置以向装饰器添加参数的方法:
<div decorator='decoration:{{id}}' id="{{id}}">
现在,如果装饰器依赖的数据发生变化(参见 http://jsfiddle.net/ffmqd0zz/2/),装饰器将被拆除并重新初始化。
不知何故文档还没有更新,但是你也可以添加一个update
方法到你的装饰器return参数中,它将被调用装饰器因参数值更改而被拆除:
var MyDecorator = function(node, title) {
console.log('new decorator', title);
function tooltip( title ) {
node.title = title;
}
return {
teardown: function() {},
update: function( title ) {
tooltip(title);
}
};
};
参考:http://jsfiddle.net/ffmqd0zz/
html:
<div id='books_container'/>
<script type='ractive/template' id="books">
{{#books}}
<div decorator='decoration' id="{{id}}">
<span> title: {{ title }}</span>
<span> id: {{ id }}</span>
</div>
{{/books}}
</script>
javascript:
var MyDecorator = function(node) {
console.log("init MyDecorator for id: " + $(node).attr('id'));
return { teardown: function() {}};
};
var books = new Ractive({
el: '#books_container',
template: '#books',
data: {books: [{"id": 1174,"title": "franny and zoey"},
{"id": 1175,"title": "moby duck"}]},
decorators: { decoration: MyDecorator }
});
console.log("init complete")
books.set('books', [{"id": 1176,"title": "life, the universe and stuff"},
{"id": 1177,"title": "yellowbrick road"},
{"id": 1178,"title": "grapes of wrath"} ]);
注意装饰器初始化记录到控制台。
当 Ractive 初始化时,"books" 列表中的两个初始项被正确修饰,如 console.log 消息所示。然而,当列表被更改为 "books.set()" 时,Ractive 只装饰列表中的第三项,而 id 为 1176 和 1177 的书籍的装饰器没有被初始化。
它似乎通过在第三个添加的项目上初始化装饰器来优化性能,跳过前两个,即使它们已被替换。
我是不是做错了,或者这是一个错误?请有人建议解决方法。
提前致谢
作为一种变通方法,您可以一次弹出和压入一个数组元素。 See full example。相关代码:
books.pop('books');
books.pop('books');
books.push('books', {"id": 1176,"title": "life, the universe and stuff"});
books.push('books', {"id": 1177,"title": "yellowbrick road"});
books.push('books', {"id": 1178,"title": "grapes of wrath"});
我不确定您看到的行为是否是由于错误造成的。就像你说的,可能是 Ractive 优化了性能。来自 Ractive docs 的一则趣闻:"Directives are just instructions to Ractive - they don't actually get added to the element as attributes."
Ractive 只会更新有变化的东西。对于节点列表 ({{each}}
),有两种用于更新的策略:
- 推送或拼接(或合并)等显式数组修改会产生相同的 DOM 节点修改 - 这意味着 DOM 节点如果未修改则保持原样,否则将被删除或插入。
- 设置数组重用 DOM 节点,但即使在这种情况下,也只有已更改的内容会随着每个列表项的结构而更新。
所以对于装饰器来说,如果它们没有参数,Ractive 将不会更新它们。一种更改此设置以向装饰器添加参数的方法:
<div decorator='decoration:{{id}}' id="{{id}}">
现在,如果装饰器依赖的数据发生变化(参见 http://jsfiddle.net/ffmqd0zz/2/),装饰器将被拆除并重新初始化。
不知何故文档还没有更新,但是你也可以添加一个update
方法到你的装饰器return参数中,它将被调用装饰器因参数值更改而被拆除:
var MyDecorator = function(node, title) {
console.log('new decorator', title);
function tooltip( title ) {
node.title = title;
}
return {
teardown: function() {},
update: function( title ) {
tooltip(title);
}
};
};