繁体   English   中英

使用Ractive.extend()时如何引用DOM元素?

[英]How to refer to DOM Elements When Using Ractive.extend()?

因此,如果我使用Ractive.extend()来实例化自定义类的对象,那么我将如何引用该类中的DOM元素? 我显然不能像往常一样使用document.getElementById(),因为尚未呈现DOM并且将Ractive.findComponent()传递给我的构造函数返回“Ractive.findComponent不是函数”。 我想做的是这样的:

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}
});

更新了评论中阐明的问题的答案

你这里有一个鸡蛋问题:

{{#each sprites}}
    <canvas id={{.id}}></canvas>
{{/each}}

表示Ractive将为sprites每个项创建<canvas>并为其分配适当的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/

关键是,在使用document.getElementsById()或类似方法之前,需要一种方法告诉Ractive渲染<canvas>元素。

原始答案

如果需要访问DOM,请将初始化代码从oninit移动到onrender 然后,您可以使用document.getElementById()ractive.find()此处的文档 )来获取所需的元素。

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' },
});

演示: http//jsfiddle.net/Lgpe2h5L/1/

编辑:完整运行示例: 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);
        });
    }
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM