之前介绍了widget的简单使用,本次来看一下widget在各种不同的场景下的使用。具体包括和marsui搭配使用、参数配置、动态传参、api、多个根组件场景的处理、widget间的动态交互等。
在学习具体业务场景的使用之前,要先明确一个概念,widget本身并不会负责ui方面的任何事情,总体来说,widget只做了三件事,1. 对ui部分和map部分进行解耦,关联生命周期。2. 对widget各种行为的封装,通过简单的配置和api,完成widget各种交互。 3. 支持对prop的配置和动态修改。当widget的这些特性结合到marsui中的pannel或者dialog使用时,就能够轻松的应对一些复杂场景。
- 搭配marsui使用
widget的入口是一个vue单文件组件,在这个组件的模板中我们可以写任何的html或者没有html,在gis的场景中经常需要一些操作面板,这些就可以在组件的模板中来编写这些代码,这个时候又免不了需要去封装一些组件,幸运的是mars-ui恰好解决了这个问题。在火星科技的vue项目中,mars-dialog 和 mars-pannel 通常都会搭配widget一起使用来实现这种操作面板的场景。下面是一个简单的示例
<template>
<!-- 这是一个宽 370px 位于左上角的固定面板 -->
<mars-pannel width="370" left="10" top="10">
<a-space>
<mars-button>按钮1</mars-button>
<mars-button>按钮2</mars-button>
<mars-button>按钮3</mars-button>
</a-space>
</mars-pannel>
</template>
<template>
<!-- 这是一个宽 370px 位于左上角的可移动可缩放的面板 -->
<mars-dialog width="370" left="10" top="10">
<a-space>
<mars-button>按钮1</mars-button>
<mars-button>按钮2</mars-button>
<mars-button>按钮3</mars-button>
</a-space>
</mars-dialog>
</template>
有一个细节,上面的示例并没有去传入visible参数,那么pannel或者dialog是如何显示的呢,这里就涉及到组件的属性继承。widget已经在外部传入了visible属性,因为两个示例都只存在一个根组件,所以就自动继承的visible属性。我们也可以手动的进行属性继承,后面会这对这种场景具体分析。
- 参数配置
WidgetState 接口定义了widget相关的配置参数,具体可参考上一篇文档,(下文中提到的defaultOption、 meta、data等概念也请参看上一篇文档)。这里主要来介绍一下在widget中对ui控件的一些配置。首先在defaultOption中可以为所有的widget配置prop,写法如下:
// widget-store.ts
// 这里配置的参数会被合并到所有组件的prop中,组件中的相同属性将会被覆盖
defaultOption: {
meta: {
props: {
top: 50,
bottom: 50,
left: 50
}
}
}
除了defaultOption 也可以在每一个widget配置中传入自己的个性化参数,写法如下:
// widget-store.ts
// 这里配置的参数会被合并到本组件的prop中,组件和defaultOption中的相同属性都将会被覆盖
{
component: markRaw(defineAsyncComponent(() => import("your-widget.vue"))),
name: "your-widget",
meta: {
props: {
top: 50,
bottom: 50,
left: 50
}
}
}
以上都是通过配置的方式来设置组件的prop值,widget还支持通过动态调用的方式,进行prop的设置:
import { useWidget } from "@mars/common/store/widget"
const { activate, disable, getWidget } = useWidget()
// 激活 your-widget
activate({
name: "your-widget",
data: {
// 为这个组件设置prop,此处属性的优先级,高于所有配置中的属性
props: {
top: 50,
bottom: 50,
left: 50
}
}
})
})
- API
上面的示例中用到了 activate 这个api,用来激活widget并传递data,他通过useWidget 函数导出,useWidget提供了多个api来操作widget。
export const useWidget: () => {
// 本页面widget配置数组
widgets: ComputedRef<Widget[]>
// 默认开启的widget
openAtStart: ComputedRef<string[]>
// 获取指定的widget
getWidget: (name: string) => Widget
// 出发对应widget的onUpdate
updateWidget: (name: string, ...args: any[]) => viod
// 获取widget的当前激活状态
isActivate: (name: string) => boolean
// 激活指定 widget模块
activate: (widget: string | Widget, reload = true) => void
// 释放指定的widget
disable: (name: string) => void
// 关闭释放所有widget ,hasAll传true值强制释放所有widget(默认autoDisable为false的widet不会释放)
disableAll: (hasAll?: boolean) => void
}
- 多个根组件的场景,假设一个widget的组件像下面这样。
此时会发现,这个widget激活之后无法在页面中显示,这是因为这里有两个根组件,此时vue无法自动继承prop,所以需要我们手动的来完成这个继承的操作,所以需要改成下面这样。 ```vue<template> <mars-pannel :width="305" left="15" top="170" bottom="40"> </mars-pannel> <mars-pannel :width="340" right="10" top="10" bottom="40"> </mars-pannel> </template>
这种方式就可以实现具有多个面板的widget,我们也可以根据自身的需求来确定让哪些面板来继承外部的props。甚至在只有一个面板时我们也可以对外部的props做一些自定义的处理。只需要再加上inheritAttrs: false 来禁用继承。 ```vue // 这里禁用了属性继承,并且将内联的prop优先级提升到最高。 <template> <mars-pannel v-bind="attrs" :width="305" left="15" top="170" bottom="40"> </mars-pannel> </template> <script setup lang="ts"> import { useAttrs } from "vue" const attrs = useAttrs() </script> <script lang="ts"> export default { inheritAttrs: false } </script>
- widget间的交互
一些复杂的场景中可能会需要两个widget之间有一些数据的传递,这里是通过updateWidget来实现的。
// widget1 <template> <mars-pannel width="370" left="10" top="10"> <mars-button @click="change">按钮1</mars-button> </mars-pannel> </template> <script setup lang="ts"> import { useWidget } from "@mars/common/store/widget" const { updateWidget } = useWidget() const change = () => { updateWidget("widget2", { /* 传递参数,这里的参数将会被处理成响应式数据,如果需要传递复杂对象,请使用markRaw */ }) } </script>
// widget2 <script setup lang="ts"> import { useWidget } from "@mars/common/store/widget" const { getWidget } = useWidget() const widget = getWidget("widget2") // 获取自身的widget widget.onUpdate((...args: any[]) => { // 监听 updateWidget 的调用 console.log(...args) }) </script>
over
~~~