2017-07-31 49 views
0

我目前有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:有道理。我也會檢查這個方法。謝謝。一旦我完成解決我有另一個問題後會回發​​(完全不同的問題) –

回答

2

出於某種原因,我不能讓它與尋找實體兒童工作。
這裏是我的方法:

  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在我訪問它的時刻似乎沒有被定義。 –

相關問題