Skip to content

如何创建模块

在工作原理中我们简单提到模块src下三个文件的作用,现在我们以创建一个可点击跳转的按钮为例,创建模块。

创建模块包

仿照已有的image目录,创建一个目录,目录名为button(不带Lc前缀)

src/package.json

建议复制已有的包进行修改,这里在button前带上@lowcode512/lc-前缀。

json
{
  "name": "@lowcode512/lc-button",
  "version": "0.0.1",
  "main": "./dist/index.cjs",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "publishConfig": {
    "access": "public"
  },
  "files": [
    "dist"
  ],
  "scripts": {
    "build": "vite build"
  },
  "keywords": [
    "low-code",
    "typescript"
  ],
  "license": "MIT",
  "dependencies": {
  }
}

tsconfig.json

json
{
    "extends": "../../tsconfig.json",
    "include": [
        "../../env.d.ts",
        "./src/**/*",
    ],
}

vite.config.ts

需要修改name值。

typescript
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue';
import pkg from './package.json'

export default defineConfig({
    plugins: [vue()],
    build: {
        lib: {
            entry: './src/index.ts',
            name: 'LcButton',
            fileName: `${pkg.name.split('/')[1]}.${pkg.version}`,
            formats: ['umd'],
        },
        cssCodeSplit: true,
    }
})

设置.vue.ts.css

此处,便是你设置真正内容的地方了!

在vue设置布局,定义参数,如果是从其他模块复制过来,一定要注意各种改名,包括不限于class名、

index.vue
vue
<script setup lang="ts">
const props = defineProps<{
    title: string;
    color: string;
    size: number;
    borderRadius: number;
}>();
</script>

<template>
    <button
        :style="{
            fontSize: size + 'px',
            color: color,
            borderRadius: borderRadius + 'px',
        }"
        class="lc-button"
    >
        {{ title }}
    </button>
</template>
index.ts
typescript
import App from './index.vue'
import './index.css'

export default {
    render: App,
    editorProps: {
        title: {
            type: 'string', // 类型,并非值的类型,而是在渲染时决定显示什么类型的输入框(如选择器、滑块)
            defaultValue: '请输入文字' ,// 默认图的cdn
            display: '内容' // 在输入框上方显示的名称,无则不显示
        },
        color: {
            type: 'color',
            defaultValue: '#333',
            display: '颜色'
        },
        size: {
            type: 'number',
            defaultValue: 16,
            display: '字体大小'
        },
        borderRadius: {
            type: 'number',
            defaultValue: 2,
            display: '圆角'
        }
    }
};

(.css此处省略,根据实际编写、参照已有即可)

编译.umd.js

在包的根目录下:

pnpm run build

随后你可见dist下有*.umd.js后缀文件,lc指LowCode,跟随其模块名button,后面是版本号0.0.1和后缀

拖入编辑器的public文件夹

通过utils.tsloadScriptloadMaterial(在./src/store/project.ts下调用),*.umd.js将被加载为物料。

配置到编辑器

apps/editor/src/data下的materials.ts存储着EditorLeft物料栏里的信息。我们在image和title后追加一下信息,编辑器上将会出现该组件。

typescript
    {
        id: 3,
        type: "component",
        category: {
            name: "基础组件",
        },
        name: "LcButton",
        title: "按钮",
        thumbnail: "",
        version: "0.0.1",
        source: "/lc-button.0.0.1.umd.js",
        data: [
            {
                version: "0.0.1",
                source: "/lc-button.0.0.1.umd.js",
            },
        ],
    },

定义完成后,来到编译器,我们可以看到新的组件已经出现:

属性

根据你在defineProps().vue)和editorProps.ts)中所配置的项,编辑器画布(EditorContent)得到render渲染成组件,右侧得到editorProps显示相关的属性。

自定义事件

需要到与material.ts同级目录下的event.ts进行配置,这说明两者的作用是有联系的。event.ts下的editorEvents是一个示例事件,以及一个监听器globalEmitter

type: 'common'表示事件为通用时间,无论点击任何画布内的元素,都会有该栏事件(简单来说,这个字符串是给编辑器右侧决定是否渲染用的),events下是name事件名和args参数。

具体见EditorRight的“自定义事件”处(搜一下“自定义事件”定位)

为方便展示例子和节省时间,在上面的代码中,我们给index.vue加上:

vue
<script setup lang="ts">
const props = defineProps<{
    title: string;
    color: string;
    size: number;
    borderRadius: number;
    events?: Record<string, any[]>;
}>();
// 一个简单的打开链接事件
function onClick() {
    const link: string = props.events["common:link"][0];
    window.open(link, "_blank");
}
</script>

<template>
    <button
        :style="{
            fontSize: size + 'px',
            color: color,
            borderRadius: borderRadius + 'px',
        }"
        class="lc-button"
        @click="onClick"
    >
        {{ title }}
    </button>
</template>

一是给组件添加了点击事件,而是通过window跳转页面,如果打开了控制台,也许还能看到所传的参数,尝试找找它来自哪里吧。(观察image的.emit,想想是否在某处见过.on?)

题外话

谁有时间记得把这个防抖做一下