React

Ref

useRef还是useState

当一条信息用于渲染时,将它保存在 state 中。当一条信息仅被事件处理器需要,并且更改它不需要重新渲染时,使用 ref 可能会更高效。

import { useState, useRef } from 'react';

export default function Stopwatch() {
  const [startTime, setStartTime] = useState(null);
  const [now, setNow] = useState(null);
  const intervalRef = useRef(null);

  function handleStart() {
    setStartTime(Date.now());
    setNow(Date.now());

    clearInterval(intervalRef.current);
    intervalRef.current = setInterval(() => {
      setNow(Date.now());
    }, 10);
  }

  function handleStop() {
    clearInterval(intervalRef.current);
  }

  let secondsPassed = 0;
  if (startTime != null && now != null) {
    secondsPassed = (now - startTime) / 1000;
  }

  return (
    <>
      <h1>时间过去了: {secondsPassed.toFixed(3)}</h1>
      <button onClick={handleStart}>
        开始
      </button>
      <button onClick={handleStop}>
        停止
      </button>
    </>
  );
}
  • 正常情况下, 我们可能会使用var timeFlag = xxx, 这里绕一圈起到了什么作用?
  • 在类定义组件里, 对应的语法是createRef

useRef保存DOM元素

const myRef = useRef(null); // 定义, 返回一个有current属性的对象
<div ref={myRef} /> // 赋值, 把DOM元素赋值给current属性
console.log(myRef.current); // 访问DOM元素

原始用法(当成id使用), 再从this.refs里用id取出来:

<input ref="myRef" onClick="handleClick" />
function handleClick() {
  console.log(this.refs.myRef.value);
}

已过时, 不建议用这个API, 除了userRef, 还有一种回调的写法

<input ref={input => this.myRef = input} onClick={this.handleClick} />
handleClick() {
  console.log(this.myRef.value);
}
  • 首先, ref给了一个回调, 你可以log一下, 它送入的就是当前的DOM元素
  • 其次, 你可以在回调里做任何你想做的事, 比如保存到this
  • 看上去这里跟useRef的作用是一样的, 仅仅是改变了定义的位置, 一个先定义, 在dom标签里就很简洁了
    • 但是它不是userRef, 因为它存的是DOM, 而不是一个带current的对象

解构赋值的连续写法:

const {current:{value}} = this.myRef
console.log(value);

等同于this.myRef.current.value

但是中间过程的变量是不可以用的, 只能用最后一层的变量:

var {a:{b:{c:{d}}}} = {"a":{"b":{"c":{"d":333}}}}

只是把d解出来了

解构赋值时重命名:

var {a:{b:data}} = {"a":{"b":123}}
console.log(data); // 123

注意, 如果把data写成{data}, 那么就是在取b下一级的datan属性, 而不是在重命名了, 当然这一节, 纯装逼, 直接用点语法取值再赋值没一点问题.