React

官方文档

Redux


技能图谱

React
├ Create React App
├ React Router // react-router-dom
├ Redux
├ Mobx 
├ hooks
├ fetch
└ proxyTrack

React 有哪些缺点

要使用 useCallback 处理那些我们本来就不需要关注的问题。

React hooks 天生就会浪费性能,而官方也说,每个简单的 obj/arr/func 使用 useMemo 和 useCallback 会浪费大量时间。

生命周期

image

未整理

  • 分析 React 组件的渲染性能
  • React
  • 图解React原理
  • 性能优化
  • 第三方协同
  • 高阶组件
  • React测试
  • Concurrent 模式
  • eslint-plugin-react-hooks
    1. 应用中所有的状态都是以一个对象树的形式存储在一个单一的store中;
    2. 当你想要改变应用的中的状态时,你就要dispatch一个action,这也是唯一的改变state的方法;
    3. 通过编写reducer来维护状态,返回新的state,不直接修改原来数据;
  • UI 组件交互操作; 调用 model 的 effect; 调用统一管理的 service 请求函数; 使用封装的 request.js 发送请求; 获取服务端返回; 然后调用 reducer 改变 state; 更新 model

API

Redux

Hooks

Demo

React

脚手架

使用脚手架(Toolchains): create-react-app

npx create-react-app react-typescript-mobx --typescript
cd react-typescript-mobx
npm start

默认入口文件 /src/index.js

基本用法

var HelloWorld = React.createElement(
    'div',
    {
        className: 'shopping-list'
    },
    'Hello world!'
)

// 使用
ReactDOM.render(
  HelloWorld,
  document.getElementById('root')
);

// 或者
class App extend React.Component {
    constructor() {
        super();
        this.state = {
            value: null,
        };
    }
    render() {
        return (
            <h1>{this.props.title}</h1>
        )
    }
}

// 函数组件
function Test() {
    return (
        <p>Hello world!</p>
    );
}

// 使用
ReactDOM.render(
  <App /><Test />,
  document.getElementById('root')
);

JSX 的大括弧中可以写任意表达式

class -> className
tabindex -> tabIndex
有状态组件

根据我们已有的知识,更新 UI 唯一的方式是创建一个全新的元素,并将其传入 ReactDOM.render()。在实践中,大多数 React 应用只会调用一次 ReactDOM.render()。在下一个章节,我们将学习如何将这些代码封装到有状态组件中。

state 的更新可能是异步的。出于性能考虑,React 可能会把多个 setState() 调用合并成一个调用。因为 this.props 和 this.state 可能会异步更新,所以你不要依赖他们的值来更新下一个状态。

受控组件 & 非受控组件

绑定事件

onClick={this.handleClick}  // 传入函数名,不带 ()
绑定 this
  1. 在构造函数中
this.handleClick = this.handleClick.bind(this)
  1. 实验性功能: public class fields 语法
handleClick = () => {}
  1. 调用时使用闭包
onClick={()=>this.handleClick()}
传参
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

注意

key 不会传递给组件,props.key读不到,必须换名字。

如果一个map() 嵌套太多,就需要提取组件。

待梳理

textarea 使用 value 属性

select 使用 value 属性,value 支持数组

非受控组件?

在受控组件上指定 value 的属性可以防止用户更改输入?

Formik

数据请求 https://blog.csdn.net/ZYC88888/article/details/82531610

v16 以后不再使用 React.createClass()

ref={node => {a = node}}

React Router

npm install --save react-router-dom

所有组件都需要引入 react-router-dom

// 使用 ES6 的转译器,如 babel
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';

// 不使用 ES6 的转译器
var BrowserRouter = require('react-router');
var Router = BrowserRouter.Router;
var Route = BrowserRouter.Route;
var Link = BrowserRouter.Link;
  • BrowerRouter & HashRouter

使用Router

function RouterTest() {
  return (
    <Router>
      <div>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
        <Link to="/topics">Topics</Link>
        <hr />
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/topics" component={Topics} />
      </div>
    </Router>
  );
}

// 然后 render <RouterTest />
  • Route 匹配 path 属性和当前 pathname,匹配就会 render component,不匹配 render null。如果 Route 不写 path 就可以匹配任何 pathname。

  • Switch 可以将 Route 归成一组,只 render 组内第一个匹配的元素。这样就可以把一个 404 放在组内最后一个。

  • NavLink 可以给匹配的路径设置 class,如下

<NavLink to="/foo" activeClassName="bar">Hello</NavLink>
  • 还可以使用 <Redirect to="" /> 跳转

不使用JSX(旧版?)

const routes = {
  path: '/',
  component: App,
  childRoutes: [
    { path: 'about', component: About },
    { path: 'inbox', component: Inbox },
  ]
}

React.render(<Router routes={routes} />, document.body)

获取URL,在组件传入参数 {match}

function Com({ match }) {
    console.log(match)
}

如果是类定义组件?不会实时更新?
match: {
    isExact: true,
    params: {},
    path: '/test/:id',  // Route 组件的 path 属性,使用:开始
    url: 'test/foo'  // 匹配到的 URL
}

Route Rendering Props

<Route
    path=""
    render={props => <About {...props} extra={someVariable} />}
/>

Flux

Redux

npm install redux

Reducer

combineReducers()

Store

getSate()
dispatch(action)
subscribe(listener)
subscribe()

createStore()

React Redux

npm install react-redux
npm install --save-dev redux-devtools

创建 reducers

import { combineReducers } from 'redux'
import todos from './todos'
import visibilityFilter from './visibilityFilter'

const todoApp = combineReducers({
  todos,
  visibilityFilter
})

export default todoApp

使用 Provider 将 store 提供给 React 子组件

import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers/index'
import App from './components/App'

const store = createStore(todoApp, {})

render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('root')
)

使用 connect() 将 state 和 action 与 React 组件连接起来

useEffect

影响函数组件作用域之外的。

React首次渲染和之后的每次渲染都会调用一遍useEffect函数,而之前我们要用两个生命周期函数分别表示首次渲染(componentDidMonut)和更新导致的重新渲染(componentDidUpdate)。

useEffect中定义的函数的执行不会阻碍浏览器更新视图,也就是说这些函数时异步执行的,而componentDidMonut和componentDidUpdate中的代码都是同步执行的。个人认为这个有好处也有坏处吧,比如我们要根据页面的大小,然后绘制当前弹出窗口的大小,如果时异步的就不好操作了。

Tips

相关文档

总结

React.CSSProperties

// mobx 追踪的是属性访问  而不是value

reactDOM.render 不一定是同步的
使用create react app部署生产目录?

修改 config 文件夹下面的 paths.js。

一个很好的React+Mobx的例子 https://www.jianshu.com/p/3d4e85f60141

Create React App v2 配置高级代理:

使用导航守卫(如用户权限判断):

事件

<button onClick={activateLasers}>
  Activate Lasers
</button>

// 阻止默认行为
e.preventDefault();
向事件处理程序传递参数

在循环中,通常我们会为事件处理函数传递额外的参数。例如,若 id 是你要删除那一行的 ID,以下两种方式都可以向事件处理函数传递参数:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

上述两种方式是等价的,分别通过箭头函数和 Function.prototype.bind 来实现。

在这两种情况下,React 的事件对象 e 会被作为第二个参数传递。如果通过箭头函数的方式,事件对象必须显式的进行传递,而通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。


react 和 vue 区别

props是可以动态变化的,子组件也实时更新,在react中官方建议props要像纯函数那样,输入输出一致对应,而且不太建议通过props来更改视图;

Vue与React的区别

vue组件分为全局注册和局部注册,在react中都是通过import相应组件,然后模版中引用; props是可以动态变化的,子组件也实时更新,在react中官方建议props要像纯函数那样,输入输出一致对应,而且不太建议通过props来更改视图; 子组件一般要显示地调用props选项来声明它期待获得的数据。而在react中不必需,另两者都有props校验机制; 每个Vue实例都实现了事件接口,方便父子组件通信,小型项目中不需要引入状态管理机制,而react必需自己实现; 使用插槽分发内容,使得可以混合父组件的内容与子组件自己的模板; 多了指令系统,让模版可以实现更丰富的功能,而React只能使用JSX语法; Vue增加的语法糖computed和watch,而在React中需要自己写一套逻辑来实现; react的思路是all in js,通过js来生成html,所以设计了jsx,还有通过js来操作css,社区的styled-component、jss等;而 vue是把html,css,js组合到一起,用各自的处理方式,vue有单文件组件,可以把html、css、js写到一个文件中,html提供了模板引擎来处理。 react做的事情很少,很多都交给社区去做,vue很多东西都是内置的,写起来确实方便一些, 比如 redux的combineReducer就对应vuex的modules, 比如reselect就对应vuex的getter和vue组件的computed, vuex的mutation是直接改变的原始数据,而redux的reducer是返回一个全新的state,所以redux结合immutable来优化性能,vue不需要。 react是整体的思路的就是函数式,所以推崇纯组件,数据不可变,单向数据流,当然需要双向的地方也可以做到,比如结合redux-form,组件的横向拆分一般是通过高阶组件。而vue是数据可变的,双向绑定,声明式的写法,vue组件的横向拆分很多情况下用mixin。

更新时间:2025-03-13 13:36:30