事件响应式机制
事件派发机制
EventDispatcher 类是可调度事件的所有类的基类
常用方法
dispatch()
dispatch(
event, ...data):boolean
触发指定事件名称.
Parameters
| Parameter | Type | Description |
|---|---|---|
event |
string |
Event name |
...data |
any |
Data |
eventNames()
eventNames():
string[]
返回注册的所有事件名.
hasEvent()
hasEvent(
event):boolean
确定是否存在事件侦听
Parameters
| Parameter | Type | Description |
|---|---|---|
event |
string |
事件名 |
listenerCount()
listenerCount(
event):number
返回具有指定事件名称的侦听总数.
Parameters
| Parameter | Type | Description |
|---|---|---|
event |
string |
Event name |
off()
off(
event,fn?):EventDispatcher
移除监听.
Parameters
| Parameter | Type | Description |
|---|---|---|
event |
string |
Event name |
fn? |
Function |
Function, If is undefined, delete all corresponding event listeners. |
on()
on(
event,fn):EventDispatcher
增加监听
Parameters
| Parameter | Type | Description |
|---|---|---|
event |
string |
Event name |
fn |
Function |
Function |
once()
once(
event,fn):EventDispatcher
只监听一次.
Parameters
| Parameter | Type | Description |
|---|---|---|
event |
string |
Event name |
fn |
Function |
Function |
removeAllEventListeners()
removeAllEventListeners(
event?):void
通过事件名移除所有监听.
Parameters
| Parameter | Type | Description |
|---|---|---|
event? |
string |
Event name, delete all events if not passed |
信号机制
Signal 信号是一种事件总线。您可以使用add方法订阅事件,并使用dispatch方法进行调度。
信号与正常事件总线的不同之处在于,1个信号对应于1个事件类型。例如,在EventDispatcher中,您用 on 监听不同名称的事件,它允许您订阅任何类型的事件,比如把 onMouseClick 做为参数。使用Signal,您将获得一个对应于onMouseClick的信号,并仅为此事件调度此信号。
示例如下(onCameraUpdate 等少数事件同时走两条通道):
EventDispatcher写法:
app.on("onCameraUpdate", e => console.log("onCameraUpdate"));
Signal写法:
app.signal.onCameraUpdate.add(e => console.log("onCameraUpdate"));
⚠️ onXxx 事件名 vs DOM 事件名:onCameraUpdate/onMarker2D/onMarker3D/onPopup2D 等源码里 app.dispatch("onXxx") 与 app.signal.onXxx.dispatch(...) 各发一次,两种写法等价;但鼠标交互事件的派发类型名是 DOM 事件名——InteractionManager.sendEvent 里 app.dispatch("click", e) + app.signal.onMouseClick.dispatch(e) 同时发生。所以 app.on("click") 和 app.signal.onMouseClick.add(...) 都能收到点击;但 app.on("onMouseClick") 永远收不到(没有这个名字的事件被 dispatch)。
常用方法
add()
add(
h,context?): () =>boolean
增加一个信号处理回调函数
Parameters
| Parameter | Type | Description |
|---|---|---|
h |
any |
|
context? |
any |
addOne()
addOne(
h,context?): () =>boolean
增加一次信号处理回调函数,执行一次后会自动移除
Parameters
| Parameter | Type | Description |
|---|---|---|
h |
any |
|
context? |
any |
contains()
contains(
h):boolean
信号处理回调函数中是否包含这个函数
Parameters
| Parameter | Type | Description |
|---|---|---|
h |
any |
dispatch()
dispatch(...
args):void
派发事件,触发事件回调
Parameters
| Parameter | Type | Description |
|---|---|---|
...args |
any[] |
remove()
remove(
h,thisArg?):boolean
从监听的信号处理回调函数中移除
Parameters
| Parameter | Type | Description |
|---|---|---|
h |
any |
|
thisArg? |
any |
if supplied, will match handlers with a specific context only |
removeAll()
removeAll():
void
移除所有监听的信号处理回调函数
响应式机制
vjmap3d的响应式参考了vue3的响应式机制。具体可参考vue3的相关文档 响应式基础 深入响应式系统
相关示例用法
const { ref, reactive, shallowRef, shallowReactive, computed, watch, watchEffect, effectScope} = vjmap3d.reactivity;
const scope = effectScope()
let ob = reactive({d: 3})
watch(ob, (newValue, oldValue) => console.log("watch ob", newValue, oldValue), { immediate: true });
scope.run(() => {
let objValue = {a: 1}
let obj = ref(objValue);
let num = ref(3);
const c = computed(() => num.value + ob.d)
watch(obj, (newValue, oldValue) => console.log("watch", newValue, oldValue), { immediate: true });
const unwatchEffect = watchEffect((onCleanup) => console.log("watchEffect", obj.value));
//
const unwatch = watch([() => obj.value, ob], ([new1, new2], [old1, old2]) => {
console.log("watch m", new1, new2, old1, old2)
},{ immediate: true } )
//
obj.value = {a: 2}
//
let num2 = shallowRef(1);
watch(num2, (n, o, onCleanup)=>{console.log(n,o); onCleanup(()=>console.log("clear"))}, { immediate: true })
//
let sobj = shallowReactive({a: 2});
watch(sobj, (n, o, onCleanup)=>{console.log(n,o); onCleanup(()=>console.log("clear"))}, { immediate: true })
//
unwatchEffect();
unwatch();
obj.value = {b: 3}
console.log(c.value)
ob.d = 4
console.log(c.value)
});
ob.d = 5
scope.stop()
ob.d = 7
ob.d = 8
在 vjmap3d 当响应式对象数据发生变化时,可以用watch或watchEffect进行监听其状态变化。
比如监听一个实体是否处于辉光,示例如下:
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
camera: {
fov: 75,
near: 0.1,
far: 1000,
position: new THREE.Vector3(0, 0, 5)
}
})
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
let entity = vjmap3d.Entity.fromObject3d(cube); // 创建一个来源于object3d的对象
entity.addTo(app);// 把实体加进应用中
// 间隔三秒设置
setInterval(() => {
entity.bloom = !entity.bloom; // 设置实体辉光
}, 3000)
// 监听响应式对象变化
vjmap3d.reactivity.watch(entity.bloomRef, (v) => app.logInfo(v ? "设置了辉光" : "没有辉光", 1000))