IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Formily 如何开发一个自定义表单控件(上) -> 正文阅读

[JavaScript知识库]Formily 如何开发一个自定义表单控件(上)

背景

在我们使用formily开发的时候,不可避免会遇到定制组件的需求。
定制组件主要分为两种情况:

  • 该功能底层组件支持,需要属性映射
  • 该功能底层组件不支持,需要对底层组件进行定制开发

本篇文章介绍第一种情况,该功能底层组件支持,需要属性映射

Formily版本:V2

编码实战

schema中有一个自定义的属性withCount,input本身没有该属性,需要通过mapProps做映射处理

demo地址

demo-定开组件-属性映射

在这里插入图片描述

组件js

import React, { useMemo } from 'react';
import { createForm } from '@formily/core';
import { createSchemaField, FormProvider, connect, mapProps } from '@formily/react';
import { Form, Input, FormItem } from '@formily/antd';
import formData from './schema';

const { form: formprops, schema } = formData;

const CustomIput = connect(
  Input,
  mapProps((props: any, field) => {
    window.console.log('CustomIput-props', props);
    window.console.log('CustomIput-field', field);
    const { withCount } = props;
    return {
      ...props,
      showCount: withCount, // schema中有一个自定义的属性withCount,input本身没有该属性,需要通过mapProps做映射处理
    };
  }),
);

const SchemaField = createSchemaField({
  components: {
    Form,
    FormItem,
    Input,
    CustomIput,
  },
});

const FormRender = () => {
  const form = useMemo(() => createForm({ validateFirst: true }), []);

  return (
    <FormProvider form={form}>
      <Form {...formprops}>
        <SchemaField schema={schema} />
      </Form>
    </FormProvider>
  );
};

export default FormRender;

schema.js

const formData = {
  form: {
    labelCol: 6,
    wrapperCol: 12,
  },
  schema: {
    type: 'object',
    properties: {
      ke4g04rtzfe: {
        type: 'string',
        title: 'custom-Input',
        'x-decorator': 'FormItem',
        'x-component': 'CustomIput',
        'x-validator': [],
        'x-component-props': {
          placeholder: '占位提示',
          withCount: true,
          maxLength: 20,
        },
        'x-decorator-props': {},
        'x-designable-id': 'ke4g04rtzfe',
        'x-index': 0,
        description: '自定义的input组件',
      },
      l2w708hrhv6: {
        type: 'string',
        title: 'formily-Input',
        'x-decorator': 'FormItem',
        'x-component': 'Input',
        'x-validator': [],
        'x-component-props': {
          placeholder: '占位提示',
          withCount: true,
          maxLength: 20,
        },
        'x-decorator-props': {},
        'x-designable-id': 'l2w708hrhv6',
        'x-index': 1,
        description: 'formily封装的input组件',
      },
    },
    'x-designable-id': 'sjo6h5jy439',
  },
};

export default formData;

知识剖析

实现自定义组件,接入现成组件库的话,主要使用 connect/mapProps/mapReadPretty API

API源码

import React from 'react'
import { isFn, isStr, FormPath, each, isValid } from '@formily/shared'
import { isVoidField } from '@formily/core'
import { observer, Observer } from '@formily/reactive-react'
import { JSXComponent, IComponentMapper, IStateMapper } from '../types'
import { useField } from '../hooks'
import hoistNonReactStatics from 'hoist-non-react-statics'

export function mapProps<T extends JSXComponent>(
  ...args: IStateMapper<React.ComponentProps<T>>[]
) {
  return (target: T) => {
    return observer(
      (props: any) => {
        const field = useField()
        const results = args.reduce(
          (props, mapper) => {
            if (isFn(mapper)) {
              props = Object.assign(props, mapper(props, field))
            } else {
              each(mapper, (to, extract) => {
                const extractValue = FormPath.getIn(field, extract)
                const targetValue = isStr(to) ? to : (extract as any)
                const originalValue = FormPath.getIn(props, targetValue)
                if (extract === 'value') {
                  if (to !== extract) {
                    delete props.value
                  }
                }
                if (isValid(originalValue) && !isValid(extractValue)) return
                FormPath.setIn(props, targetValue, extractValue)
              })
            }
            return props
          },
          { ...props }
        )
        return React.createElement(target, results)
      },
      {
        forwardRef: true,
      }
    )
  }
}

export function mapReadPretty<T extends JSXComponent, C extends JSXComponent>(
  component: C,
  readPrettyProps?: React.ComponentProps<C>
) {
  return (target: T) => {
    return observer(
      (props) => {
        const field = useField()
        if (!isVoidField(field) && field?.pattern === 'readPretty') {
          return React.createElement(component, {
            ...readPrettyProps,
            ...props,
          })
        }
        return React.createElement(target, props)
      },
      {
        forwardRef: true,
      }
    )
  }
}

export function connect<T extends JSXComponent>(
  target: T,
  ...args: IComponentMapper<T>[]
) {
  const Target = args.reduce((target, mapper) => {
    return mapper(target)
  }, target)

  const Destination = React.forwardRef(
    (props: Partial<React.ComponentProps<T>>, ref) => {
      return React.createElement(Target, { ...props, ref })
    }
  )

  if (target) hoistNonReactStatics(Destination, target as any)

  return Destination
}

export { observer, Observer }

参考资料

formily2.0-实现自定义组件
formily/react API-connect

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-24 18:03:56  更:2022-05-24 18:05:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:12:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码