react是facebook出的一款针对view视图层的library库。react遵循单向数据流的机制。目前我们学的是react17.x的版本
https://react.docschina.org/
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是一样的功能
- https://yarn.bootcss.com/
- npm i yarn -g # 安装yarn
# 使用
yarn add xx # 安装模块
yarn remove xx # 删除模块
yarn # 找到package.json文件,根据依赖项安装所有的依赖 - vite
- 它是另外的一种创建项目的方式,使用的不是webpack。下一代前端开发与构建工具
- https://cn.vitejs.dev/
- npm init vite@latest
# or
yarn create vite - 使用sass
- npm i sass -D # 安装sass插件就行
- 路由
- https://reactrouter.com/
- 安装
- 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组件库。
- https://ant-design.gitee.io/index-cn
- npm i antd # 安装依赖
- 管理后台项目
- redux
- https://redux.js.org/
- 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
- https://umijs.org/
- umi是一个企业级的开发框架,内置了react、react-router、dva、antd等插件,可以实现开箱即用
- dva
- 是一个redux的封装,内置了常见的redux插件:redux-thunk、redux-saga、redux-devtools等等,可以让我们很方便的来实现redux的使用
- ts和antd pro
- antd pro
- https://pro.ant.design/zh-CN/docs/getting-started
- # 使用 npm
npx create-umi myapp
# 使用 yarn
yarn create umi myapp - ts
- TypeScript是js的一个超集。就是在js语言的基础上加入了数据类型的概念,所有的ts语句最终都会被编译成js进行运行
- https://www.tslang.cn/ ts的官网
- 在ts中当出现报错警告的时候,直接定义数据类型为any
- http://json2ts.com/ 作用是把json数据转换为ts数据结构,用来在项目中对接口返回的数据做处理
- 其他ui框架
- ionic
- 这是一个移动端开发框架,是用来做手机页面的
- https://ionicframework.com/
- 可以让我们的做的页面具有原生app一模一样的效果
- npm install -g @ionic/cli
ionic start --type=react - framework7
- https://framework7.io/
- maturial
- https://mui.com/zh/ 这个是一定要知道的。是google推出的,目前比较流行的flutter就是使用的这种设计风格
- next.js
- 它是一个react的服务器端渲染框架,可以做多页面应用程序开发。解决了单页面应用程序存在的所有弊端。
- npx create-next-app first-next-app-pre # 创建一个next项目Reach route61.基础更改<Route>特性变更
path:与当前页面对应的URL匹配
element新增,用于决定路由匹配时,渲染组件组件,代替,v5的compoent和render
<Routers>代替了Switch>
<Outlet></Outlet>嵌套路由更简单
useNavigate代替useHitory
移除Navlink的activeClass和activeStyle
钩子useRouter代替react-router-config
index用于嵌套路由,仅匹配父路由路径时,设置渲染 2.路由重定向 Navigate使用
<Route path="*" element={<Navigate to="/film"/>}/>3.组件嵌套
<Outlet></Outlet>
本文暂时没有评论,来添加一个吧(●'◡'●)