因此,如果我使用Ractive.extend()来实例化自定义类的对象,那么我将如何引用该类中的DOM元素?我显然不能像往常一样使用document.getElementById(),因为DOM还没有被渲染,并且将Ractive.findComponent()传递给我的构造函数返回" Ractive.findComponent不是函数。 #34;我想做的是这样的事情:
class myClass {
constructor(id /*,...*/) {
this.element = document.getElementById(id); //how do I do this??
};
};
var Extended = Ractive.extend( {
oninit() {
var myObject = new myClass(id /*,...*/);
this.set({myObject});
}
});
var ractiveExtended = new Extended({
el: document.body,
template: '#template',
data: { id: myId}
});
ETA:这不起作用......
class myClass {
constructor(id /*,...*/) {
this.element = document.getElementById(id);
};
};
var Extended = Ractive.extend( {
onrender() {
var myObject = new myClass(id /*,...*/);
this.set({myObject});
}
});
var ractiveExtended = new Extended({
el: document.body,
template: '#template',
data: { id: myId}
});
这也不是......
class myClass {
constructor(id /*,...*/) {
this.element = id;
this.element.innerHTML = 'Hello world!';
};
};
var Extended = Ractive.extend( {
onrender() {
var myObject = new myClass(document.getElementById(id) /*,...*/);
this.set({myObject});
}
});
var ractiveExtended = new Extended({
el: document.body,
template: '#template',
data: { id: myId}
});
答案 0 :(得分:0)
更新了评论中澄清的问题的答案
你这里有一点鸡蛋问题:
{{#each sprites}}
<canvas id={{.id}}></canvas>
{{/each}}
表示Ractive会为<canvas>
中的每个项目创建sprites
,并为其指定相应的ID。但是,sprites
在初始渲染时未定义,因此不会创建<canvas>
个元素。
然后,在onrender()
内部创建您的类的实例,假设<canvas>
元素已经存在。只有在此之后,您才将实例添加到sprites
,告诉Ractive渲染元素:
this.set({ sprites });
有几种可能的解决方案。 (我认为)最好的方法是在你的类中添加一个render()
方法,并从构造函数中移除任何与DOM相关的东西。然后,您的代码将更改为以下内容:
onrender () {
var sprites = this.get('repeaters').map(function(repeater){
return new CanvasSprite(repeater.id);
});
this.set({ sprites });
sprites.forEach(function (sprite) {
sprite.render();
});
}
但是,如果您不想修改类,则只需将现有repeaters
数组用于{{each}}
循环即可。在这里演示:http://jsfiddle.net/9xLzj3zd/1/
关键是,您需要一种方法来告诉Ractive在使用<canvas>
或类似方法之前呈现document.getElementsById()
元素。
原始回答
如果您需要访问DOM,请将初始化代码从oninit
移至onrender
。然后,您可以使用document.getElementById()
或ractive.find()
(documentation here)来获取所需的元素。
class myClass {
constructor(id) {
this.element = document.getElementById(id);
this.element.innerHTML = 'Hello world!';
};
};
var Extended = Ractive.extend( {
onrender() {
// use this.get('id') to get ID from Ractive's data
var myObject = new myClass(this.get('id'));
this.set({myObject});
}
});
var ractiveExtended = new Extended({
el: document.body,
template: '#template',
data: { id: 'content' },
});
答案 1 :(得分:0)
编辑:完整运行示例:http://jsbin.com/vuziyepeku/edit?html,js,output
我会将每个CanvasSprite
封装在其自己的组件中:
const CanvasSpriteComponent = Ractive.extend({
template: '#sprite',
// Using onrender, not oninit, because we need DOM canvas node
onrender(){
const canvas = this.find('canvas');
const repeater = this.get('repeater');
var sprite = new CanvasSprite(canvas, repeater.width, repeater.height, repeater.spriteSheetURL, repeater.rows, repeater.columns, repeater.totalFrames);
sprite.left = repeater.left; //add variables *not* in the constructor
sprite.setFrame(0);
this.on('setFrame', function (event) {
var offsetY = event.original.clientY - event.node.getBoundingClientRect().top;
var relY = offsetY/sprite.height;
sprite.setFrame(relY);
});
}
});
然后在主实例中使用它:
var CanvasAnimation = Ractive.extend( {
template: '#animation',
components: {
'canvas-sprite': CanvasSpriteComponent
}
});
var canvasAnimation = new CanvasAnimation({
el: 'main',
data: { repeaters: repeater }
});
可以说,你的CanvasSprite
类更有意义采用画布节点,因为它不再依赖于该节点所在的 (当前document.getElementById
)。
如果您根本不愿意更改该类,则只需要编写一个唯一的ID(如果转发器集合不会变异,则使用索引)。在这种情况下,我重复使用该组件的唯一ID:
const CanvasSpriteComponent = Ractive.extend({
// ...
onrender(){
const canvas = this.find('canvas');
canvas.id = `canvas-${this._guid}`
const repeater = this.get('repeater');
var sprite = new CanvasSprite(canvas.id, repeater.width, repeater.height, repeater.spriteSheetURL, repeater.rows, repeater.columns, repeater.totalFrames);
sprite.left = repeater.left; //add variables *not* in the constructor
sprint.setFrame(0);
this.on('setFrame', function (event) {
var offsetY = event.original.clientY - event.node.getBoundingClientRect().top;
var relY = offsetY/sprite.height;
sprite.setFrame(relY);
});
}
});