本文介绍组件的主要文件开发和测试。

入口文件index开发

组件本身的代码开发,主要集中在src/index.tsx文件中。根据业务要求,对主要文件进行修改:

import * as React from "react";
import * as PropTypes from 'prop-types';
import classNames from 'classnames'
import BaseComponent from "@maliang/base-class-component";
import { createIntl, IntlShape } from "react-intl";

import styles from './index.scss';
// 此处必须import,否则无法触发specs.js到specs.json的实时编译
import "./specs/specs";

// 加载国际化语言包 如需使用此功能则在_locales_的语言包内设置相关定义
import zh from "./locales/zh-CN";
import en from "./locales/en-US";

export interface Props {
    defaultValue: string;
    placeholder: string;
    maxLength: number;
    percent: number;
    $width: number;
    theme: string; // 主题色
    locale: string; // 语言,国际化支持
}

export interface State {
    value: string;
    defaultValue: string;
}

interface Intl {
  [key: string]: string;
}

class Demo extends BaseComponent<Props, State, {}> {

    //如果没有传递该属性时的默认值
    static defaultProps = {
        theme: "theme-light",
        locale: "zh"
    };

    //如果传递该属性,该属性值的类型约束
    static propTypes = {
        $width: PropTypes.number
    };

 /* eslint-disable @typescript-eslint/no-explicit-any*/
    constructor(props: Props, context: any) {
        /* eslint-enable @typescript-eslint/no-explicit-any*/
        super(props, context);

        this.state = {
            value: "",
            defaultValue: ""
        };
    }

    static getDerivedStateFromProps(props: Props, state: State): Partial<State> | null {
        if (props.defaultValue !== state.defaultValue) {
            return {
                value: props.defaultValue,
                defaultValue: props.defaultValue
            };
        }

        return null;
    }

    componentDidMount(): void {
        console.log("componentDidMount");
    }

    componentWillUnmount(): void {
        console.log("componentWillUnmount");
    }

    handleChange(e: React.ChangeEvent<HTMLInputElement>): void {
        this.updateValue(e.target.value);
    }

    handleClick(): void {
        this.updateValue("");
    }

    updateValue(value: string): void {
        this.setState({ value });

        this.$emit('$change', { value });
    }

    // 预留国际化加载语言包能力
    getIntl(locale: string): IntlShape {
        const intl = createIntl({
            locale: locale,
            defaultLocale: locale,
            messages: locale == "en" ? en : zh
        });

        return intl
    }

    // 如果不需要国际化和主题设置,则删除ConfigContext.Consumer相关代码,直接写jsx
    render(): JSX.Element {
        const {placeholder, maxLength, $width, percent, theme, locale} = this.props;
        const style = {width: $width};
        const intl = this.getIntl(locale);

        return (
            <div className={classNames(styles.container, theme)} style={style}>
                <h2>Demo</h2>
                <p>{intl.messages.Tip}</p>
                <p>{intl.messages.CurrentTime}:{intl.formatTime(Date.now())}</p>
                {intl.messages.Percent}:{percent}
                <input className={styles.input} type="text" placeholder={placeholder} maxLength={maxLength}
                    value={this.state.value} onChange={(e): void => this.handleChange(e)}/>
                <button className={styles.button} onClick={(): void => this.handleClick()}>Reset</button>
            </div>
        );
    }
}

export default Demo;

属性文件specs开发

组件的能力描述,在src/specs/specs.js文件中。根据业务要求,对主要文件进行修改:

有关属性配置的定义说明,请参见定义属性

export default {
  "properties": [{
    "identifier": "$width",
    "defaultValue": 200,
    "options": {
      "min": 160
    }
  }, {
    "identifier": "$height",
    "defaultValue": 300,
    "options": {
      "min": 200
    }
  }, {
    "identifier": "placeholder",
    "text": "默认提示",
    "type": "text",
    "defaultValue": "请输入"
  }, {
    "identifier": "maxLength",
    "text": "字符数量限制",
    "type": "number",
    "options": {
      "min": 1,
      "defaultValue": 6
    },
    "defaultValue": 6
  }, {
    "identifier": "defaultValue",
    "text": "默认值",
    "type": "text",
    "defaultValue": "",
    "linkage": (nextProps, changedProps, currentProps) => {
      if (nextProps.defaultValue.length >= nextProps.maxLength) {
        return nextProps.defaultValue.substring(0, nextProps.maxLength);
      }
    }
  }, {
    "identifier": "period",
    "text": "状态",
    "type": "enum",
    "defaultValue": 1,
    "options": {
      "items": [{
        "label": "初始",
        "value": 1
      }, {
        "label": "运行中",
        "value": 2
      }, {
        "label": "停止",
        "value": 3
      }]
    }
  }, {
    "identifier": "percent",
    "text": "进度",
    "type": "number",
    "defaultValue": 0,
    "options": props => {
      const {
        period
      } = props;

      if (period === 2) {
        return {
          min: 0,
          max: 100
        };
      }

      return {
        min: 0,
        max: 0
      };
    },
    visible: props => {
      const {
        period
      } = props;

      if (period === 2) {
        return true;
      }

      return false;
    }
  }],
  "services": [{
    "identifier": "$getValue",
    "text": "取值",
    "effect": false
  }],
  "events": [{
    "identifier": "$change",
    "text": "值改变",
    "fields": [{
      "identifier": "value",
      "description": "当前值"
    }]
  }]
};

运行代码测试

执行以下命令 ,运行代码。

cd <项目名>

# 安装依赖
bnpm install
# 启动应用
bnpm start

您可在打开的浏览器中查看组件开发效果。