-
2022-02-23 17:09:44
/*
学习目标:组件封装总结
步骤:
1. 一般组件要支持style与className,👍方便组件自定义样式
2. 考虑联合字面量+字符串,提供代码提示
3. 复用React或第三方的类型,快速获得代码提示
4. 🔔自己写代码的技巧:TSX中封装组件,一般需要先定义props类型,后使用。类似vue中的props
组件封装要考虑的(三种)四种状态
*/更多相关内容 -
react ts
2022-03-26 12:18:55react ts 杂记react一些 记录
工作也有也有大半年了,一些知识点想着做些记录,顺便学学我这糟糕的MD 编辑器的使用
单向数据流:
什么叫单向数据流: 父 》 子 props 改变 引起子组件 重新render 子组件不能改变props 不能影响到父组件 及其依赖组件重新render,否则就乱套。
ReactElement 和 ReactNode
写ts 报错的时候 每次直接返回一个DOM 结构 或者 一个组件 不报错了 就完事,并未搞明白 区别。
interface ReactElement< P = any, T extends string | JSXElementConstructor<any> = | string | JSXElementConstructor<any> > { type: T props: P key: Key | null }
interface: 接口又是啥呢 简单说 就是一个约束
泛型:可以类型不固定 一个函数 要是直接写死 参数 string 那调用只能传stringfunction test(str:string):string{return str} //只能传 ,返回str 类型 function test2<T>(arg:T):T{return arg} //调用方决定类型 test2<number>(2) test2<string>('..') //也可以简写 test2(2) test2('..') 这样可以自动推导 也是可以的 function test3<T>(arg:T[]):T{return arg[0]} //规定泛型T 入参 数组类型 返回的泛型T中一个元素 //调用: test3<number>([3]) test3(['1']) test3([1]) //这样就规定了传入一个数字类型数组 必须返回数字类型 传字符数组 必须返回字符类型
type ReactText = string | number; type ReactChild = ReactElement | ReactText; interface ReactNodeArray extends Array<ReactNode> {} type ReactFragment = {} | ReactNodeArray; type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
看的出来ReactNode 范围是包括ReactElement 的 (还有一个JSXElement 继承 ReactElement 并且没有扩展)
所以 结论: ReactNode > RecatElement = 约等于 JSXElement你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
-
安装react ts 脚手架 + scss
2022-02-23 16:58:38react ts 脚手架安装+scss 1、安装react-ts脚手架 npm i -g creat-react-ts npx create-react-app (项目名) --template typescript npm start 2、安装scss npm node-sass sass-loader --save-dev -
react ts环境搭建及ts格式写法
2020-07-23 15:58:19npx create-react-app 项目名称 --template typescript 官方建议: If you've **previously installed create-react-app globally** via npm install -g create-react-app, we recommend you uninstall the...1、脚手架启动 npx create-react-app 项目名称 --template typescript 官方建议: If you've **previously installed create-react-app globally** via npm install -g create-react-app, we recommend you uninstall the package using **npm uninstall -g create-react-app** to ensure that npx always uses the latest version. **Global installs of create-react-app are no longer supported.** 不使用脚手架手动创建: react和react-dom都需要按照@types对应的声明文件,解析tsx语法使用ts-loader/awesome-typescript-loader/babel 2、创建.tsx文件 3、类型约束(类组件不写接口放到继承组件的泛型里会报错) (1)类组件 接收参数的组件需要接口声明并使用泛型 方式一:React.ComponentClass<props泛型,state泛型> 对应有状态组件 方式二:React.Component<P,S,SS> 泛型P:参数props,泛型S:状态state,泛型SS:updater和虚拟dom更新相关 方式三:React.ComponentType<P> P代表参数props,对应无状态组件 type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P>; 方式四:React.PureComponent<P,S,SS> PureComponent<P = {}, S = {}, SS = any> extends Component<P, S, SS> { } class App extends Component<P,S,SS>{ 泛型P:参数props,泛型S:状态state,泛型SS:updater和虚拟dom更新相关 状态: state:S={ ... } readonly state:Readonly<S>= { 该方法可避免this.state.x去改变状态,使用了Readonly映射类型,只对一级属性有用 ... } 构造函数中设置状态: constructor(props:P) { super(props); this.state = { ... } } } (2)函数组件 function(props:any或者定义接口约束) {...} 或 import React from 'react' import React,{FC,SFC} from 'react' interface P { count: number } const xx:React.FC<P> = props => { 其中: (1)React.SFC表示无状态函数,泛型P约束props (2)使用React提供的FC进行约束,会隐式在约束中提供一个children属性,可以之间props.children实现插槽 (3)使用xx.defaultProps为指定参数赋默认值是,FC约束的函数的接口中的指定属性必须是可选的,普通函数不用 import React from 'react' interface helo{ name: string, age?:number } const Hello: React.FC<helo> = (props) => { return (<h1>哈哈哈+{props.name}</h1>) } Hello.defaultProps = { age:12 } export default Hello; } const xx:FC<x> = props => { ... } (3)高阶函数(通过一个组件返回另一个组件) 1、使用React.ComponentType<P>约束传入的组件 泛型P约束props React.ComponentType:React.ComponentClass<P, any> | React.FunctionComponent<P>的联合类型 2、进行约束 因为传入的组件本身就是一个具有类型约束的组件,所以可以直接使用其泛型(在调用时自动推断参数类型)来进行高阶函数的约束 interface L{ loading:boolean } 泛型P使得传入高阶函数的参数约束和传入组件的参数一致 function Hello<P>(WrapComp:React.ComponentType<P>) { 组件类型:泛型P约束props,是React.ComponentClass<P, any> | React.FunctionComponent<P>的联合类型 return class extends Component<P & L>{ 通过交叉接口添加高阶函数本身的参数约束 render() { const { loading, ...props } = this.props; return ( loading ? <div>loading</div> : <WrapComp {...props as P}/> 因为不知道剩余参数的类型,使用断言排除报错 ) } } } export default Hello(Wrap); 使用该高阶组件的时候,传入的参数必须满足组件的泛型P代表的约束和交叉接口扩展的约束 (4)Hooks const [test, setTest] = useState<string | null>(null); useCallback<()=>void>(()=>{},[]) (4.5)event事件类型约束: clickHandle = (e:React.事件类型) => { React.FormEvent 表单事件,无法获取到value属性 泛型精确化: React.Formvent<HTMLInputElement> html的input事件,可以获取到value属性 React.MouseEvent 鼠标事件 React.KeyboardEvent 键盘事件 React.TouchEvent 手势事件 } (4.6)Promise类型 type c = Promise<string>; 接收一个参数,用来限制resolve传入参数的类型 let c:c=new Promise((resolve,reject)=>{resolve('s')}) (5)路由: cnpm install react-router-dom --save cnpm install @types/react-router-dom 其他写法一样 (6)Redxu: 1、安装 cnpm install -S redux react-redux @types/react-redux 不需要安装@types/redux,因为Redux已经自带了声明文件(.d.ts文件)。 2、创建types文件夹,其中的index.tsx文件放置reducer中state的接口格式 export interface IStoreState{ x:类型 } 3、创建action-type.tsx文件,放置action的type常量 (1)每个常量包括常量本身及其类型格式,方便在定义action接口时,定义type的类型 (2)当类型格式type名称和常量名称相同时,在导出时,会自动识别接口中的type和常量 export const INCREMENT='INCREMENT' export type INCREMENT=typeof INCREMENT 4、创建action.tsx文件 (1)每个action包括及接口格式和自身函数表达式 (2)还要导出使用联合类型声明的接口格式总和 1、方便在组件mapDispatchToPros中,约束dispatch参数格式, 2、方便约束reducer中action的参数格式 (3)引入定义的常量 (4)当常量文件中类型格式type名称和常量名称相同时,在导出时,会自动识别接口中的type和常量 import * as constants from '../constants/index' export interface IIncrement{ type:constants.INCREMENT } export interface IDecrement{ type:constants.DECREMENT } export type EnthusiamAction=IIncrement | IDecrement; export function increment():EnthusiamAction{ return { type:constants.INCREMENT } } export function decrement():EnthusiamAction{ return { type:constants.DECREMENT } } 5、定义reducer.tsx (1)引入types文件夹中定义的state接口约束,约束state (2)引入action文件中的对象联合约束类型,约束action (3)引入action-type中定义的常量,做switch的case import {EnthusiamAction} from '../actions' import { IStoreState } from '../types/index'; import {INCREMENT,DECREMENT} from '../constants/index' export function count(state:IStoreState={count:0},action:EnthusiamAction) { switch(action.type) { case INCREMENT: return { count:state.count+1 } default: return state } } 6、创建store.js文件,导出store (1)redux-devtools-extension的使用和之前一样 (2)导出store的方式和之前一样 7、在index.tsx中使用Provider包裹 使用方式和之前一样 8、在组件中使用 (1)从'react-redux'中引入connect (2)引入types文件夹中的对state的约束接口,约束mapStateToProps的state参数 (3)引入action.tsx文件中的接口联合类型约束,约束mapDispatchToProps的dispatch函数 mapDispatchToProps(dispatch:Dispatch<x>) Dispatch为type声明的函数格式,泛型约束参数 源码:type Dispatch<A> = (value: A) => void; (4)组件分别创建props接口和state接口,约束传入的状态和参数,放在继承类的泛型上进行约束 (5)注意在设置action的函数约束时,返回类型要设置成void,不能设置成返回对象 import React,{Component, Dispatch} from 'react' import * as actions from '../actions/index' import {IStoreState} from '../types' import {connect} from 'react-redux' interface IProps{ title:string, myclick:(data:string)=>void, count:number, increment:()=>void; decrement:()=>void; } interface IState{ count:number } class App extends Component<IProps,IState>{ ... } function mapStateToProps(state:IStoreState){ return{ count:state.count } } function mapDispatchToProps(dispatch:Dispatch<actions.EnthusiamAction>){ //Dispatch是个函数类型,泛型约定了参数 return{ increment:()=>dispatch(actions.increment()), decrement:()=>dispatch(actions.decrement()) } } 除了显示定义,还可以使用ReturnType type StateProps=ReturnType<typeof mapStateToProps> type DispatchProps=ReturnType<typeof mapDispatchToProps> 当涉及到路由时,可以这样定义props type Props=RouteComponentProps<any>&StateProps&DispatchProps&父组件传递的props 其中:当需要约束路由中参数时,如:this.props.match.params.id这种提示id,可以写成RouteComponentProps<{id:number}> 由如下类型可知,第一泛型参数的内容,会作为match中的提示 export interface RouteComponentProps< Params extends { [K in keyof Params]?: string } = {}, C extends StaticContext = StaticContext, S = H.LocationState > { history: H.History<S>; location: H.Location<S>; match: match<Params>; staticContext?: C | undefined; } 例:React.Component<Props,组件自身state> export default connect(mapStateToProps,mapDispatchToProps)(App) 4、文件拷贝 ts文件可通过tsconfig指定输出,但其他类型文件不能 方式一:通过shelljs库,将文件拷贝 shelljs.cp("R"," public' , "dist") 通过递归拷贝,将public文件夹拷贝的dist目录下
代码示例:
types下的index.tsx:export interface IStoreState{ count:number }
constants下的index.tsx:
export const INCREMENT='INCREMENT' export type INCREMENT=typeof INCREMENT export const DECREMENT='DECREMENT' export type DECREMENT=typeof DECREMENT
action下的index.tsx:
import * as constants from '../constants/index' export interface IIncrement{ type:constants.INCREMENT } export interface IDecrement{ type:constants.DECREMENT } export type EnthusiamAction=IIncrement | IDecrement; export function increment():EnthusiamAction{ return { type:constants.INCREMENT } } export function decrement():EnthusiamAction{ return { type:constants.DECREMENT } }
reducers下的index.tsx:
import {EnthusiamAction} from '../actions' import { IStoreState } from '../types/index'; import {INCREMENT,DECREMENT} from '../constants/index' export function count(state:IStoreState={count:0},action:EnthusiamAction) { switch(action.type) { case INCREMENT: return { count:state.count+1 } case DECREMENT: return{ count:state.count-1 } default: return state } }
store下的index.tsx:
import {createStore} from 'redux' import {count} from '../reducers/index' import {composeWithDevTools} from 'redux-devtools-extension' const store = createStore(count,composeWithDevTools()); export default store;
index.tsx:
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; import AppRouter from './router/appRouter' import {Provider} from 'react-redux' import store from './store/index' ReactDOM.render( <Provider store={store}> <React.Fragment> <AppRouter /> </React.Fragment> </Provider> , document.getElementById('root') ); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker.unregister();
路由文件:
import React,{Component} from 'react' import {HashRouter,Switch,Route} from 'react-router-dom' import App from '../App' class App2 extends Component{ render() { return( <div> <HashRouter> <Switch> <Route exact path='/' component={App}> </Route> </Switch> </HashRouter> </div> ) } } export default App2
App.tsx:
import React from 'react'; import logo from './logo.svg'; import './App.css'; import Hello from './components/hello' import List from './pages/list' function App() { function myclick(data:string) { console.log('父组件') console.log(data); } return ( <div className="App"> ts <Hello title='标题' myclick={myclick}></Hello> <List></List> </div> ); } export default App;
子组件Hello:
import React,{Component, Dispatch} from 'react' import { Button } from 'antd'; import * as actions from '../actions/index' import {IStoreState} from '../types' import {connect} from 'react-redux' interface IProps{ title:string, myclick:(data:string)=>void, count:number, increment:()=>void; decrement:()=>void; } interface IState{ count:number } class App extends Component<IProps,IState>{ constructor(props:IProps){ super(props); this.state={ count:2 } } // readonly state:Readonly<IState>= { // count: 1 // } componentDidMount() { // this.state.count=3; // this.setState({ // count:5 // }); } click() { this.setState({ count:7 }); } send() { console.log('111'); this.props.myclick('ahh'); } increment() { this.props.increment() } decrement() { this.props.decrement() } render() { return( <div> hello {this.props.title} {this.state.count} redux:{this.props.count} <Button onClick={this.click.bind(this)}>点击</Button> <Button onClick={this.send.bind(this)}>send</Button> <Button onClick={this.increment.bind(this)}>增加</Button> <Button onClick={this.decrement.bind(this)}>减少</Button> </div> ) } } function mapStateToProps(state:IStoreState){ return{ count:state.count } } function mapDispatchToProps(dispatch:Dispatch<actions.EnthusiamAction>){ //Dispatch是个函数类型,泛型约定了参数 return{ increment:()=>{dispatch(actions.increment());}, decrement:()=>dispatch(actions.decrement()) } } export default connect(mapStateToProps,mapDispatchToProps)(App) // import React,{useState} from 'react' // interface IProps{ // title:string // } // function App(props:IProps){ // return( // <div> // {props.title} // </div> // ) // } // export default App
子组件List:
import React,{Component} from 'react' import ListView from '../components/listView' interface IState { dataInfo:{ info:number[] } } class App extends Component<{},IState>{ constructor(props:any){ super(props); this.state={ dataInfo:{ info:[] } } } componentDidMount() { this.setState({ dataInfo:{ info:[1,2,3] } }) } render() { return( <div> { this.state.dataInfo.info.length>0? <div> <ul> { this.state.dataInfo.info.map((item,index)=>{ return <ListView key={index} content={item}></ListView> }) } </ul> </div>: <div>数据加载中</div> } </div> ) } } export default App
List子组件ListView:
import React,{Component} from 'react' interface IProps{ content:number } class App extends Component<IProps,any>{ render() { return( <div> {this.props.content} </div> ) } } export default App
高阶组件:
import React, { Component } from 'react'; import Wrap from './wrapComp' interface L{ loading:boolean } function Hello<P>(WrapComp:React.ComponentType<P>) { //组件类型:泛型P约束props,是React.ComponentClass<P, any> | React.FunctionComponent<P>的联合类型 return class extends Component<P & L>{ render() { const { loading, ...props } = this.props; return ( loading ? <div>loading</div> : <WrapComp {...props as P}/> ) } } } export default Hello(Wrap);
高阶组件传入的组件
import React from 'react'; interface helos{ name?: string, age?: number, add:string } const Hello: React.FC<helos> = (props) => { return (<h1>哈哈哈+wrap</h1>) } export default Hello;
高阶组件调用:
<HelloHigh add={'ww'} loading={false} ></HelloHigh>
-
React Ts 项目配置 Axios
2021-04-26 14:19:40React项目Ts版,使用Hooks API。本示例主要是配置Axios并使用Eggjs写了两个接口进行测试。 -
jinle-ui:react + ts封装UI组件库
2021-02-14 16:59:53第三方库 ...类名---使用js来动态判断是否为组件添加类 ... import React , { ButtonHTMLAttributes , AnchorHTMLAttributes } from 'react' ; // 加入 btn 默认属性 type NativeButtonProps = BaseButto -
7-react-admin-ts:用react-hooks实现的管理后台
2021-02-04 20:47:26ts + react-hooks + react-router-dom@5.2.0 + redux@^4.0.5 + react-redux + axios styled-components + echarts + antd redux-logger + redux-thunk 中间件 通过 create-react-app 脚手架构建 (二)主要功能 (1... -
umi基础框架(React+umi+Ts)
2021-08-05 11:10:50umi、dva、React -
前端 js 基于react ts的excel文件模板下载 文件导入、导出
2020-10-27 17:50:14基于react ts的excel文件模板下载 文件导入、导出 ####### 按钮 {pagePermission?.pageActionModels.find(item => item.name === 'OPP_DOWNLOAD_TEMPLATE') && <Button icon={<CopyOutlined />... -
react-antd-admin:react + ts + antd实现的管理系统模版
2021-03-11 18:34:27基于react + ts + antd建立的管理后台脚手架模版 线上地址 git地址 单独使用 详情请查看 1.配置抽屉 1-1。可缓存系统配置 记录用户使用的系统配置,缓存浏览器中,记录用户习惯。 1-2.antd换肤(Layout组件未封装)... -
带有 TS 和 React-hooks 的纯富文本编辑器
2021-06-08 16:45:34已经过去 4 年多了……现在 react-editor 又回来了,带有完全 TS 和 REACT-HOOKS 集成的富文本编辑器,带有 TS 和 React-hooks Polyfill 解决方法,通过 CSS 方法使用 React < 16.8 Placeholder:focus()、... -
基于electron react ts 实现的音乐下载软件.zip
2022-05-30 10:34:15基于electron react ts 实现的音乐下载软件.zip -
react-TSLint规则用于检测ReactHooks的无效使用
2019-08-14 22:37:58TSLint规则,用于检测React Hooks的无效使用 -
react-component-template-ts:我在TypeScript中的React组件模板
2021-05-02 10:58:17我的组件 这是我的组件。 该项目支架可以在 。 演示版 在尝试演示。 如何使用 首先,运行npm install my-component进行生产构建。 或运行npm install my-component@master获取最新开发版本。... import MyComponent ... -
React Ts项目 react-hot-loader 热更新,类型“NodeModule”上不存在属性“hot”
2021-07-16 15:46:07由于使用了ts,在类型检查过程中对于不存在的属性就会抛此种格式的提示,解决方法也很简单,使用as关键字将 module 断言成 any 类型: if ((module as any).hot) { (module as any).hot.accept('./App', () => {... -
「React TS3 专题」使用 TS 的方式在类组件里定义事件
2019-09-30 00:11:45今天的文章我们就到这里,内容不是太多,我们一起学习了如何在React里使用TS的方法定义事件,以及使用箭头函数的方式进行事件方法的实现,接下来的文章,笔者将继续介绍,在React里如何用 TS 的方式定义 State。... -
vant-react:受React和TS启发的轻量级2kb移动UI组件,灵感来自Vant @ https:github.comyouzanvant
2021-02-06 02:44:26基于Typescript和React的轻量级移动UI组件,大小不到2kb! 产品特点 支持打字稿 60多个可重复使用的组件 100%故事书覆盖率: : 大量的文档和演示 安装 # Using npm npm i vant-react -S # Using yarn yarn add ... -
拼西西商城后台管理系统源码(react(hook) + antd + ts).zip
2022-05-16 23:04:58拼西西商城后台管理系统源码(react(hook) + antd + ts) 拼西西商城后台管理系统源码(react(hook) + antd + ts) 拼西西商城后台管理系统源码(react(hook) + antd + ts) 拼西西... -
React TS JSX项目自动化配置,打包build报错问题解决
2021-01-14 19:35:50最终解决 最终问题定位到了一个地方就是查看本地的依赖配置和Jenkins的依赖有出入 找到了问题就知道怎么去解决了,发现配置文件package.json 的tslint是"tslint": “*“和”@types/node”: “^8.0.7”,问题就是出现... -
VM_Buget_App:App Buget .Net5和React TS
2021-03-25 18:13:06VM_Buget_App:App Buget .Net5和React TS -
react ts 脚手架
2020-06-28 09:49:44@ react ts 脚手架 react ts 脚手架 根据自己的项目开发了一个配置好的react+ts 的脚手架,里面集成了一部分配置,那部分部署和问题的解决方案后续都会加上的 地址 https://github.com/bufanpeng/react-ts-cli npm i... -
ReactByDemo:SaaS后台管理系统-练习React钩,TS
2021-03-11 22:35:38首页接口全部变更了 目录结构 │ .gitignore │ package.json │ README.md │ yarn-error.log │ yarn.lock │ ├─config │ ├─public │ │ favicon.ico │ │ index.html │ │ ... ├─Types // -
ts-react-todoList:用react + ts完成简单的todoList
2021-02-15 15:32:31ts-react-todoList 用react + ts完成简单的todoList import React , { useEffect , useRef , useState } from "react" ; import "./App.css" ; import produce from "immer" ; interface TodoList { id: string ; ... -
react-ts-template:React Typescript项目样板
2021-05-24 11:21:16React打字稿模板 React Typescript项目样板 开始使用 yarn 地方发展 启动开发服务器 yarn start 运行测试 运行您所有的测试文件 yarn test 建造 将网站build到build文件夹中 yarn build 埃斯林特 扩展react-app... -
react-fullscreen-crossbrowser:一个简单的React全屏组件,将在JS和TS环境中均可用
2021-05-11 06:35:01全屏跨浏览器React 一个React组件,它使用Fullscreen API将其子级设置为全屏,并使用进行了。 揭露 该软件包是下载并转换为打字稿的两个软件包的组合所有学分: 用法与原始作者相似,但也可以在打字稿中使用 安装。... -
react-fakers:React-Fakers是用于应用程序开发测试的虚拟数据的集合
2021-05-14 09:15:43React Fakers React Fakers是来自最流行的伪数据提供者(例如Json Place Holder,Faker,Pokemon等)的伪数据的集合,用于应用程序开发测试。 表中的内容 API清单 翻译 笔记 贡献 虫子 作者 执照 安装 npm i react... -
react-ts-project-template:React + TS 项目模板 V2.0(基于之前的版本进行了一次大升级)
2021-05-30 04:46:03react-ts-project-template ├── babel.config.js ├── build # Webpack 配置文件目录 │ ├── webpack.base.config.js # Webpack 基础配置文件 │ ├── webpack.dev.config.js # Webpack 开发环境配置文件 ... -
my-react-template:我用于VS Code的简单React + TypeScript模板
2021-05-14 05:27:21我的React模板 我的简单React + TypeScript模板。 , 和是必需的。 $ yarn install $ code . & yarn start 如果您在cmd或powershell中运行, NODE_ENV 用于NODE_ENV 。 高级设置 带有transpileOnly选项也可以看看... -
react-ts-tailwinds:具有TS和Tailwinds的CRA
2021-02-11 14:37:54创建React应用 :heavy_plus_sign: TypeScript + Tailwind CSS TLDR 点击“使用此模板” clone到你的 :laptop_computer: cd进入新目录 :open_file_folder: npm i要建立所有的'node_modules' npm start 在VS ... -
react创建ts项目
2022-06-03 10:20:11react创建ts过程