React项目实战
(一) 创建项目
npm i create-react-app -g
安装脚手架(需要node14以上)create-react-app my-app
创建项目用vscode打开项目my-app
npm start
运行项目win7安装node14:
若安装有nvm, 先卸载
下载node14解压到c盘
右键我的电脑 => 属性 => 高级系统设置 => 环境变量 => 系统变量 => 双击Path
查看有Path里node的路径, 将路径改为
C:\node-v14.15.3-win-x64;NODE_SKIP_PLATFORM_CHECK=1
(二) 路由配置
(1) 配置路由步骤
npm i react-router-dom
安装路由插件创建组件: 首页,目的地,提交需求,发现,我的
在app.js配置路由
- Router 最外层需要用Router进行包裹(只需一次)
- Routes 路由组件包裹层
- Route 用来配置路由,包括路由地址和路由组件
- 重定向使用Navigate
// App.js
import { BrowserRouter as Router, Routes, Route,Navigate} from "react-router-dom";
import Home from "./pages/home/index";
import Demand from "./pages/demand/index";
function App() {
return (
<div className="app">
<Router>
<Routes>
{/*重定向*/}
<Route path="/" element={<Navigate to="/house"/>} />
<Route path="/house" element={<Home />}>房子</Route>
<Route path="/demand" element={<Demand />}> 需求 </Route>
</Routes>
</Router>
</div>
);
}
export default App;
(2) 子路由配置
// App.js配置
import { BrowserRouter as Router, Routes, Route} from "react-router-dom";
import Home from "./pages/home/index";
// Home子路由组件
import Detail from "./pages/home/detail";
import List from "./pages/home/list";
import Demand from "./pages/demand/index";
function App() {
return (
<div className="app">
<Router>
<Routes>
<Route path="/house" element={<Home />}>
{/* 嵌套路由(子路由)配置 */}
<Route path="detail" element={<Detail />} />
{/*访问/home,默认显示list*/}
<Route index element={<List />} />
</Route>
<Route path="/demand" element={<Demand />}> 需求 </Route>
</Routes>
</Router>
</div>
);
}
export default App;
// home.jsx 父路由
import { Outlet } from "react-router-dom";
function Index() {
return (
<div>
<h3>父组件</h3>
<hr />
<Outlet />
</div>
);
}
export default Index;
(3) 重定向
react-router-dom v6以前的版本, 有一个Redirect组件可以实现
v6的重定向, 官方给出的参考是
import { useEffect } from "react"; import { useNavigate } from "react-router-dom"; function Redirect({ to }) { let navigate = useNavigate(); useEffect(() => { navigate(to); }); return null; } // usage <Routes> <Route path="/" element={<Home />} /> <Route path="/events" element={<Users />} /> <Route path="/dashboard" element={<Redirect to="/events" />} /> </Routes>;
(4) 编程式导航
(三) 添加预处理语言支持
- 添加scss支持(不要安装node-sass, 有很多问题)
npm install sass
- 添加less支持
npm i less less-loader@6
less-loader版本太高则不兼容- npm run eject 暴露webpack配置
- 在webpack.config.js修改散出地方, 把sass修改为了less
// 1. 在64行中,将
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
修改成下面的代码(若想保留sass则复制后再修改)
const lessRegex = /\.(less)$/;
const lessModuleRegex = /\.module\.(less)$/;
// 2. 在502行, 将sass修改为less, 如果想保留sass就复制一份出来进行修改
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
},
'sass-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
getLocalIdent: getCSSModuleLocalIdent,
},
},
'sass-loader'
),
},
(四) 导入ant-design
(五) 父子组件通信
// 父组件
import React from 'react';
import Son from './Son'
class Father extends React.Component{
constructor() {
super();
this.getMsg = this.getMsg.bind(this);
}
// 接收子组件传过来的数据
getMsg(data) {
console.log(data);
}
render() {
return(
<div>
<h3>父组件</h3>
<hr/>
{/* 给子组件传递属性和方法 */}
<Son msg="hello son" getMsg={this.getMsg}/>
</div>
)
}
}
export default Father;
// 子组件
import React from 'react';
class Son extends React.Component{
constructor() {
super();
}
render() {
let {msg,getMsg} = this.props;
return(
<div>
{msg}<br/>
{/* 调用父组件传过来的方法,并传递数据 */}
<button onClick={()=>{getMsg('哈哈哈哈哈')}}>发送消息</button>
</div>
)
}
}
export default Son;
(六) axios 拦截器
import axios from "axios";
let isDev = process.env.NODE_ENV === 'development';
let baseURL;
if (isDev) {
baseURL = "http://localhost:3006";
} else {
baseURL = "http://huruqing.cn:3006";
}
const service = axios.create({
baseURL,
timeout: 10 * 60 * 1000,
});
//4. 请求拦截
service.interceptors.request.use(
(config) => {
// do something
return config;
},
(err) => {
return Promise.reject(err);
}
);
service.interceptors.response.use(
(res) => {
const data = res.data;
if (data.code != 666) {
return Promise.reject(data.msg);
}
return data;
},
(err) => {
return Promise.reject(err);
}
);
const get = (url, data = {}) => {
return service.get(url, { params: data });
};
const post = (url, data = {}) => {
return service.post(url, data);
};
export default {
get,
post,
};
(七) 静态页面
引入icont
使用短路径
在React项目使用短路径, 跟 ../../../../地狱模式说拜把
项目的根目录下创建
jsconfig.json
文件,并添加以下代码。
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
// 使用
import axios from "../../../utils/request"; // 以前的写法
import axios from "utils/request";
图片的引用问题
最佳实践: 写静态的时候, 如果图片来自网上, 随便用网上的一张图片暂代, 等 拿到数据再使用变量代替
方式1: 支持完整路径
<img sr="https://mall.s.maizuo.com/aaa.png"/>
方式2: 使用import
import bg from 'assest/img/bg.png'
<img src={bg} alt=""/>
渲染还可以这样写
{
list.map(item=>(
<ul>
<li>11111</li>
<li>22222</li>
</ul>
))
}
// 类似vue的template的做法
{
list.map(item=>(
<>
<div>11111</div>
<div>22222</div>
</>
))
}
react渲染html字符串(类似vue的v-html指令)
let htmlStr = `<ul class="nav fcc bg-fff">
<li class="fg1 ifcc item active">推荐•路线</li>
<li class="fg1 ifcc item">推荐•路线</li>
<li class="fg1 ifcc item">推荐•路线</li>
</ul>`
export default function() {
return (
<div className="pt-15 bg-fff" dangerouslySetInnerHTML={{ __html:htmlStr}}></div>
)
}
(八) classnames
类似vue绑定class的操作
// 判断条件为true时会给div添加class类 on
<div className={classnames("flex jc-sa",{on:判断条件}}></div>
// 实际应用
import React from 'react';
import classnames from 'classnames';
export default function() {
let curr = '01';
return(
<div className="demo-index">
<li className={classnames("flex f18 jc-sb",{on: curr==='01'})}>111</li>
<li className={classnames("flex f18 jc-sb",{on: curr==='02'})}>222</li>
<li className={classnames("flex f18 jc-sb",{on: curr==='03'})}>333</li>
</div>
)
}
(九) Hooks
推荐链接: React useState() 使用指南
react hooks介绍
- 在函数组件中没有state(状态), 也没有生命周期
- react hooks是react中引入新特性,它可以让react函数组件也拥有状态
知识点
- useState 定义状态
- useEffect 副作用
- useNavigate 导航
- 其它hooks
(1) useState
- 在函数组件中使用useState来定义响应式数据, 接收一个参数(变量的默认值)
- 使用格式
let [value,setValue] = useState(initValue)
- value要定义的变量名称
- setValue用来修改value的方法
- initValue初始值
01 value是基本数据类型
import React, { useState } from 'react';
export default function() {
// 定义响应式数据keyword,keyword的默认值是 ''
let [keyword,setKeyword] = useState('');
return(
<div>
<button onClick={()=>{setKeyword('哈哈哈哈哈')}}>修改关键字</button>
<p>{keyword}</p>
</div>
)
}
02 value是对象
import React, { useState } from "react";
function Demo() {
let [obj, setObj] = useState({
username: "张三",
age: 18,
});
const handleClick = (key, value) => {
// 需要传入一个新的对象
setObj({
...obj,
[key]: value,
});
};
return (
<div>
<p>
{obj.username}
<button onClick={() => { handleClick("username", "李四"); }} > 修改姓名 </button>
</p>
<p>
{obj.age}
<button onClick={() => { handleClick("age", 20); }} > 修改年龄 </button>
</p>
</div>
);
}
export default Demo;
03 value是数组
import React, { useState } from "react";
function Demo() {
let [list, setList] = useState([
{ username: "张三", finished: 17 },
{ username: "李四", finished: 18 },
{ username: "王五", finished: 19 },
]);
const update = (item)=> {
item.finished = !item.finished;
// 需要传入一个新的数组
setList([...list]);
}
return (
<ul>
{list.map((item, index) => (
<li key={index}>
<span>{item.username} </span>
{item.finished?'已完成':'未完成'}
<button onClick={()=>{update(item)}}>修改状态</button>
</li>
))}
</ul>
);
}
export default Demo;
04 useState依赖原来的值
let [count,setCount] = useState(0);
// 在原来的基础上加1
setCount(val=>val+1);
(2) useEffect
- 中括号内的变量发生了改变, 就会触发回调函数
- 请求后台接口可以放在useEffect的函数里执行, 中括号为空或者不要中括号
let [keyword,setKeyword] = useState('');
useEffect(()=> {
console.log(2222);
// 当keyword发生变化时,会触发回调函数
},[keyword])
(3) useNavigate
import {useNavigate} from 'react-router';
// 跳转到/home/detail
navigate('/home/detail'});
// // 跳转到/home/detail并传参参数
navigate('/home/detail',{
state: {
id: item.id
}
})
useMemo
类似vue的computed
(十) 路由跳转和传参
路由跳转:
1. 使用 <Link to="xxx">xxx</Link>
2. 通过 navigate进行跳转
- 一个参数: 目的地路由
- 两个参数: 目的路由, state数据
(1) 通过state传参
传递数据
// 列表页面
import {useNavigate} from 'react-router';
function House({ houseList}) {
const navigate = useNavigate();
// 跳转到详情
const toDetail = (item) => {
navigate('/home/detail',{
// state里放要传递的参数
state: {
id: item.id
}
})
}
接收参数
// 详情页面
import {useLocation} from 'react-router';
function List() {
const location = useLocation();
console.log(location);
return ( <div>详情</div> );
}
export default List;
(2) 动态路由传参
配置动态路由(app.js)
<Route path="/demo2/:id" element={<Demo2 />} />
路由跳转并传参(demo.jsx);
import React from "react";
import { Link } from "react-router-dom";
import {useNavigate} from 'react-router'
function Demo() {
const navigate = useNavigate();
return (
<div>
<Link to="/demo2/2222">去demo2</Link>
<button onClick={()=>{navigate('/demo2/3333')}}>去demo2</button>
</div>
);
}
export default Demo;
接收参数
import React from "react";
import {useParams} from 'react-router';
function Demo2() {
const params = useParams();
console.log(params);
return (
<div>
<p>{params.id}</p>
</div>
);
}
export default Demo2;
(十一) redux
本例gitee地址: git@gitee.com:huruqing/react-redux-demo.git
新版redux,使用hooks https://react-redux.js.org/tutorials/quick-start
(1) redux使用场景
mobx也是用来进行跨组件通信, 比redux更简单一些 一句话: 状态共享, 跨组件通信
某个组件的状态,需要共享
某个状态需要在任何地方都可以拿到
一个组件需要改变全局状态
一个组件需要改变另一个组件的状态
(2) 核心概念
- **Store: **Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。
Redux 提供createStore这个函数,用来生成 Store。
- **State: **状态, 存放在store里
- Action
- action是个对象, 描述当前发生的事情
- Action Creator: View 要发送多少种消息,就会有多少种 Action。如果都手写,会很麻烦。可以定义一个函数来生成 Action,这个函数就叫 Action Creator。
- 派发action: store.dispatch() 是 View 发出 Action 的唯一方法。
- Reducer
- Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。
- Reducer 是一个纯函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。上面的createStore接受 Reducer 作为参数,生成一个新的 Store
- 纯函数: 纯函数是函数式编程的概念,必须遵守以下一些约束。
- 特点: 相同的输入会有相同的输出
- 不得改写参数
- 不能调用系统 I/O 的API(就是输入输出)
- 不能调用
Date.now()
或者Math.random()
等不纯的方法,因为每次会得到不一样的结果
(3) 项目中redux步骤
知识目录
- 创建store
- 获取状态
- 修改状态
- 模块化
- 持久化
1. 安装redux和react-redux
npm i redux react-redux
2. 创建store和相关的东西
- src下新建 /redux/index.js
- 初始化state、声明action、声明reduer
- 创建store并导出
import {createStore} from 'redux';
// 1.state的初始值
const initState = {
count: 0
}
// 2.声明action creator 并导出,payload是派发action时传进来的数据
export const updateCount = function(payload) {
// 此函数返回一个action
return {
type: 'UPDATE_COUNT',
payload,
}
}
// 3.声明reducer
const reducer = function(state=initState,action) {
let {type,payload} = action;
switch(type) {
case 'UPDATE_COUNT':
return {
...state,
count: state.count+payload
}
default:
return state;
}
}
let store = createStore(reducer);
export default store;
3. 挂载store
// index.js(src目录下的)
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {Provider} from 'react-redux';
import store from 'redux/index'
ReactDOM.render(
<React.StrictMode>
// 挂载store
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
4. 获取和修改store的状态
把普通react组件改造成react高阶组件
import React from "react";
// 1 导入action creator等相关东西
import { updateCount } from "redux/index";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
function Demo(props) {
return (
<div>
{/* 5.获取count的值 */}
<p>count的值: {props.count}</p>
{/* 修改count的值 */}
<button onClick={()=>{props.updateCount(props.count+1)}}>修改count</button>
</div>
);
}
// 2.把store里state转变成props来使用,后面访问state时就使用props.xxx来进行访问
// @params state store里面所有状态
function mapStateToProps(state) {
return {
// 组件使用props.count来访问count状态
count: state.count
}
}
// 3.把dispatch转变成props来使用
function mapDispatchToProps(dispatch) {
return {
// bindActionCreators的作用:把action creator和dispatch绑定起来
updateCount: bindActionCreators(updateCount,dispatch)
}
}
// 4.connect方法的作用: 把普通组件Demo变高阶组件
export default connect(mapStateToProps,mapDispatchToProps)(Demo);
(4) redux 模块化
- 新增cart模块, 在里面定义state,action,reducer并导出
// demo模块
// 1.state的初始值
const initState = {
count: 10
}
// 2.声明action creator 并导出,payload是派发action时传进来的数据
export const updateCount = function(payload) {
// 此函数返回一个action
return {
type: 'UPDATE_COUNT',
payload,
}
}
// 3.声明reducer
export default function(state=initState,action) {
let {type,payload} = action;
switch(type) {
case 'UPDATE_COUNT':
return {
...state,
count: payload
}
default:
return state;
}
}
// user模块
// 1.usermok的初始化状态
const initState = {
phone: "",
token: "",
};
// 2.相关action creator
export const updatePhone = function (payload) {
// 返回一个action
return {
type: "UPDATE_PHONE",
payload,
};
};
export const updateToken = function (payload) {
return {
type: "UPDATE_TOKEN",
payload
};
};
// 3.声明reducer
export default function (state = initState, action) {
let { type, payload } = action;
switch (type) {
case "UPDATE_PHONE":
return {
...state,
phone: payload,
};
case "UPDATE_TOKEN":
return {
...state,
token: payload,
};
default:
return state;
}
}
// 合并reducer, /src/redux/index.js
import {createStore} from 'redux';
import demoReducer from './demo';
import userReducer from './user';
import { combineReducers } from 'redux';
// 合并reducer
let reducers = combineReducers({
demo: demoReducer,
user: userReducer
})
export default createStore(reducers);
- 合并reducer, 改造/redux/index.js 代码
import {createStore} from 'redux';
import demoReducer from './demo';
import userReducer from './user';
import { combineReducers } from 'redux';
// 合并reducer
let reducers = combineReducers({
demo: demoReducer,
user: userReducer
})
export default createStore(reducers);
(5) redux 持久化
1. 安装持久化插件 redux-persist
npm i redux-persist
2. 使用插件对store进行持久化操作
改造 /redux/index.js 代码, 对reducer和store进行持久化配置
3. 应用持久化后的store
改造 /src/index.js, 实现持久化
*************************模块化之前持久化**************************
// src/redux/index.js
import { createStore } from "redux";
import {persistStore, persistReducer} from 'redux-persist';
import storageSession from 'redux-persist/lib/storage/session';
// 初始状态
const initState = {
count: 0,
};
export const updateCount = (payload) => {
return {
type: "UPDATE-COUNT",
payload,
};
};
// 修改状态的一个方法, 叫reducer, 当用户派发了一个action, 不管是什么action, 这里都会接收到
const reducer = (state = initState, action) => {
let { type, payload } = action;
switch (type) {
case "UPDATE-COUNT":
return {
...state,
count: state.count + payload,
};
break;
default: {
return state;
}
}
};
const storageConfig = {
key: 'root', // 必须有的
storage:storageSession, // 缓存机制
blacklist: [] // reducer 里不持久化的数据,除此外均为持久化数据
}
const newReducer = persistReducer(storageConfig, reducer);
export let store = createStore(newReducer);
export let newStore = persistStore(store);
/**
* 模块之前的持久化
* src/index.js
*/
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import "antd-mobile/dist/antd-mobile.css";
import { Provider } from "react-redux";
import {store,newStore} from "./redux/index";
import { PersistGate } from "redux-persist/lib/integration/react";
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate persistor={newStore}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
reportWebVitals();
*************************模块之后的持久化**************************
// src/redux/index.js代码
import {createStore} from 'redux';
import demoReducer from './demo';
import userReducer from './user';
import { combineReducers } from 'redux';
// 1.导入相关插件
// persistStore持久化store, 持久化reducer
import {persistStore, persistReducer} from 'redux-persist';
// storageSession缓存
import storageSession from 'redux-persist/lib/storage/session';
// 2.store持久化设置
const storageConfig = {
key: 'root', // 必须有的
storage:storageSession, // 缓存机制
blacklist: [] // reducer 里不持久化的数据,除此外均为持久化数据
}
// 3.合并reducer
let reducers = combineReducers({
demo: demoReducer,
user: userReducer
})
// 4.给reducer应用持久化配置
const newReducers = persistReducer(storageConfig, reducers);
// 5.创建store
const store = createStore(newReducers);
// 6.对store进行持久化并导出
export const persistor = persistStore(store);
// 7.导出store
export default store;
// src/index.js代码
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
// 8.持久化
import store, { persistor } from "./redux/index";
import { PersistGate } from "redux-persist/lib/integration/react";
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
{/* 用持久化后的store包裹<App/> */}
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
reportWebVitals();
(6) 异步action,使用redux-thunk实现
- 安装redux-thunk
npm i redux-thunk
- 改造/redux/index.js
// 核心代码如下
//1.applyMiddleware 加载中间件
import { createStore,applyMiddleware } from "redux";
//2.导入异步中间件thunk
import thunk from 'redux-thunk';
const store = createStore(newReducers,applyMiddleware(thunk));
- 创建异步action
改造/redux/demo.js
// 1.state的初始值
const initState = {
count: 10,
};
// 2.声明action creator 并导出,payload是派发action时传进来的数据
// export const updateCount = function(payload) {
// // 此函数返回一个action
// return {
// type: 'UPDATE_COUNT',
// payload,
// }
// }
export const updateCount = (payload) => {
// 异步action, 允许返回一个函数,使用dispatch派发action
return (dispatch) => {
setTimeout(() => {
dispatch({
type: "UPDATE_COUNT",
payload,
});
}, 1000);
};
};
// 3.声明reducer
export default function (state = initState, action) {
let { type, payload } = action;
switch (type) {
case "UPDATE_COUNT":
return {
...state,
count: statepayload,
};
default:
return state;
}
}
(7) axios拦截器给http请求头添加token
配置后再查看首页的请求是否都带上了token
import axios from 'axios';
// 1.导入redux
import redux from 'redux/index';
const service = axios.create({
baseURL: 'http://132.232.87.95:3006',
timeout: 10 * 60 * 1000 //10分钟
})
service.interceptors.request.use(
(config) => {
// 2.获取store
let store = redux.getState();
// 3.把token放入请求头
config.headers['user-token'] = store.user.token;
return config;
},
(err) => {
return Promise.reject(err);
}
)
service.interceptors.response.use(
(res) => {
const data = res.data;
if (data.code != 666) {
return Promise.reject(data.msg);
}
return data;
},
(err) => {
return Promise.reject(err);
}
)
const get = (url,data={})=> {
return service.get(url,{params: data});
}
const post = (url,data={})=> {
return service.post(url,data);
}
export default {
get,post
};
(十二) Mobx
介绍
- mobx是react用来跨组件通信的一个插件, 它的核心是依赖注入
- 具体做法就是:
- 先创建一个(或多个)可观察的仓库
- 在需要使用仓库状态的组件, 使用enject方法将这个仓库注入到它的props里, 就可以使用仓库的状态了
- 若组件要修改仓库的状态, 则需要将组件用observer方法成包装高级组件
(1) 安装依赖
npm install mobx mobx-react
(2) 配置store
// src/store/index.js
makeAutoObservable 使一个普通类的属性和方法变成一个响应式的状态库
函数前面加get, 类似vuex的getters, 用来根据已有属性计算出一个新的属性
import * as mobx from "mobx";
class Store {
count = 0;
constructor() {
mobx.makeAutoObservable(this);
}
add() {
this.count++;
}
minus() {
this.count--;
}
// 求平方根
get sqrt() {
return Math.sqrt(this.count);
}
}
export default new Store();
(3) 挂载
// src/index.js
Provider: 提供数据
import React from "react";
import ReactDOM from "react-dom";
import "./index.scss";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "mobx-react";
import store from "store";
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
reportWebVitals();
(4) 使用和修改
- inject 将store注入到props里
- observer 将组件变成高级组件, 可以修改仓库状态
- 在不需要修改状态的组件里, 只需要注入即可
import { inject, observer } from "mobx-react";
import React from "react";
function Demo({ store }) {
return (
<div style={{margin:'30px'}}>
<button onClick={()=>{store.add()}}>+</button>
<button>{store.count}</button>
<button onClick={()=>{store.minus()}}>-</button>
<p>
开平方根: {store.sqrt.toFixed(2)}
</p>
</div>
);
}
export default inject("store")(observer(Demo));
错误: Support for the experimental syntax 'decorators-legacy' isn't currently enab -- 装饰器@
[报错显示:Parsing error: This experimental syntax requires enabling one of the following parser plugin(s): “decorators-legacy”, “decorators”.](https://blog.csdn.net/lfy_wybss/article/details/122079178)
(十三) 性能优化
知识点
- shouldComponentUpdate
- PureComponent
- useMemo
(1) shouldComponentUpdate
类(class)组件性能9优化可以使用shouldCompoentUpdate进行优化
// nextProps下一个属性(新的属性),nextState下一个状态(新的状态)
shouldComponentUpdate(nextProps, nextState) {
// 根据新的属性或者状态决定要不要更新页面
if(xxx) {
return true;
} else {
return false
}
}
(2) PureComponent
类(class)组件, 可以让其继承React.PureComponent来实现优化
import React from "react";
class Demo extends React.PureComponent {
constructor(props){
super(props);
}
render() {
console.log(this.props);
return (<div>性能优化</div>)
}
}
export default Demo;
(3) memo
函数组件可以使用React.memo进行包装以实现优化
import React from "react";
function Scene(props) {
return <div>{props.name}</div>;
}
export default React.memo(Scene);