组件
定义生命周期处理程序方法
模式是解剖学,生命周期方法是生理学; 模式定义数据的形状,生命周期处理程序方法使用数据来修改实体。处理程序通常会与 Entity API 进行交互。
方法概述
方法 | 描述 |
---|---|
init |
初始化组件时调用一次。用于设置初始状态和实例化变量。 |
update |
在组件初始化时以及任何组件的任何属性更新时(例如,通过 setAttribute ) 调用。用于修改实体。 |
remove |
从组件中删除组件时(例如,通过 removeAttribute )或当实体与场景分离时调用。用于撤消对实体的所有先前修改。 |
tick |
在每个渲染循环或场景的刻度上调用。用于连续更改或检查。 |
play |
每当场景或实体播放时调用以添加任何背景或动态行为。初始化组件时也调用一次。用于启动或恢复行为。 |
pause |
每当场景或实体暂停以删除任何背景或动态行为时调用。从实体中删除组件或从场景中分离实体时也会调用。用于暂停行为。 |
updateSchema |
每当更新任何组件的属性时调用。可用于动态修改架构。 |
组件原型属性
在这些方法中,我们可以通过 this
访问组件原型:
属性 | 描述 |
---|---|
this.data |
根据模式默认值,mixins 和实体的属性计算解析的组件属性。 |
this.el |
将[entity] [entity]引用为 HTML 元素。 |
this.el.sceneEl |
将[scene] [scene]引用为 HTML 元素。 |
this.id |
如果组件可以具有[多个实例] [多个],则组件的单个实例的 ID(例如,来自 sound__foo 的 foo )。 |
方法
init
.init ()
在组件生命周期的开始时调用一次。实体可以调用组件的 init
处理程序:
- 在 HTML 文件中的实体上静态设置组件并加载页面时。
- 通过
setAttribute
在附加实体上设置组件时。 - 在未附加的实体上设置组件时,然后通过
appendChild
将实体附加到场景。
init
处理程序通常用于:
- 设置初始状态和变量
- 绑定方法
- 附加事件侦听器
例如,游标组件的 init
将设置状态变量,绑定方法和添加事件侦听器:
AFRAME.registerComponent('cursor', {
// ...
init: function () {
// Set up initial state and variables.
this.intersection = null;
// Bind methods.
this.onIntersection = AFRAME.utils.bind(this.onIntersection, this);
// Attach event listener.
this.el.addEventListener('raycaster-intersection', this.onIntersection);
}
// ...
});
.update(oldData)
每当组件的属性发生变化时,都会调用 .update (oldData)
,包括组件生命周期的开始。实体可以调用组件的 update
处理程序:
- 在调用
init ()
之后,在组件生命周期的开始。 - 使用
.setAttribute
更新组件的属性时。
update
处理程序通常用于:
- 使用
this.data
进行大部分修改实体的工作。 - 只要一个或多个组件属性发生更改,就修改实体。
对实体的细粒度修改可以通过在更新(oldData
)之前使用先前的数据集[diffing] [diff]当前数据集(this.data
)来完成。
A-Frame 在组件生命周期的开始和每次组件的数据发生变化时调用 .update()
(例如,由于 setAttribute
)。更新处理程序通常使用 this.data
来修改实体。更新处理程序可以通过其第一个参数访问组件数据的先前状态。我们可以使用组件的先前数据来确切地告知更改了哪些属性以进行粒度更新。
例如,可见组件的 update
设置实体的可见性。
AFRAME.registerComponent('visible', {
/**
* this.el is the entity element.
* this.el.object3D is the three.js object of the entity.
* this.data is the component's property or properties.
*/
update: function (oldData) {
this.el.object3D.visible = this.data;
}
// ...
});
remove
每当组件与实体分离时,都会调用 .remove ()
。实体可以调用组件的 remove
处理程序:
- 当组件通过
removeAttribute
从实体中移除时。 - 当实体与场景分离时(例如,
removeChild
)。
remove
处理程序通常用于:
- 删除,撤消或清除组件对实体的所有修改。
- 分离事件监听器。
例如,当移除[光分量] [光]时,光分量将移除它先前在实体上设置的光对象,从而将其从场景中移除。
AFRAME.registerComponent('light', {
// ...
remove: function () {
this.el.removeObject3D('light');
}
// ...
});
.tick(time,timeDelta)
在场景的渲染循环的每个刻度或帧上调用 .tick ()
。场景将调用组件的 tick
处理程序:
- 在渲染循环的每个帧上。
- 大约每秒 60 至 120 次。
- 如果实体或场景未暂停(例如,检查员已打开)。
- 如果实体仍附加到场景。
tick
处理程序通常用于:
- 在每个帧或间隔上连续修改实体。
- 轮询条件。
tick
处理程序以毫秒(time
)提供场景的全局正常运行时间,以及自上一帧(timeDelta
)以来以毫秒为单位的时间差。这些可用于插值或仅在设定的时间间隔内运行 tick
处理程序的部分。
例如,跟踪的控件组件将调整控制器的动画,更新控制器的位置和旋转,并检查按钮按下。
AFRAME.registerComponent('tracked-controls', {
// ...
tick: function (time, timeDelta) {
this.updateMeshAnimation();
this.updatePose();
this.updateButtons();
}
// ...
});
.pause()
当实体或场景暂停时调用 .pause ()
。实体可以调用组件的 pause
处理程序:
- 在删除组件之前,在调用
remove
处理程序之前。 - 当实体暂停时使用
Entity.pause ()
。 - 使用
Scene.pause ()
暂停场景时(例如,打开 Inspector)。
pause
处理程序通常用于:
- 删除事件侦听器。
- 消除任何动态行为的可能性。
例如,声音组件将暂停声音并删除会在事件上播放声音的事件侦听器:
AFRAME.registerComponent('sound', {
// ...
pause: function () {
this.pauseSound();
this.removeEventListener();
}
// ...
});
.play()
当实体或场景恢复时,调用 .play ()
。实体可以调用组件的 play
处理程序:
- 首次连接组件时,调用
update
处理程序后。 - 当实体暂停但随后用
Entity.play ()
恢复。 - 当场景暂停但随后用
Scene.play ()
重新开始。
play
处理程序通常用于:
- 添加事件侦听器。
例如,声音组件将播放声音并更新将在事件上播放声音的事件侦听器:
AFRAME.registerComponent('sound', {
// ...
play: function () {
if (this.data.autoplay) { this.playSound(); }
this.updateEventListener();
}
// ...
});
.updateSchema(data)
.updateSchema ()
(如果已定义)在每次更新时调用,以检查是否需要动态修改模式。
updateSchema
处理程序通常用于:
- 动态更新或扩展架构,通常取决于属性的值。
例如,几何组件检查 primitive
属性是否已更改,以确定是否更新不同类型几何的模式:
AFRAME.registerComponent('geometry', {
// ...
updateSchema: (newData) {
if (newData.primitive !== this.data.primitive) {
this.extendSchema(GEOMETRIES[newData.primitive].schema);
}
}
// ...
});
组件原型方法
.flushToDOM()
为了节省字符串化的 CPU 时间,A-Frame 只会在调试模式下更新实际 DOM 中组件的序列化表示。调用 flushToDOM()
将手动序列化组件的数据并更新 DOM:
document.querySelector('[geometry]').components.geometry.flushToDOM();