# 元素
元素Element本身沒有邏輯,其主要負責(zé)兩部分——組件的聚合和屬性代理。所以在閱讀以下內(nèi)容之前,請保證先閱讀了組件的相關(guān)內(nèi)容。
元素有兩種使用方式,在xml中直接對應(yīng)于標(biāo)簽,也可以在腳本中動態(tài)創(chuàng)建,但注意動態(tài)創(chuàng)建的時候,必須作為Shadow元素的子孫結(jié)點?。?!
# 定制一個元素
讓我們從定制一個元素開始,理解它的功能:
import XrFrame from 'XrFrame';
const xrFrameSystem = wx.getXrFrameSystem();
// 指定默認掛載的組件
const AutoRotateTouchableGLTFDefaultComponents: XrFrame.IEntityComponents = Object.assign({
'mesh-shape': {},
'auto-rotate': {}
}, xrFrameSystem.GLTFDefaultComponents);
// 指定一個映射,將`xml`上特定的屬性,映射為組件的數(shù)據(jù)
const AutoRotateTouchableGLTFDataMapping: {[key: string]: string[];} = Object.assign({
speed: ['auto-rotate', 'speed']
}, xrFrameSystem.GLTFDataMapping);
// 定義元素類
class XRAutoRotateTouchableGLTF extends xrFrameSystem.Element {
// 指定默認組件集
public readonly defaultComponents: XrFrame.IEntityComponents = AutoRotateTouchableGLTFDefaultComponents;
// 指定默認數(shù)據(jù)映射
public readonly dataMapping: {[key: string]: string[];} = AutoRotateTouchableGLTFDataMapping;
}
// 注冊元素實現(xiàn)`XRAutoRotateTouchableGLTF`為名字`auto-rotate-touchable-gltf`
xrFrameSystem.registerElement('auto-rotate-touchable-gltf', XRAutoRotateTouchableGLTF);
在這個自定義元素中,我們首先指定了它初始化時就要掛載的組件,這其中有兩部分,第一部分是xrFrameSystem.GLTFDefaultComponents,這其實就是xr-gltf組件默認掛載的組件集合,之后在其上追加了mesh-shape和上一節(jié)定制的auto-rotate組件。
其次我們指定了映射,還是分為了兩部分,第一部分是xrFrameSystem.GLTFDataMapping,第二部分是追加的speed。來看看speed的值,數(shù)組第一個值為auto-rotate,就是掛載在這個元素上的組件名字,第二個值是speed,就是說要將寫在標(biāo)簽上的speed屬性直接映射到auto-rotate組件的數(shù)據(jù)speed上。
注意,所有的內(nèi)置組件的映射,都是會將如
isARCamera這樣的駝峰,映射為is-ar-camera這樣的小寫加中劃線分割的形式。 從這里我們可以看出,元素確實是用組合而非繼承的方式實現(xiàn)的功能。最后我們繼承自Element實現(xiàn)了元素,并用registerElement將其注冊到了框架中。
# 使用這個元素
和組件一樣,使用元素的方式同樣有兩種:
# 在wxml使用
首先是在wxml中使用,只需要按照注冊時的名字使用就好:
<xr-auto-rotate-touchable-gltf id="artg" position="-2 0 0" model="gltf-damageHelmet" speed="1 0 0" bind:drag-shape="handleDrag" bind:touch-shape="handleTouchStart" bind:untouch-shape="handleTouchEnd" />
可以看到,這里確實直接寫了speed屬性。
組件的屬性寫法和數(shù)據(jù)映射是可以共存的,同時數(shù)據(jù)映射并不先要求組件存在。
# 手動使用
我們也可以在運行時來代碼創(chuàng)建元素和添加到場景,但注意絕對不能將其添加到Shadow元素以外的元素?。?!
為了避免開發(fā)者失誤,創(chuàng)建和添加詳見Shadow元素。
const node = scene.createElement(xrFrameSystem.XRNode, {
position: '1 1 1'
});
node.setAttribute(position, '2 2 2');
這段代碼通過createElement方法創(chuàng)建了一個元素,注意第二個初始化參數(shù)傳入的是屬性,其完全對應(yīng)于標(biāo)簽上的名字,值也是字符串,接下來我們還通過setAttribute方法更新了其屬性。
但建議不要使用
setAttribute去更新屬性,而是先獲取組件,然后用組件中的setData方法來設(shè)置,省去字符串解析!
# 查找
有時候我們需要獲得元素的實例,來進一步進行其他操作,以下幾個方法可以幫助我們拿到它:
// 通過在`wxml`的元素上設(shè)置的`id`索引,比如上面例子中的`artg`,`id`是唯一的
scene.getElementById(id);
// 獲取元素的第`i`個子元素
el.getChildAtIndex(i);
// 通過一個`filter`函數(shù),獲取第一個子元素或者子元素集
el.getChildByFilter(filter);
el.getChildrenByFilter(filter);
// 通過類獲取子元素
el.getChildByClass(clz);
// 通過在`wxml`元素上設(shè)置的名字`name`獲取子元素,`name`可以不唯一
el.getChildName(name);
el.getChildrenName(name);
# 事件
每個元素上都有一個事件管理器,來管理其下掛載的所有組件的事件派發(fā),這個派發(fā)也可以觸達到wxml的事件綁定,詳見事件。