tinper-libraui

yonui mobile

Usage no npm install needed!

<script type="module">
  import tinperLibraui from 'https://cdn.skypack.dev/tinper-libraui';
</script>

README

yonui-mobile

yonui-mobile组件库,基于 antd-mobile,做了封装,用于适配到页面设计器。

贡献代码

本项目基于 Typescript 语言,主要内容为对Antd Mobile的一层封装,添加上相关的Manifest信息。

开发时请遵守项目中的eslint规范和commitlint规范,按要求格式化代码和提交信息。

如何开发组件

为什么选择Typescript?

开发组件的时候,需要按照约定写符合规范的Manifest定义。但是其结构比较复杂,容易写错。

用Typescript的话,可以引入定义好的Manifest类型定义 import { ComponentManifest, Component } from 'libraui-extension',基于它的提示和相应的报错,实现轻松编写Manifest的目的。

另外示例组件是用Typescript开发的,相关流程会比Javascript测试更多一些,质量相对更可靠一些。

我不熟悉/喜欢Typescript,是否可以用Javascript ?

可以,Typescript只是多一层类型定义检查,直接用JS编写符合规范的代码也是可以的。

代码组织结构

默认将所有组件平铺在 components 目录下。

每添加一个组件,就需要在components目录中创建一个子目录,名称和组件名称保持一致。同时在组件目录中创建相应的 index.tsx,以及配套的样式文件等。

最后,需要在顶层目录的 index.ts 中导出这个组件。

下面看下示例代码:

index.tsx

export { default as Button } from './components/button'

components/button/index.tsx

import React from 'react'
import { Button } from 'antd-mobile'
import { FieldTypes, EditTypes, ReactWrapper, ComponentManifest } from 'libraui-extension'
// todo 未配置 style activeStyle
const manifest: ComponentManifest = {
  name: 'Button', // 自定义组件名称
  label: '按钮', // 自定义组件文本
  // description: '',//描述
  props: [
    {
      name: 'name',
      type: FieldTypes.string,
      defaultValue: '按钮',
      showDesign: true,
      designConfig: {
        type: EditTypes.Icon,
        isRequired: true,
        props: {},
        label: '名称'
      }
    },
    {
      name: 'type',
      type: FieldTypes.string,
      defaultValue: 'primary',
      showDesign: true,
      designConfig: {
        type: EditTypes.Select,
        isRequired: true,
        props: {
          options: [
            { value: 'primary', text: '主按钮' },
            { value: 'ghost', text: '透明' },
            { value: 'warning', text: '警告红' }
          ]
        },
        label: '按钮类型'
      }
    },
    {
      name: 'size',
      type: FieldTypes.string,
      defaultValue: 'large',
      showDesign: true,
      designConfig: {
        type: EditTypes.Select,
        isRequired: true,
        props: {
          options: [
            { value: 'large', text: '大' },
            { value: 'small', text: '小' }
          ]
        },
        label: '按钮大小'
      }
    },
    {
      name: 'activeClassName',
      type: FieldTypes.string,
      defaultValue: '',
      showDesign: true,
      designConfig: {
        type: EditTypes.Text,
        isRequired: true,
        props: {},
        label: '点击反馈的自定义类名'
      }
    },
    {
      name: 'disabled',
      type: FieldTypes.boolean,
      defaultValue: false,
      showDesign: true,
      designConfig: {
        type: EditTypes.Bool,
        isRequired: true,
        props: {},
        label: '设置禁用'
      }
    },
    {
      name: 'inline',
      type: FieldTypes.boolean,
      defaultValue: false,
      showDesign: true,
      designConfig: {
        type: EditTypes.Bool,
        isRequired: true,
        props: {},
        label: '行内按钮'
      }
    },
    {
      name: 'loading',
      type: FieldTypes.boolean,
      defaultValue: false,
      showDesign: true,
      designConfig: {
        type: EditTypes.Bool,
        isRequired: true,
        props: {},
        label: '按钮载入状态'
      }
    },
    {
      name: 'icon',
      type: FieldTypes.string,
      defaultValue: '',
      showDesign: true,
      designConfig: {
        type: EditTypes.Icon,
        isRequired: true,
        props: {},
        label: '图标'
      }
    },
    {
      name: 'prefixCls',
      type: FieldTypes.string,
      defaultValue: 'am-button',
      showDesign: true,
      designConfig: {
        type: EditTypes.Text,
        isRequired: true,
        props: {},
        label: 'class前缀'
      }
    },
    {
      name: 'className',
      type: FieldTypes.string,
      defaultValue: '',
      showDesign: true,
      designConfig: {
        type: EditTypes.Text,
        isRequired: true,
        props: {},
        label: '样式类名'
      }
    }
  ],
  children: [],
  
}

export default ReactWrapper((props: any) => <Button {...props}>{props.name}</Button>, manifest)

// 如果不需要转换,直接封装即可
export default ReactWrapper(Button, manifest)

项目构建配置

现在的打包方式是基于webpack的方式。

打包时使用了一个工具 libraui-extension-packager,内部集成了 webpackbabel 以及其它各种 webpack plugin 和 loader。

暂时不支持传入自定义配置。

如果开发的时候用到了 Antd/AntdMobile/MaterialUI 等UI组件库,又想实现按需加载。就需要使用 babel-plugin-import 或 ts-import-plugin。目前在webpack中已经集成了ts-import-plugin,只需要在 tsconfig.json 中设置 module: 'esnext' 即可实现。

一些关键设计思想

注意事项

为了支持设计器中的拖拽功能,需要在组件中有 nid / uitype 这种 custom attribute,设计器会将相关信息通过 props 传给组件,需要组件将其映射到dom结构上。

目前默认的实现方式,是在组件的外面包一层div,在div上设置custom attribute。