Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用Ractive.extend()时如何引用DOM元素?_Javascript_Dom_Ractivejs - Fatal编程技术网

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

Javascript 使用Ractive.extend()时如何引用DOM元素?,javascript,dom,ractivejs,Javascript,Dom,Ractivejs,所以,如果我使用Ractive.extend()来实例化自定义类的对象,那么如何引用该类中的DOM元素呢?显然,我不能像往常一样使用document.getElementById(),因为DOM尚未呈现,将Ractive.findComponent()传递给构造函数会返回“Ractive.findComponent不是函数”。我要做的是这样: class myClass { constructor(id /*,...*/) { this.element = documen

所以,如果我使用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}
});
埃塔:这也不行

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

更新了评论中澄清的问题的答案

这里有一个小问题:

{{{#每个精灵}
{{/每个}}
意味着Ractive将为
精灵中的每个项目创建
,并为其分配适当的ID。但是,
精灵在初始渲染时未定义,因此不会创建
元素

然后,在
onrender()
中创建类的实例,这些实例假定
元素已经存在。只有在这之后,您才能将实例添加到
精灵中,告诉Ractive渲染元素:

this.set({sprites});
有几种可能的解决办法。(我认为)最好是在类中添加
render()
方法,并将任何与DOM相关的内容移出构造函数。然后,您的代码将更改为以下内容:

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}
});
onrender(){
var sprites=this.get('repeaters').map(函数(repeater){
返回新画布(repeater.id);
});
this.set({sprites});
sprite.forEach(函数(sprite){
sprite.render();
});
}
但是,如果您不想修改您的类,您可以简单地为
{{each}
循环使用现有的
中继器
数组。此处演示:

关键是,在使用
document.getElementsById()
或类似方法之前,您需要一种方法告诉Ractive呈现
元素

原始答案

如果需要访问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' },
});

演示:

更新了评论中澄清的问题的答案

这里有一个小问题:

{{{#每个精灵}
{{/每个}}
意味着Ractive将为
精灵中的每个项目创建
,并为其分配适当的ID。但是,
精灵在初始渲染时未定义,因此不会创建
元素

然后,在
onrender()
中创建类的实例,这些实例假定
元素已经存在。只有在这之后,您才能将实例添加到
精灵中,告诉Ractive渲染元素:

this.set({sprites});
有几种可能的解决办法。(我认为)最好是在类中添加
render()
方法,并将任何与DOM相关的内容移出构造函数。然后,您的代码将更改为以下内容:

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}
});
onrender(){
var sprites=this.get('repeaters').map(函数(repeater){
返回新画布(repeater.id);
});
this.set({sprites});
sprite.forEach(函数(sprite){
sprite.render();
});
}
但是,如果您不想修改您的类,您可以简单地为
{{each}
循环使用现有的
中继器
数组。此处演示:

关键是,在使用
document.getElementsById()
或类似方法之前,您需要一种方法告诉Ractive呈现
元素

原始答案

如果需要访问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' },
});

演示:

编辑:完整的跑步示例可从以下网址获得:

我会将每个
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(或者如果repeater集合不会发生变化,则使用索引)。在这种情况下,我将重用组件的唯一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);
        });
    }
});

编辑:完整的跑步示例可从以下网址获得:

我会将每个
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(或者如果repeater集合不会发生变化,则使用索引)。在这种情况下,我将重用组件的唯一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);
        });
    }
});

那不行。如果我在类中调用document.getElementById(this.id),它将返回null。与document.querySelector(this.id)相同。我已经解释了从Ractive.findComponent()得到的错误。无论渲染后是否实例化对象,这两种情况都会发生。请检查
this.id
的值是否与元素的id匹配-它肯定会工作。至于
find()
-它是一个实例方法,因此请确保在您的ractive实例(
ractiveExtended
)上调用它,而不是全局ractive变量。是的,请确保:this.id与id匹配。不过,感谢您解释find()。但如果我必须打电话,我