0.0.4 • Published 5 years ago

ccharts-test-buttton v0.0.4

Weekly downloads
-
License
MIT
Repository
-
Last release
5 years ago

组件(库) 之 ButtonDemo

前言

  最近菜鸟整个前端在推物料中心,发现上面的组件全部是StoryBook + react jsx 的写法, 想着推下 TS 的组件写法, 就整理了这篇 组件开发文章 StoryBook + Typescript + Tslint(tslint-config-ali) 。

图说

003.png

简介

StoryBook

StoryBook : 在你的应用程序之外运行。这允许您单独开发UI组件,这可以提高组件重用,可测试性和开发速度。您可以快速构建,而无需担心特定于应用程序的依赖项。

TS

TypeScript: 老生常谈, js 超级, 拥有可选的强类型定义, 类型可以让你方便快捷的进行类型检查、定义软件组件之间的接口和洞察现有JavaScript库的属性和方法, 在集团不包含蚂蚁金服的已有 990 个 TS 库; 

TSLint (tslint-config-ali) 

TSLint:  是一种可扩展的静态分析工具,可检查TypeScript代码的可读性,可维护性和功能性错误。它在现代编辑器和构建系统中得到广泛支持,可以使用您自己的lint规则,配置和格式化程序进行自定义。

tslint-config-ali: 是集团 TS 规约配套 TSLint 规则和扩展包, 已经融入到喜码中,会作为检测、修复工具辅助集团内部的 TS 开发。

方法步骤

一、初始化Story 

1. 初始化项目 test-comp

mkdir test-comp
cd test-comp
yarn init -y
yarn add -D @storybook/react @storybook/addon-info @storybook/addon-knobs storybook-addon-jsx @types/react babel-core typescript awesome-typescript-loader react-docgen-typescript-webpack-plugin jest "@types/jest" ts-jest 
yarn add react react-dom
mkdir .storybook src
touch .storybook/config.js .storybook/addons.js .storybook/welcomeStory.js utils.js

2. 在 package.json 中增加 启动 story 脚本

{
  "scripts": {
    "storybook": "start-storybook -p 6001 -c .storybook"
  }
}

3. 配置 storybook/config.js 

import { configure } from '@storybook/react';
import { setAddon, addDecorator } from '@storybook/react';
import JSXAddon from 'storybook-addon-jsx';
import { withKnobs, select } from '@storybook/addon-knobs/react';
addDecorator(withKnobs);
setAddon(JSXAddon);

// automatically import all files ending in *.stories.js
const req = require.context('../src', true, /.stories.js$/);
function loadStories() {
  require('./welcomeStory');
  req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);

4. 配置 .storybook/addons.js

addons 说明

import '@storybook/addon-knobs/register';
import 'storybook-addon-jsx/register';

5. 写 Style 工具类  utils.js

import { withInfo } from '@storybook/addon-info';
const wInfoStyle = {
  header: {
    h1: {
      marginRight: '20px',
      fontSize: '25px',
      display: 'inline'
    },
    body: {
      paddingTop: 0,
      paddingBottom: 0
    },
    h2: {
      display: 'inline',
      color: '#999'
    }
  },
  infoBody: {
    backgroundColor: '#eee',
    padding: '0px 5px',
    lineHeight: '2'
  }
};
export const wInfo = text =>
  withInfo({ inline: true, source: false, styles: wInfoStyle, text: text });

6. 写Story 欢迎页 .storybook·/welcomeStory.js

import React from 'react';
import { storiesOf } from '@storybook/react';
import { wInfo } from '../utils';
storiesOf('Welcome', module).addWithJSX(
  'to your new Storybook🎊',
  wInfo(`
    ### Notes
    Hello world!:
    ### Usage
    ~~~js
    <div>This is an example component</div>
    ~~~
    ### To use this Storybook
    Explore the panels on the left.
  `)(() => <div>This is an example component</div>)
);

7. 试运行 Story : npm run storybook

image.png

二、引入TypeScript 

1. 创建 ts 组件空文件

mkdir src/Button
touch src/Button/Button.tsx src/Button/Button.css src/Button/Button.stories.js

2. 写 ts 组件内容: src/Button/Button.tsx

import * as React from 'react';
import './Button.scss';
export interface Props {
  /** this dictates what the button will say  */
  label: string;
  /** this dictates what the button will do  */
  onClick: () => void;
  /**
   * Disables onclick
   *
   * @default false
   **/
  disabled?: boolean;
  testA?: boolean;
}
const noop = () => {}; // tslint:disable-line
const Button = (props: Props) => {
  const { label, onClick, disabled = false } = props;
  const disabledclass = disabled ? 'Button_disabled' : '';
  return (
    <div
      className={`Button ${disabledclass}`}
      onClick={!disabled ? onClick : noop}
    >
      <span>{label}</span>
    </div>
  );
};
export { Button };

3. 写 scss 组件样式:  src/Button/Button.scss

.Button span {
  margin: auto;
  font-size: 16px;
  font-weight: bold;
  text-align: center;
  color: #fff;
  text-transform: uppercase;
}
.Button {
  padding: 0px 20px;
  height: 49px;
  border-radius: 2px;
  border: 2px solid var(--ui-bkgd, #3d5567);
  display: inline-flex;
  background-color: var(--ui-bkgd, #3d5567);
}
.Button:hover:not(.Button_disabled) {
  cursor: pointer;
}
.Button_disabled {
  --ui-bkgd: rgba(61, 85, 103, 0.3);
}

4. 组件接入 story 文档: src/Button/Button.stories.js

import React from 'react';
import { storiesOf } from '@storybook/react';
import { Button } from './Button';
import { wInfo } from '../../utils';
import { text, boolean } from '@storybook/addon-knobs/react';
storiesOf('Components/Button', module).addWithJSX(
  'basic Button',
  wInfo(`
  ### Notes
  This is a button
  ### Usage
  ~~~js
  <Button
    label={'Enroll'}
    disabled={false}
    onClick={() => alert('hello there')}
  />
  ~~~`
)(() => (
    <Button
      label={text('label', 'Enroll')}
      disabled={boolean('disabled', false)}
      onClick={() => alert('hello there')}
    />
  ))
);

5. 让strorybook 接入typescript, 创建相关配置文件

touch .storybook/webpack.config.js tsconfig.json

6. 配置 storybook 的 webpack 配置文件:   storybook/webpack.config.js

const path = require('path');
const TSDocgenPlugin = require('react-docgen-typescript-webpack-plugin');
module.exports = (baseConfig, env, defaultConfig) => {
  const rules = defaultConfig.module.rules;
  rules.push({
    test: /\.tsx?$/,
    use: [
      {
        loader: 'babel-loader',
      },
      {
        loader: 'ts-loader',
        options: {
          transpileOnly: true, // IMPORTANT! use transpileOnly mode to speed-up compilation
        },
      },
    ],
    exclude: /node_modules/,
  });

  rules.push({
    test: /\.scss$/,
    include: [path.resolve(__dirname, '../src')],
    use: ['style-loader', 'css-loader', 'sass-loader'],
  });

  defaultConfig.plugins.push(new TSDocgenPlugin());
  defaultConfig.resolve.extensions.push('.ts', '.tsx');
  return defaultConfig;
};

7. 配置tsconfig 文件:  tsconfig.json

{
  "compilerOptions": {
    "outDir": "build/lib",
    "module": "commonjs",
    "target": "es5",
    "lib": ["es5", "es6", "es7", "es2017", "dom"],
    "sourceMap": true,
    "allowJs": false,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "baseUrl": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "declaration": true,
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "build", "scripts"]
}

8. 试运行 Story : npm run storybook

image.png

三、引入 TSLint

1. 引入 tslint 依赖并添加 lint 配置空文件

yarn add tslint @ali/tslint-config-ali
touch tslint.json

2. 配置 tslint 规则:   tslint.json

{
  "extends": ["@ali/tslint-config-ali"],
  "rules": {
    "no-namespace": false,
    "whitespace": false,
    "no-boolean-literal-compare": false,
    "no-unsafe-any": false,
    "no-implicit-dependencies": false,
    "semicolon": false,
    "no-eval": false,
    "trailing-comma": false,
    "no-use-before-declare": false,
    "variable-name": [
      false,
      "allow-trailing-underscore",
      "allow-leading-underscore"
    ],
    "no-unused-variable": false,
    "ali-method-length": {
      "options": { "limit": 100 },
      "severity": "warning"
    }
  }
}

3. 重启 VScode IDE, 测试 TSLint 是否生效 (其他 IDE 工具没有测试)

如图: 有 tslint 错误提示 则为生效

image.png

四、build & 暴露组件

1. 添加 copy 依赖库, 增加 index 文件

yarn add -D cpx
touch src/index.tsx
echo "node_modules" >> .gitignore
echo "build" >> .gitignore
git init # version control is good for you

2. 添加 main、types 指引 和 build 脚本

{
  "main": "build/lib/index.js",
  "types": "build/lib/index.d.ts",
  "files": [
    "build/lib"
  ],
  "scripts": {
    "storybook": "start-storybook -p 6001 -c .storybook",
    "build": "npm run build-lib && build-storybook",
    "build-lib": "tsc && npm run copy-css-to-lib",
    "build-storybook": "build-storybook",
    "copy-css-to-lib": "cpx \"./src/**/*.css\" ./build/lib"
  },
}

3. 添加要暴露的组件到 index 文件 : src/index.tsx

import { Button } from './Button/Button';
export { Button };

4. npm run build 测试编译文件

image.png

小结

       组件的开发方式有很多, 结合 Typescript 和 TSLint 会让我们的开发更紧跟时代潮流, 让我们的组件更具有明确的类型的属性和方法、让我们组件的使用者更快捷方便的使用;一起努力吧, 为更高效的开发;