唯杰地图 logo唯杰地图
VJMAP
EN

事件响应式机制

vjmap3d/references/core/event.md 7.5 KB303 行
原文

事件派发机制

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))