react实战

React项目实战

[[TOC]]

(一) 创建项目

  1. npm i create-react-app -g 安装脚手架(需要node14以上)

  2. create-react-app my-app 创建项目

  3. 用vscode打开项目my-app

  4. npm start 运行项目

    win7安装node14:

  5. 若安装有nvm, 先卸载

  6. 下载node14解压到c盘

  7. 右键我的电脑 => 属性 => 高级系统设置 => 环境变量 => 系统变量 => 双击Path

  8. 查看有Path里node的路径, 将路径改为

    C:\node-v14.15.3-win-x64;NODE_SKIP_PLATFORM_CHECK=1
    

(二) 路由配置

(1) 配置路由步骤

  1. npm i react-router-dom 安装路由插件
  2. 创建组件: 首页,目的地,提交需求,发现,我的
  3. 在app.js配置路由
    1. Router 最外层需要用Router进行包裹(只需一次)
    2. Routes 路由组件包裹层
    3. Route 用来配置路由,包括路由地址和路由组件
// App.js
import { BrowserRouter as Router, Routes, Route} 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="/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 (
    
} /> }> {/* 嵌套路由(子路由)配置 */} } /> } /> }> 需求
); } export default App;
// home.jsx 父路由
import { Outlet } from "react-router-dom";

function Index() {
  return (
    

父组件


); } export default Index;

(3) 重定向

  1. react-router-dom v6以前的版本, 有一个Redirect组件可以实现

  2. v6的重定向, 官方给出的参考是

    import { useEffect } from "react";
    import { useNavigate } from "react-router-dom";
    
    function Redirect({ to }) {
      let navigate = useNavigate();
      useEffect(() => {
        navigate(to);
      });
      return null;
    }
    
    // usage
    
      } />
      } />
      }
      />
    ; 
    

(三) 添加预处理语言支持

  1. 添加scss支持(不要安装node-sass, 有很多问题)
npm install sass
  1. 添加less支持
    1. npm i less less-loader@6 less-loader版本太高则不兼容
    2. npm run eject 暴露webpack配置
    3. 在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,
};

(七) 静态页面

  1. 引入icont
  2. 使用短路径

    在React项目使用短路径, 跟 …/…/…/…/地狱模式说拜把

    项目的根目录下创建jsconfig.json文件,并添加以下代码。

{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "include": ["src"]
}

// 使用
import axios from "../../../utils/request";   // 以前的写法
import axios from "utils/request";   
  1. 图片的引用问题

最佳实践: 写静态的时候, 如果图片来自网上, 随便用网上的一张图片暂代, 等        拿到数据再使用变量代替

方式1: 支持完整路径
<img sr="https://mall.s.maizuo.com/aaa.png"/>
方式2: 使用import
import bg from 'assest/img/bg.png'
 <img src={bg} alt=""/>
  1. 渲染还可以这样写
{
	list.map(item=>(
  <ul>
  	<li>11111li>
    <li>22222li>
  ul>
  ))
}

// 类似vue的template的做法
{
	list.map(item=>( 
  <>
  	<div>11111div>
    <div>22222div> 
    
  ))
}


  1. react渲染html字符串(类似vue的v-html指令)
let htmlStr = ``

export default function() {
	return (
   <div className="pt-15 bg-fff" dangerouslySetInnerHTML={{ __html:htmlStr}}></div> 
)
}

(七) classnames

类似vue绑定class的操作

// 判断条件为true时会给div添加class类 on
div> // 实际应用 import React from 'react'; import classnames from 'classnames'; export default function() { let curr = '01'; return( <div className="demo-index">
  • 111li>
  • 222li>
  • 333li> div> ) }
  • (九) Hooks

    react hooks是什么

    1. 在函数组件中没有state(状态), 也没有生命周期
    2. react hooks是react中引入新特性,它可以让react函数组件也拥有状态
    (1) useState
    1. 在函数组件中使用useState来定义响应式数据, 接收一个参数(变量的默认值)
    2. setKeyword相当于之前的setState, 用来修改keyword的值
    import React, { useState } from 'react';
    export default function() {
        // 定义响应式数据keyword,keyword的默认值是 ''
        let [keyword,setKeyword] = useState(''); 
        return(
            <div>
                <button onClick={()=>{setKeyword('哈哈哈哈哈')}}>修改关键字</button>
                <p>
                    {keyword}
                </p> 
            </div>
        )
    }
    
    (2) useEffect
    1. 中括号内的变量发生了改变, 就会触发回调函数
    2. 请求后台接口可以放在useEffect的函数里执行, 中括号为空或者不要中括号
        let [keyword,setKeyword] = useState(''); 
        useEffect(()=> {
            console.log(2222);
          // 当keyword发生变化时,会触发回调函数
        },[keyword])
    
    (3) useHistory

    用来进行路由跳转

    (十) 路由跳转和传参

    路由跳转:

    1. 使用 <Link to="xxx" />
    2. 使用history
     - 如果是class组件, 使用this.props.history.push();
     - 函数组件则使用hooks
    import {useHistory} from 'react-router';
    let history = useHistory();
    history.push();
    
    (1) 动态路由传参
    1.  {props.match.params.id}
    // 从其他页面跳转到 /demo
    import { useHistory } from "react-router-dom";
    export default function () {
      const history = useHistory();
      const goto = () => {
        history.push("/demo/2222");
      };
      return (
        <div>
          <button onClick={goto}>动态路由button>
          <Link to="/demo/22222" />
        div>
      );
    }
    
    // 路由配置 app.js
     <Route path="/demo/:id" component={Demo} />
    
    // demo.jsx
    import React from 'react';   
    
    export default function(props) { 
        console.log(props);
        return(
            <div className="demo-index">
               动态路由参数: {props.match.params.id}
            div>
        )
    }
    
    (2) query传参(页面刷新后参数不存在)
    // 核心代码
     history.push({
          pathname: '/my',
          query:{
            username: 'zs',
            age: 100
          }
        })
    // 接收
    props.location.query;
    
    // app.js的路由配置
    <Route path="/demo" component={Demo} />
    // 其他页面
    import { useHistory } from "react-router-dom"; 
    export default function () {
      const history = useHistory();
      const goto = () => {
        history.push({
            pathname: '/demo',
            query: {
                username: '法外狂徒'
            },
            state: {
                age: 1000
            }
        });
      };
      return (
        <div>
          <button onClick={goto}>query&statebutton> 
        div>
      );
    }
    
    // 接收参数
    // query传参刷新页面就没有了,要使用&&以防报错
    import React from "react";
    export default function (props) { 
      let { query, state } = props.location;
      return (
        <div className="demo-index">
          <p> query参数: {query && query.username}p>
          <p> state参数: {state.age}p>
        div>
      );
    }
    
    
    (3) state传参(页面刷新后参数还存在)
    // 核心代码
     history.push({
          pathname: '/my',
          state:{
            username: 'zs',
            age: 100
          }
        })
    // 接收
    props.location.state;
    
    (4) search传参

    url后拼接参数, 通过props.location.serach接收, 需要处理参数

    (九) hooks

    函数组件中没有state, 也没有生命周期, hooks可以在函数组件中使用state

    (1) useState
    1. 在函数组件中使用useState来定义响应式数据, 接收一个参数(变量的默认值)
    2. setKeyword相当于之前的setState, 用来修改keyword的值
    import React, { useState } from 'react';
    export default function() {
        // 定义响应式数据keyword,keyword的默认值是 ''
        let [keyword,setKeyword] = useState(''); 
        return(
            <div>
                <button onClick={()=>{setKeyword('哈哈哈哈哈')}}>修改关键字</button>
                <p>
                    {keyword}
                </p> 
            </div>
        )
    }
    
    (2) useEffect
    1. 中括号内的变量发生了改变, 就会触发回调函数
    2. 请求后台接口可以放在useEffect的函数里执行, 中括号为空或者不要中括号
        let [keyword,setKeyword] = useState(''); 
        useEffect(()=> {
            console.log(2222);
          // 当keyword发生变化时,会触发回调函数
        },[keyword])
    
    (3) useHistory

    可以让函数组件拥有使用history的功能(跳转的时候需要)

    (十) redux

    本例gitee地址: [email protected]:huruqing/react-redux-demo.git

    新版redux,使用hooks https://react-redux.js.org/tutorials/quick-start

    (1) redux使用场景

    mobx也是用来进行跨组件通信, 比redux更简单一些
    一句话: 状态共享, 跨组件通信

    某个组件的状态,需要共享
    某个状态需要在任何地方都可以拿到
    一个组件需要改变全局状态
    一个组件需要改变另一个组件的状态
    

    (2) 核心概念

    1. **Store: **Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。

    Redux 提供createStore这个函数,用来生成 Store。

    1. **State: **状态, 存放在store里
    2. Action
      1. action是个对象, 描述当前发生的事情
      2. Action Creator: View 要发送多少种消息,就会有多少种 Action。如果都手写,会很麻烦。可以定义一个函数来生成 Action,这个函数就叫 Action Creator。
      3. 派发action: store.dispatch() 是 View 发出 Action 的唯一方法。
    3. Reducer
      1. Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。
      2. Reducer 是一个纯函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。上面的createStore接受 Reducer 作为参数,生成一个新的 Store
      3. 纯函数: 纯函数是函数式编程的概念,必须遵守以下一些约束。
        1. 特点: 相同的输入会有相同的输出
        2. 不得改写参数
        3. 不能调用系统 I/O 的API(就是输入输出)
        4. 不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果

    (3) 项目中redux步骤

    知识目录
    1. 创建store
    2. 获取状态
    3. 修改状态
    4. 模块化
    5. 持久化
    1. 安装redux和react-redux

    npm i redux react-redux

    2. 创建store和相关的东西
    1. src下新建 /redux/index.js
    2. 初始化state、声明action、声明reduer
    3. 创建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 模块化

    1. 新增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);
    
    
    1. 合并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包裹 */}
          <PersistGate persistor={persistor}>
            <App />
          </PersistGate>
        </Provider>
      </React.StrictMode>,
      document.getElementById("root")
    );
    reportWebVitals();
    

    (6) 异步action,使用redux-thunk实现

    1. 安装redux-thunk npm i redux-thunk
    2. 改造/redux/index.js
    // 核心代码如下
    //1.applyMiddleware 加载中间件
    import { createStore,applyMiddleware } from "redux";
    //2.导入异步中间件thunk
    import thunk from 'redux-thunk';
     
    const store = createStore(newReducers,applyMiddleware(thunk)); 
    
    1. 创建异步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

    https://blog.csdn.net/sinat_17775997/article/details/82772760

    它由几个部分组成:Actions、State、Computed Values、Reactions

    核心:

    在整个数据流中,通过事件驱动(UI 事件、网络请求…)触发 Actions,在 Actions 中修改了 State 中的值,这里的 State 既应用中的 store 树(存储数据),然后根据新的 State 中的数据计算出所需要的计算属性(computed values)值,最后响应(react)到 UI 视图层。

    (1) 配置

    1. 安装依赖

      npm install mobx
      
    2. package.json添加装饰器支持

      {
        "scripts": {},
        "babel": {
          "plugins": [
            [
              "@babel/plugin-proposal-decorators",
              {
                "legacy": true
              }
            ]
          ],
          "presets": [
            "react-app"
          ]
        }
      }
      

    错误: 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)

    (十二) 性能优化PureComponent和useMemo

    1. 类(class)组件性能9优化可以使用shouldCompoentUpdate进行优化
    // nextProps下一个属性(新的属性),nextState下一个状态(新的状态)   
    shouldComponentUpdate(nextProps, nextState) { 
        // 根据新的属性或者状态决定要不要更新页面
       if(xxx) {
           return true;
    	} else {
           return false
       }
    }
    
    1. 类(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;
    
    1. 函数组件可以使用React.memo进行包装以实现优化
    import React from "react";
    function Scene(props) { 
      return <div>{props.name}</div>;
    }
    export default React.memo(Scene);
    

    https://www.jianshu.com/p/b3d07860b778

    你可能感兴趣的:(react,前端,reactjs)