OpenDataV 打算采纳子库的形式增加子组件,即每一个组件都当做一个子库,子库有本人的依赖,而我的项目自身的依赖只针对框架,因而每一个组件咱们都当做一个子库来开发。上面我带着大家一步步具体的开发一个数字展现组件。
创立组件目录和文件
- 进入组件库目录下
所有的可拖拽组件都寄存在 src/resource/components
目录下
cd src/resource/components
- 依据组件名称创立目录
默认组件目录是以组件的名称命名,当然也能够依据本人的要求命名,组件能够放在 components
目录下,也能够放在其子目录的目录下。
mkdir DigitalText
- 创立组件所需的固定文件
每个组件必须的文件有 vue 文件xxx.vue
、配置文件config.ts
、导出文件index.ts
,每个文件有本人的用途,vue 文件不用说了是组件渲染的主体,导出文件名称固定为index.ts
,次要是导出组件的信息给内部援用,配置文件次要是在编辑页面右侧展现的配置项,这个咱们前面再详述。所以这里咱们须要创立三个文件:DigitalText.vue、config.ts、index.ts
以上咱们就创立好了组件所需的文件,上面就须要做组件的初始化了
初始化组件文件
因为咱们的组件都是以子库的形式引入,所以须要进行包的初始化,执行以下命令
cd src/resource/components/Text/DigitalText
npm init
这里应用 npm
初始化包会让咱们抉择填写局部数据。
上面咱们先初始化一下组件文件DigitalText.vue
,先初始化最简略的组件数据
<template>
<div> 数字展现 </div>
</template>
<script lang="ts" setup></script>
<style lang="less" scoped></style>
而后咱们要初始化组件的配置文件config.ts
import {ComponentGroup, FormType} from '@/enum'
import type {PropsType} from '@/types/component'
import {BaseComponent} from '@/resource/models'
export const componentName = 'Digital'
class DigitalComponent extends BaseComponent {constructor(id?: string, name?: string, icon?: string) {
super({
component: componentName,
group: ComponentGroup.TEXT,
name: name ? name : '数字文本',
id,
width: 100,
height: 30,
icon
})
}
}
export default DigitalComponent
这里要阐明的点:componentName
是组件在我的项目中的注册名称,因而必须保障惟一,group
是给组件分组,这里的分组次要是展现在组件拖拽页面,其类型的 ComponentGroup
是固定好的,能够本人减少,展现地位如下:
name
是组件在拖拽页面上显示的名称,width
和 height
是组件拖拽到画布上显示的初始大小
配置完组件后数据后,就能够配置导出文件 index.ts
了,次要是导出组件名、组件对象和配置项。
import DigitalTextComponent, {componentName} from './config'
export default {
componentName,
component: () => import('./DigitalText.vue'),
config: DigitalTextComponent
}
初始化到这一步,咱们的组件曾经能够在编辑页面失常应用了,看一下成果:
在左边的编辑页面咱们看到有 款式
和属性
,所有的组件都蕴含根底款式 地位大小
,包含组件的上下边距和宽高,属性蕴含公共属性,其中 组件
和组件 ID
无奈批改,次要是展现来看的,名称
能够批改,名称属性次要是展现在图层上,批改名称后图层上会响应的显示批改后的名称。
这是最根底的组件,只能展现固定数据,不能进行任何配置,上面咱们要做组件的配置项。
组件配置项
款式配置
作为文字显示组件,最根底的字体相干属性配置应该要有,比方 字体、字体色彩、字体大小、字体宽度
,配置项仍然是在配置文件中增加,继承自根底组件类的公有属性_style
class DigitalTextComponent extends BaseComponent {constructor(id?: string, name?: string, icon?: string) {......}
_style: PropsType[] = [
{
label: '字体设置',
prop: 'font',
children: [
{
prop: 'color',
label: '色彩',
type: FormType.COLOR,
componentOptions: {defaultValue: 'skyblue'}
},
{
prop: 'fontSize',
label: '字体大小',
type: FormType.NUMBER,
componentOptions: {defaultValue: 20}
},
{
prop: 'fontWeight',
label: '字体宽度',
type: FormType.FONT_WEIGHT,
componentOptions: {defaultValue: 200}
},
{
prop: 'fontFamily',
label: '字体',
type: FormType.FONT_STYLE,
componentOptions: {defaultValue: 'Arial'}
}
]
}
]
}
款式配置的格局曾经定义好了,其中须要留神的是所有 children
下的子项中 prop
必须是 html
元素的 css
属性,具体的 css
属性名称并不是咱们在 style
文件中填写的,而是在 js
中对应的名称,这个能够在网上搜寻:css3 中文手册
,相似如下:
咱们再详述一下各配置项的意义:
- label:配置显示的分组名
- prop:惟一的属性辨别,此属性要与同级别中的其余配置不同
-
children:此属性组上面的配置项
- label:每个属性的名称
- prop:
css
属性值 - type:属性编辑时显示的组件类型,目前可显示的组件是固定的,类型都定义在
FormType
中 - componentOptions:属性对应的配置项,不同类型的组件有不同的配置项,具体能够在
src/types/component.d.ts
中查看定义,所有配置都有defaultValue
配置,作为属性初始化时的默认值
配置完款式后,咱们在编辑页面看一下成果:
搞清楚了款式的配置,上面咱们再说说属性的配置,属性配置与款式配置格局统一,有一些小细节须要留神。
属性配置
属性配置是继承公有变量_prop
,配置格局与款式雷同,咱们这里配置一个示例属性:
class DigitalTextComponent extends BaseComponent {constructor(id?: string, name?: string, icon?: string) {......}
_prop: PropsType[] = [
{
label: '数据配置',
prop: 'dataconfig',
children: [
{
prop: 'data',
label: '数据',
type: FormType.NUMBER,
componentOptions: {
defaultValue: 100000,
max: 99999999,
min: 0
}
}
]
}
]
}
格局这里就不解释了,这里咱们用到了数值类型,因而能够配置最大最小值。
接下来就是要在 vue
文件中应用属性配置了,属性不像款式,款式是 html
元素自身就反对的,因而只有咱们配置好,就能够失效了,然而属性是组件专有的,什么属性要产生什么成果全凭咱们本人书写逻辑,因而配置好属性咱们只会在编辑页面看到属性展现和配置,然而理论配置后是没有任何成果的,具体成果咱们在 vue
中实现。
属性应用
首先咱们要增加一个类型定义文件,因为 ts
最根底的劣势就是类型提醒,而咱们封装的组件基类是通用的,因而须要在每个组件中应用本人的属性类型定义,定义如下:
// DigitalText/type.ts
export interface DigitalType {
dataconfig: {data: number}
}
为了精确的进行提醒,类型定义必须和属性配置始终,具体来讲就是 children
上面的 prop
作为属性值,children
里面的 prop
作为属性键,能够比照一下 type.ts
中的配置和 _prop
的配置。
组件的配置信息是通过内部传入的,所以所有组件都必须接管内部数据,咱们曾经定义好了固定的格局
const props = defineProps<{component: DigitalTextComponent}>()
组件相干的所有信息都将通过 component
传入进来,为了监听属性变动和类型提醒,咱们封装了一个 hook,缩小每个组件中通用的解决,useProp
的应用如下:
const propChange = (prop: string, key: string, value: number) => {console.log(prop, key, value)
}
const {propValue} = useProp<DigitalType>(props.component, propChange)
useProp
接管三个参数,一个是 component
,次要是为了增加类型提醒,所以这里也传入了一个泛型定义,就是咱们在type.ts
中定义的类型,另外两个参数是属性变动回调函数和款式变动回调函数。个别状况下咱们只须要解决属性变动回调,款式变动是主动失效的,所以基本上不必解决,如果有非凡需要才须要。属性变动回调函数中有三个参数,prop
对应的是属性配置中外层的 prop
值,key
对应的是属性配置中 children
中的 prop
值,而 value
就是属性变动的值。
最终咱们的属性处理结果如下:
<template>
<div>{{data}}</div>
</template>
<script lang="ts" setup>
import {ref} from 'vue'
import DigitalTextComponent from './config'
import {useProp} from '@/resource/hooks'
import {DigitalType} from './type'
const props = defineProps<{component: DigitalTextComponent}>()
const propChange = (prop: string, key: string, value: number) => {if (prop === 'dataconfig' && key === 'data') {data.value = value}
}
const {propValue} = useProp<DigitalType>(props.component, propChange)
const data = ref<number>(propValue.dataconfig.data)
</script>
<style lang="less" scoped></style>
看一下页面上的成果:
下面咱们用了属性回调去解决值变动响应,实际上还有其余的形式能够解决,咱们要明确属性回调的基本需要是什么?次要就是为了编辑了对应的属性后,咱们在组件内能监测到变动反馈到显示上。雷同这一点,可用的办法就多了。
- 间接应用
props
传递的属性值在template
中渲染数据
<template>
<div>{{propValue.dataconfig.data}}</div>
</template>
<script lang="ts" setup>
import DigitalTextComponent from './config'
import {useProp} from '@/resource/hooks'
import {DigitalType} from './type'
const props = defineProps<{component: DigitalTextComponent}>()
const {propValue} = useProp<DigitalType>(props.component)
因为 vue
响应式的起因,props
中的数据是能够响应变动的,那么咱们间接在 template
中应用即可,不须要做任何监测。
- 应用
computed
或者watch
监听属性变动
这里和下面是一样的情理,vue
会主动帮咱们解决响应式数据,只有用 vue
的计算属性或者 watch
也能够监听到属性变动。
<template>
<div>{{data}}</div>
</template>
<script lang="ts" setup>
import {computed} from 'vue'
import DigitalTextComponent from './config'
import {useProp} from '@/resource/hooks'
import {DigitalType} from './type'
const props = defineProps<{component: DigitalTextComponent}>()
const {propValue} = useProp<DigitalType>(props.component)
const data = computed<number>(() => {return propValue.dataconfig.data})
</script>
<style lang="less" scoped></style>
- 属性变动回调的另一种用法
<template>
<div>{{data}}</div>
</template>
<script lang="ts" setup>
import {ref} from 'vue'
import DigitalTextComponent from './config'
import {useProp} from '@/resource/hooks'
import {DigitalType} from './type'
const props = defineProps<{component: DigitalTextComponent}>()
const propChange = () => {data.value = propValue.dataconfig.data}
const {propValue} = useProp<DigitalType>(props.component, propChange)
const data = ref<number>(propValue.dataconfig.data)
</script>
<style lang="less" scoped></style>
属性变动回调接管任何参数,咱们能够抉择接管参数,也能够不接管参数,在一些配置项比拟多的组件中,咱们不想在属性回调中去一个一个判断变动的属性,那么就能够应用这种形式,在这种形式中咱们只是把属性回调作为一个告诉,即告诉咱们属性发生变化了,而咱们不关怀哪一个属性产生了变动,把所有的属性都批改一遍即可,尽管听起来比拟麻烦,然而在一些简单组件中的确很有作用。在这里咱们要明确,只有属性产生了变动,那么 prop
中的数据也必然产生了变动,所以咱们随时取 prop
中的数据它都是最新的。
总结
到这里,一个组件的整个增加过程就讲完了,依据目前的开发进度来看,基本上所有的局部都讲到了,如果有人在应用过程中发现了什么问题或者有哪些地方不够分明的,能够在我的项目的 issue 中提,也能够通过其余形式反馈。
增加微信公众号理解更多信息: