ccharts-test-buttton
v0.0.4
Published
# 前言 最近菜鸟整个前端在推物料中心,发现上面的组件全部是StoryBook + react jsx 的写法, 想着推下 TS 的组件写法, 就整理了这篇 组件开发文章 StoryBook + Typescript + Tslint(tslint-config-ali) 。
Downloads
6
Readme
组件(库) 之 ButtonDemo
前言
最近菜鸟整个前端在推物料中心,发现上面的组件全部是StoryBook + react jsx 的写法, 想着推下 TS 的组件写法, 就整理了这篇 组件开发文章 StoryBook + Typescript + Tslint(tslint-config-ali) 。
图说
简介
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
二、引入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
三、引入 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 错误提示 则为生效
四、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 测试编译文件
小结
组件的开发方式有很多, 结合 Typescript 和 TSLint 会让我们的开发更紧跟时代潮流, 让我们的组件更具有明确的类型的属性和方法、让我们组件的使用者更快捷方便的使用;一起努力吧, 为更高效的开发;