乐趣区

关于vue.js:OpenDataV低代码平台新增组件流程

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是组件在拖拽页面上显示的名称,widthheight 是组件拖拽到画布上显示的初始大小

配置完组件后数据后,就能够配置导出文件 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 中提,也能够通过其余形式反馈。

增加微信公众号理解更多信息:

退出移动版