React进阶之路
我是ThinkTs作者兼Buzzard的作者,也是独立开发者,现在在自学c,c++,熟悉react,angular,vue,ts,js,es,golang,delphi。
使用typescript开发
React.FC的本质实际上就是FunctionComponent,如果我有一个css与tsx混合的组件,需要在外部引用,并且能推导类型那么可以这样使用FuctionComponent组装类型中间用&链接不同的类型
const Button= styled.button<ButtonTypes>`……这里写css样式`
const Btn:FunctionComponent<{disabled?: any; onClick?: any; style?: any;id:any }& ButtonTypes>= (v) => {
const [disabled, setDisabled] = useState(false);
useEffect(() => {
v.disabled!==undefined&&setDisabled(v.disabled)
}, [v.disabled])
return (
<Button disabled={disabled} {...v}
onClick={v.onClick?isPromise(v.onClick)?() => {
setDisabled(true);v.onClick().then(()=>{setDisabled(false);})
}:()=>{v.onClick()}:void 0}
>{v.children}</Button>
)
}
那么我在其他tsx组件调用的时候,会发现type类型被推导了,有自动提示
使用jest进行单元测试
使用identity-obj-proxy来规避css与less文件找不到的问题,使用正则表达式来规避@符号导致的路径问题,使用ts-jest来测试ts或者tsx,使用babel-jest来测试js或者jsx,使用jest-svg-transformer来规避svg找不到的问题
jest.config.js
module.exports = {
verbose: true,
collectCoverageFrom: [
"**/*.{ts,jsx,tsx}",
"!**/node_modules/**",
"!**/public/**",
"!**/views/**",
"!**/config/**",
"!**/*.d.ts",
"!**/scripts/**"
],
testRegex: './src/(.+)\\.test\\.(jsx?|tsx?)$',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
moduleNameMapper: {
".+\\.(css|less)$": "identity-obj-proxy",
"^@/(.*)$": "./$1"
},
transform: {
"^.+\\.tsx?$": "ts-jest",
"^.+\\.jsx?$": "babel-jest",
"^.+\\.svg$": "jest-svg-transformer"
}
};
App.test.tsx
import { render } from '@testing-library/react';
import App from './App';import React from 'react';
test('renders learn react link', () => {
render(<App />)
});
custom.d.ts来解决静态文件的import
并在tsconfig.json中include加入"./custom.d.ts"
declare module '*.bmp' {const src: string;export default src;}
declare module '*.gif' {const src: string;export default src;}
declare module '*.jpg' {const src: string;export default src;}
declare module '*.jpeg' {const src: string;export default src;}
declare module '*.png' {const src: string;export default src;}
declare module '*.webp' {const src: string;export default src;}
declare module '*.svg' {import * as React from 'react';
export const ReactComponent:React.FunctionComponent<React.SVGProps<SVGSVGElement>&{title?:string}>;
const src: string;export default src;}
declare module '*.css' {const classes: { readonly [key: string]: string };export default classes;}
declare module '*.less' {const classes: { readonly [key: string]: string };export default classes;}
@路径问题ts自动提示
在项目目录创建.vscode/settings.json
{
"emmet.includeLanguages": {
"javascript": "javascriptreact"
},"path-intellisense.mappings": {
"@": "${workspaceRoot}/src"
},"typescript.suggest.paths": true
}
在项目目录创建.babelrc
{
"presets": ["@babel/preset-typescript","@babel/preset-env"],
"plugins": ["@babel/plugin-transform-react-jsx"]
}
tsconfig.json
{
"compilerOptions": {
"jsx": "react",
"module": "commonjs",
"lib": ["dom", "esnext"],
"checkJs": true,
"allowJs": true,
"target": "es5",
"allowSyntheticDefaultImports": true,
"strict": false,
"noImplicitAny": false,
"baseUrl": "./",
"esModuleInterop": true ,
"moduleResolution": "Node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"paths": {
"@/*": ["src/*"]
},
"outDir": "./views"
},
"include": [
"./src/**/*","./custom.d.ts"
],
"exclude": ["node_modules","config","public","scripts"]
}
.eslintrc.js
module.exports = {
"parserOptions": {
"project": "./tsconfig.json"
},
"parser": "@babel/eslint-parser",
"plugins":["@babel"],
"rules": {
"new-cap": "warn",
"no-invalid-this": "off",
"no-unused-expressions": "off",
"no-unused-vars": "off",
"no-undef":"off",
"object-curly-spacing": "off",
"semi": "off",
}
};
兼容ie9及以上版本
需要在index.tsx文件中加入这些
import 'core-js/es'; import 'react-app-polyfill/ie9'; import 'react-app-polyfill/stable';
import 'core-js/stable'; import 'regenerator-runtime/runtime'; import 'raf/polyfill';
package.json
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all",
"ie > 8"
],
"development": [
"ie 11",
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},