从A帧中的其他组件访问动态创建的子项目

从A帧中的其他组件访问动态创建的子项目

问题描述:

我目前有2个组件。其中一个创建了一系列十二面体,另一个则隐藏了它们。它们都是在运行时生成的。从A帧中的其他组件访问动态创建的子项目

问题在于看不见的问题。在可见组件的init方法

el.querySelector('*') 

:我无法使用得到的动态生成的孩子。

我甚至试过:

  • 监听“装”事件,然后注册该组件。
  • 使用承诺并收听加载的事件。
  • 在组件注册后使用3秒的window.setTimeout()函数。

这是我完整的代码,到目前为止:

export class InvisibleComponent { 
    constructor() { 
    /** 
    * Sets the current element and all of its children as invisible 
    * by using its materials property. 
    * 
    */ 
    const _this = this; 
    AFRAME.registerComponent('invisible', { 
     init: function() { 
     _this.setTransparent(this.el); 
     console.log(this.el); 
     let children = this.el.querySelector('*'); 
     if (!children) return; 
     Array.from(children).forEach(child => { 
      _this.setTransparent(this.el); 
     }) 
     }, 
     remove: function() { 
     if (!this.el) return; 
     _this.setOpaque(this.el); 
     let children = this.el.querySelector('*'); 
     if (!children) return; 
     Array.from(children).forEach(child => { 
      _this.setOpaque(this.el); 
     }) 
     } 
    }) 
    } 
    setTransparent(el: AFrame.Entity) { 

    this.getMaterial(el).then((material :any) => { 
     this.setAttributes(el,material.opacity); 
    }) 
    .catch(resolve => { 
     console.log("Material couldn't be gathered. Using 100% of opacity instead", resolve); 
     this.setAttributes(el, 1); 
    }); 
    } 

    setAttributes(el : AFrame.Entity, opacity){ 
    el.setAttribute('data-previous-opacity',opacity); 
    el.setAttribute('material', 'opacity:0; transparent: true; visible:false;'); 
    } 

    /** 
    * This is a solution if the element which is trying to load 
    * hasn't been loaded yet. All elements must have a material 
    * in order to be inserted in a scene. 
    * @param el 
    */ 
    getMaterial(el: AFrame.Entity): Promise<number> { 
    return new Promise<number>((resolve, reject) => { 
     let material = el.getAttribute('material'); 
     if (material) resolve(material); 

     el.sceneEl.addEventListener('loaded', function() { 
     let material = el.getAttribute('material'); 
     !material ? reject(undefined) : resolve(material); 
     }) 


    }); 
    } 

    // If you had previous property, this will not remove them. 
    setOpaque(el: AFrame.Entity) { 
    let dataPreviousOpacity = el.getAttribute('data-previous-opacity'); 
    if (!dataPreviousOpacity) dataPreviousOpacity = 1; 
    el.setAttribute('material', 'transparent', dataPreviousOpacity === 1 ? false : true); 
    el.setAttribute('material', 'opacity', dataPreviousOpacity); 
    el.setAttribute('material', 'visible', true); 

    } 
} 
+1

组件不应该在运行时注册,而应该在页面加载。当你检测到所有的孩子被加载并且让其他组件监听那个事件时,附属于孩子的事件应该会有帮助,发出一个事件。或者setTimeouts也应该工作。将有助于将不可分割的组件设置为十二面体生成器作为依赖关系 – ngokevin

+0

@ngokevin:有道理。我也会检查这个方法。谢谢。一旦我完成解决我有另一个问题后会回发​​(完全不同的问题) –

出于某种原因,我不能让它与寻找实体儿童工作。
这里是我的方法:

  1. 揭露创建的元素:

    init:function(){ 
        //expose the object: 
        this.object = document.createElement('a-dode(..)') 
    } 
    
  2. 访问使用el.components.componentName.object

它可以是对象的公共数组对象,但是你喜欢。 访问undefined对象似乎没有问题。如果你有,你可以做一个间隔检查,如果对象是未定义的,或者循环访问一个数组,在每个'未定义'元素上执行'set invisible'。

工作小提琴here:component'create'制作一个方框,'change_color'设置颜色+位置。还有一个getObject()函数,稍后我会讨论它,因为我的方法存在严重的安全问题,并且可能需要适当的getter来获取对象。


我不知道什么是所提到的“安全问题”的正确方法,但我设法让一个“吸”,用 bind();传递对象,吸气:

init: function(){ 
    object = (...); 
    this.getObject = this.getObject.bind(this,[object]); 
}, 
getObject(){ 
    return arguments[0]; 
} 

如果这太可怕了,而且本来应该被处理,请让我知道。
也许我应该使用get getterName(){//getterBody},但它会引发一些错误。
更新提琴here

+0

有趣。感谢您的高举。这可以工作。让我想出一个方法来自动化这个过程,我会回来;) –

+0

@JoseA肯定,祝你好运:) –

+0

虽然我已经偏离了自己在做什么,但el.components存在问题。 componentName.object,因为componentName在我访问它的时刻似乎没有被定义。 –