react是facebook出的一款针对view视图层的library库。react遵循单向数据流的机制。目前我们学的是react17.x的版本
React 官方中文文档 – 用于构建用户界面的 JavaScript 库
react基础语法和常见api
jsx语法
就是在js种直接使用html标签来写。
const str = '你好啊!' const people = [<p>苹果嘉儿</p>,<p>云宝</p>,<p>紫悦</p>,<p>珍奇</p>] function Demo() { return <> <h1>我是一个组件</h1> <p>{str}</p> <hr/> {people} <hr/> {people.length>1?'人数多于一个':'人数少于一个'} </> }
function定义组件
组件传参
父传子使用props
子传父使用方法调用
hooks
是react16.8之后新增得功能,可以在function定义得组件中设置局部状态和模拟组件的生命周期。是目前官方推荐的组件定义方式。
useState
可以在function定义的组件中设置局部状态数据,当状态数据改变的时候组件会重新更新
function App() { const [count, setCount] = React.useState(1) // // useState返回一个数组,接收一个参数作为初始状态数据 // 一个组件中可以定义多次useState,但是它不能放在循环或者条件语句中 // 第一项表示变量名 // 第二项表示改变数据的方法 // 当count值变了,这个function中的代码会重新执行 .... }
useEffect
副作用,接收两个参数
参数一:回调函数,回调函数可以返回一个function,这个返回值在组件销毁的时候执行
参数二:依赖数组
当依赖数组中的数据改变的时候,回调函数会执行
关于参数二有以下几种场景
参数二不存在,没有参数二。当组件的属性或者状态数据改变的时候,参数一的回调函数都会执行
参数二是一个空数组,就是数组没有内容。只在组件初始化的时候执行一次,用来调接口取数据
参数二是一个正常的数据。当数组中的任意一项发生了改变,那么回调函数就会执行
useRef
作用是获取组件中的dom元素
useContext
上下文,在react中实现跨组件之间传参.
useCallback
对function做缓存,接收两个参数,参数一是一个function,参数二是一个依赖数组。当依赖数组中的数据改变的时候function会重新执行
useMemo
对值做缓存,接收两个参数,参数一是一个返回一个值的function,参数二是一个依赖数组。当依赖数组中的数据改变的时候被缓存的值会重新计算
memo
对组件做缓存,主要是做性能优化。当组件接收到的属性没有改变的时候组件不会重新渲染
class定义组件
class定义组件时react中另外一种定义组件的方式。可以在组件内部设置局部状态和生命周期。当状态或者属性数据改变的时候组件会重新渲染
class定义的组件和function定义的组件是可以混合使用的
class Counter extends React.Component { // 每一个组件都需要有一个render方法,这个方法需要一个返回值,返回一个html节点作为当前组件展示的元素内容 render() { return <h1>我是一个计数器</h1> } }
组件状态
state表示局部状态
如果要改变状态数据,需要调用setState方法。setState方法接收两个参数,一般参数二都不用。改变state数据是异步操作的,在参数二的回调函数中可以获取state改变之后的最新数据
... this.setState({ count: 18 }, function() { // 这里可以获取state的最新数据 console.log(this.state) }) ...
this指向问题
改变this指向有三种写法:
在constructor中直接绑定(建议使用第一种)
在render的时候进行绑定
使用箭头函数(如果需要传参使用第三种)
// 在class定义的组件中有一个很麻烦的问题,就是this指向问题 class Counter extends React.Component { // 创建的时候执行 constructor(props) { super(props); // 通过this.state可以为组件设置状态数据 this.state = { count: 1, name: "counter计数器", }; this.clickHandle = this.clickHandle.bind(this); // 推荐写法 } clickHandle() { // console.log(this); // 在class定义的组件中如果我们要改变state数据,需要调用setState方法 // setState是异步的,如果想获取最新的state数据,需要在参数二的回调函数中获取值 this.setState( { count: this.state.count + 1, }, function () { console.group("回调函数中获取"); console.log(this.state.count); console.groupEnd(); } ); console.log(this.state.count); } clickHandle2() { this.setState({ count: this.state.count + 2, }); } clickHandle3() { this.setState({ count: this.state.count + 3, }); } // 在属性或者数据改变的时候会调用 render() { console.log("render执行了"); return ( <> <h1> {this.state.name}-{this.state.count} </h1> <button onClick={this.clickHandle}>加+</button> <button onClick={this.clickHandle2.bind(this)}>加+2</button> <button onClick={() => this.clickHandle3()}>加+3</button> </> ); } } const App = () => ( <> <h1>我是组件</h1> <Counter /> </> ); ReactDOM.render(<App />, document.querySelector("#app"));
PureComponent
对组件做性能优化,组件属性只做浅比较。当属性没有改变的时候组件不会重新渲染。相当于function定义组件中的memo方法
contextType
通过为组件设置属性contextType可以在组件内部获取context上下文中提供的数据
const { createContext, Component } = React; const context = createContext(); class AppProvider extends Component { constructor(props) { super(props); } render() { return ( <context.Provider value={{ name: "class定义的组件" }}> {this.props.children} </context.Provider> ); } } class Home extends Component { constructor(props) { super(props); } render() { console.log(this.context); return ( <> <h1>首页</h1> <p>{this.context.name}</p> </> ); } } Home.contextType = context; // 通过为组件设置一个contextType属性把context上下文中的value数据映射到组件内部 const App = () => ( <> <h1>我是组件</h1> <Home /> </> ); ReactDOM.render( <AppProvider> <App /> </AppProvider>, document.querySelector("#app") );
组件生命周期
class组件的生命周期16.3之前和之后有差异
16.3之前的钩子函数:
constructor(不算生命周期钩子函数,应该是class的构造函数,可以在这里面设置state数据和获取props属性)
componentWillMount,组件挂载之前执行
componentDidMount【很重要】,class定义的组件在这里获取数据
componentWillReceiveProps,将要接收新的属性
shouldComponentUpdate,组件是否需要更新。主要用来做性能优化的时候需要操作的生命周期函数。返回bool值,true后续的更新阶段会执行;否则不更新
componentWillUpdate,将要更新
componentDidUpdate,更新完成
componentWillUnmount,卸载
16.3之后的删除了will开头的三个函数(componentWillMount、componentWillReceiveProps、componentWillUpdate)。新增了几个钩子函数,作为了解听过就行
function定义的组件中useEffect对应class定义组件中的三个生命周期钩子函数:componentDidMount、componentDidUpdate、componentWillUnmount
和function定义的组件的useEffect对应:
// 参数二为空数组,对应componentDidMount useEffect(()=>{ return () => { // 对应componentWillUnmount } }, []) // 对应componentDidUpdate useEffect(()=>{ }, [xx])
嵌套组件的生命周期问题:如果组件出现嵌套,那么在执行父组件的更新或者挂载完成之前会完成所有子组件的挂载和更新。最后才会执行外围的挂载和更新完成
class组件中使用ref
用来获取组件中的dom元素
function和class定义组件的区别
function定义的组件中不存在this指向问题,function定义的组件又叫无状态组件但是在react16.8之后新增了hooks,可以在function定义的组件中模拟局部状态和生命周期
class定义的组件有自己的局部状态和生命周期
目前官方推荐使用function的方式定义组件
备注:hooks在2019年的时候已经开始推荐并普及使用,antd是react中一个非常知名的ui组件库,它在4.0之后的版本中已经开始全面使用function+hooks的写法
useReducer
是react中的一个hooks,可以让我们使用类似redux中的数据流机制进行状态数据的管理
reducer是一个function,这个function接收两个参数(state,action),返回一个新的state数据
state表示状态数据
action表示行为,必须包含一个type属性
高阶组件
react脚手架
create-react-app
create-react-app(CRA)是官方的脚手架,这个脚手架只提供基础的一些插件,是基于webpack的。
npx create-react-app first-react-app # 创建一个react项目 cd first-react-app npm start # 启动项目
如果电脑上安装的有yarn这个模块管理工具,那么cra默认使用的是yarn做模块管理
yarn
它是facebook推出的一款包管理工具,和npm是一样的功能
npm i yarn -g # 安装yarn # 使用 yarn add xx # 安装模块 yarn remove xx # 删除模块 yarn # 找到package.json文件,根据依赖项安装所有的依赖
vite
它是另外的一种创建项目的方式,使用的不是webpack。下一代前端开发与构建工具
npm init vite@latest # or yarn create vite
使用sass
npm i sass -D # 安装sass插件就行
路由
React Router: Declarative Routing for React.js
安装
npm i react-router-dom # 安装路由插件
使用
HashRouter或者BrowserRouter
路由组件的根节点,一个项目中只能有一个
Route
路由组件,每一个路径对应显示的内容在这里标准
path
表示路由的路径,就是url中访问的地址,访问指定路径的时候展示对应的组件
exact
表示绝对匹配
Route对应展示的组件有三种写法
直接写成子标签children的形式
<Route path="/list"> <List/> </Route>
推荐用法,在List组件的属性中不能直接获取路由对象信息,但可以通过withRouter方法实现
写成属性component
<Route path="/list" component={List} />
可以直接在List组件的属性中获取路由对象信息
通过render方法展示
<Route path="/list" render={()=><List/>} />
在List组件的属性中不能直接获取路由对象信息,但可以通过withRouter方法实现
Link
生成跳转链接
Switch
只匹配一个
withRouter
作用是把路由对象的属性信息映射到组件的属性上
import React from "react"; import { withRouter } from "react-router-dom"; function Products(props) { console.group("products"); console.log(props); console.groupEnd(); return ( <div> <h2>商品列表</h2> </div> ); } export default withRouter(Products);
路由传参
params
需要在路由中设置占位符。如果没有占位符,那么刷新之后会消失
search
就是直接在url中传递,通过?进行分割。刷新之后也不会消失。建议使用search
state
直接传递。刷新之后直接消失
useLocation
获取location数据,可以用来获取参数
useHistory
获取历史记录信息,可以使用push、go等方法做跳转
useParams
获取parmas参数
antd
ant.design是蚂蚁金服出的一款ui组件库。
Ant Design - 一套企业级 UI 设计语言和 React 组件库
npm i antd # 安装依赖
管理后台项目
redux
Redux - A predictable state container for JavaScript apps. | Redux
redux是一个全局状态管理插件。它是单向数据流的。
单向数据流:数据是单向流动的,分为三部分(state,action,view)。在view视图中通过dispatch派发一个action改变数据,数据改变之后view视图重新渲染
action
行为,每一个action都建议有一个type属性,type不能重复。因为在dispatch派发的时候所有的reducer都会收到这个action,根据type不一样来做不同的处理
state
存储数据
reducer
改变数据的地方,reducer是一个function。接收两个参数
参数一 表示state的初始值
参数二是一个action
安装使用
npm i redux # 安装插件,是核心模块 npm i react-redux # 插件的作用是实现redux和react的连接
redux中的方法
createStore 作用是创建一个数据存储
combineReducers 合并多个reducer为一个
react-redux中的方法
Provider
是一个组件需要放在项目的最外层,用来把store数据传递给整个项目
connect
实现数据以及dispatch方法和组件的关联,把数据和dispatch方法映射到组件的属性上
useSelector
获取state数据
useDispatch
获取dispatch方法
redux-thunk
插件的作用是用来处理异步action。所有的action必须返回一个plain object,不能是一个function。为了解决异步问题,可以借助插件实现
redux-thunk,它的作用是判断action的数据类型,如果是function,那么会把dispatch当参数传递给function;如果是一个对象,那么就直接执行
redux-toolkits
它目前是redux官方推荐的写法
npm install @reduxjs/toolkit react-redux # 安装依赖
umi
UmiJS - Extensible enterprise-level front-end application framework.
umi是一个企业级的开发框架,内置了react、react-router、dva、antd等插件,可以实现开箱即用
dva
是一个redux的封装,内置了常见的redux插件:redux-thunk、redux-saga、redux-devtools等等,可以让我们很方便的来实现redux的使用
ts和antd pro
antd pro
# 使用 npm npx create-umi myapp # 使用 yarn yarn create umi myapp
ts
TypeScript是js的一个超集。就是在js语言的基础上加入了数据类型的概念,所有的ts语句最终都会被编译成js进行运行
TypeScript中文网 · TypeScript——JavaScript的超集 ts的官网
在ts中当出现报错警告的时候,直接定义数据类型为any
json2ts - generate TypeScript interfaces from json 作用是把json数据转换为ts数据结构,用来在项目中对接口返回的数据做处理
其他ui框架
ionic
这是一个移动端开发框架,是用来做手机页面的
Cross-Platform Mobile App Development: Ionic Framework
可以让我们的做的页面具有原生app一模一样的效果
npm install -g @ionic/cli ionic start --type=react
framework7
Framework7 - Full Featured Framework For Building iOS, Android & Desktop Apps
maturial
MUI: The React component library you always wanted 这个是一定要知道的。是google推出的,目前比较流行的flutter就是使用的这种设计风格
next.js
它是一个react的服务器端渲染框架,可以做多页面应用程序开发。解决了单页面应用程序存在的所有弊端。
npx create-next-app first-next-app-pre # 创建一个next项目