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 (
    <div className="app">
      <Router>
        <Routes>
          <Route path="/" element={<Redirect to="/house" />} />
          <Route path="/house" element={<Home />}>
            {/* 嵌套路由(子路由)配置 */}
            <Route path="detail" element={<Detail />} />
            <Route path="list" 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) 重定向

  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
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/events" element={<Users />} />
      <Route
        path="/dashboard"
        element={<Redirect to="/events" />}
      />
    </Routes>; 
    

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

  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>11111</li>
    <li>22222</li>
  </ul>
  ))
}

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


  1. 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 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. <Route path="/demo/:id" component={Demo} />
  2. <Link to="/demo/22222" />
  3.  {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&state</button> 
    </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地址: git@gitee.com: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包裹<App/> */}
      <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.youkuaiyun.com/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.youkuaiyun.com/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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值