React

V17:

  • 新的渲染返回类型:碎片(数组)和字符串
  • Portals 提供了一种很好的将子节点渲染到父组件以外的 DOM 节点的方式
  • componentDidCatch(error, info)
  • 更好的服务端渲染
  • 支持自定义 DOM 属性
  • 组件(或者空的 JSX 标签)
  • new Context API // 避免层层传递
  • createRef API(以前是字符串或者回调函数)
  • forwardRef API 提供了一种拦截 ref 并将其转发为普通 prop 的方法(例子:高阶组件调用)
16.4 生命周期(为了异步渲染,fiber)
  • static getDerivedStateFromProps(nextProps, prevState) 取代之前的 componentWillMount、componentWillReceiveProps 和 componentWillUpdate
  • getSnapshotBeforeUpdate(prevProps, prevState) 的返回值会作为第三个参数传给componentDidUpdate
v16.7
  • Hooks:[userName, setUsername] = useState('’); 在函数组件中实现状态和生命周期
    // 在状态改变时,如何通知组件的?执行组件纯函数前记下该函数,在函数中就可以进行函数和状态的绑定
    // 只能用在顶层中,不能按条件调用。解释
  • useEffect 执行副作用,类似 didmount(无依赖),didupdate(执行回调再执行主体),willunmount
    // 第二个参数指定是否要依赖 state 执行副作用,默认依赖所有 state
  • useCallback 返回一个有依赖的回调
  • useReducer 类似 redux,出发一个 action 改状态 // 不是直接使用状态值
  • useMemo 返回一个有依赖的值
  • useRef 返回一个引用值
v15.3
  • PureComponent shouldComponentUpdate 使用浅比较


React 是通过 render 生成的对象比较进行更新,所以使用 classList 添加的类名在下一次渲染的时候 react 认为没有变化。

React 推崇 HOC 和组合的方式,而不是继承的方式来扩展组件

绝对不要直接改变 this.state,因为在之后调用 setState() 可能会替换掉你做的更改。把 this.state 当做不可变的。
不保证 setState() 调用的同步性,为了提升性能,可能会批量执行 state 转变和 DOM 渲染。// https://stackoverflow.com/questions/48563650/does-react-keep-the-order-for-state-updates/48610973#48610973
setState(updater[, callback])(与现有state合并)将总是触发一次 render,除非在 shouldComponentUpdate() 中实现了条件渲染逻辑。

Input 受限控件直接设置值就可以更改 value,而 textarea 需要使用 setState 才能更改,且值为 undefined 也会显示上次的值,应该改为 ''

设置不存在属性用null值,比如表单元素的 checked 为 null 时不会默认选择,且能直接更改选择状态。
(react的表单value和checked属性使DOM元素该属性不能更改)
React.Component API
在 ES6 中,一般选择 extends 一个 Component 对象,ES5 而是 createClass
所以在 ES6 中,一个已存在的 Component 可以被多次 extends
坑:回调函数试着写在最后扩展组件身上,因为写在中间组件的回调函数中的this并不指向最终组件。然而props会被中间组件重写所以props中的this指向没有问题。
通过es6类的继承实现时 state 的初始化要在 constructor 中声明
在DOM事件处理函数中,其 this 没有指向React组件实例(而是null),可以通过在构造函数中使用 bind 来改变


react 渲染动态子组件时需要写个唯一 key 的 props

React使用JSX语法,需要在线转换或者build转换,也可以直接用js语法编写
JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。

ReactDOM.render 是 React 的最基本方法,用于将模板(单子级)转为 HTML 语言,并插入指定的 DOM 节点。(即2个参数)

执行函数返回的结果是 render 的模板

模板中出现的数组,JSX 会把它的所有成员,添加到模板。

先通过 React.createClass 封装(像自定义元素)成组件,再像普通HTML标签一样插入,React.createClass 有一个render方法返回HTML模板,还可以有一些其他的方法和属性

this.props 对象的属性与组件的属性一一对应。
但是this.props.children代表的是它的所有子节点,然而this.props.children的返回可能是undefined、object、Array,所以需要用React.Children来方便处理

有时,我们需要一种机制,验证别人使用组件时,提供的参数(用于属性)是否符合要求。组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求

getDefaultProps 方法用来设置属性默认值(ES5)
值得注意的是,props中任何引用类型的值(如数组,对象),都会在所有实例中共享,而不是每个组件实例拥有单独的副本,所以不要在组件实例中去修改 props,把它当成只读的数据最好。

refs是具有ref属性的组件实例集合,this.refs.myInput.getDOMNode()或者React.findDOMNode(this.refs.table)获取
ref也可以是一个回调函数,渲染的时候立即执行,并穿入该React组件/DOM作为参数。

React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI,状态集合属性 state,getInitialState 用于初始状态,setState 设置状态。像表单等互动应该用state(属性要预定义),不能用 props(不能更改)属性


组件的生命周期分成三个状态:

  • Mounting:已插入真实 DOM。2个处理函数。如componentWillMount(),服务器端和客户端都只调用一次,在初始化渲染执行之前立刻调用,在里面setState也只在感知更新后执行一次。
  • Updating:React组件重新渲染前后。2个处理函数,初始化时不会调用
  • Unmounting:已移出真实 DOM。1个处理函数
所以同步数据在外部调用组件函数setState或者在首次插入组件的时候绑定事件来setState(addEventLisen原理)
forceUpdate() 改变组件以外的数据时更新组件

还有两个特殊处理函数:componentWillReceiveProps 已加载组件收到新的props时调用
shouldComponentUpdate 组件判断是否重新渲染时调用。属性、状态更改时组件将重新渲染。如果确定新的 props 和 state 不会导致组件更新,则此处应该 返回 false。// 优化

React 组件样式是一个对象,所以内联样式应该style={{opacity: this.state.opacity}}

表单是受控组件:在 HTML 当中,表单元素会维持自身状态,并根据用户输入进行更新,在 React 中则仍然是 prop(onChange 触发修改) 来更新

// 多次 render 时会导致部分输入法直接上屏