帮助
支持我们

引用

在某些情况下,你需要直接引用由 Preact 渲染的 DOM 元素或组件。引用允许你执行此操作。

一个典型的用例是测量 DOM 节点的实际大小。虽然可以通过 ref 获取组件实例的引用,但我们通常不建议这样做。它将在父级和子级之间创建硬耦合,从而破坏组件模型的可组合性。在大多数情况下,直接传递回调作为 prop 比直接调用类组件的方法更自然。



createRef

createRef 函数将返回一个仅具有一个属性的普通对象:current。每当调用 render 方法时,Preact 都会将 DOM 节点或组件分配给 current

class Foo extends Component {
  ref = createRef();

  componentDidMount() {
    console.log(this.ref.current);
    // Logs: [HTMLDivElement]
  }

  render() {
    return <div ref={this.ref}>foo</div>
  }
}
在 REPL 中运行

回调引用

获取元素引用的另一种方法是传递函数回调。它需要输入更多内容,但它的工作方式与 createRef 类似。

class Foo extends Component {
  ref = null;
  setRef = (dom) => this.ref = dom;

  componentDidMount() {
    console.log(this.ref);
    // Logs: [HTMLDivElement]
  }

  render() {
    return <div ref={this.setRef}>foo</div>
  }
}
在 REPL 中运行

如果 ref 回调被定义为内联函数,它将被调用两次。一次使用 null,然后使用实际引用。这是一个常见的错误,而 createRef API 通过强制用户检查 ref.current 是否已定义,使其更容易一些。

将所有内容放在一起

假设我们有一个场景,我们需要获取 DOM 节点的引用来测量其宽度和高度。我们有一个简单的组件,我们需要用实际测量值替换占位符值。

class Foo extends Component {
  // We want to use the real width from the DOM node here
  state = {
    width: 0,
    height: 0,
  };

  render(_, { width, height }) {
    return <div>Width: {width}, Height: {height}</div>;
  }
}

只有在调用了 render 方法并且组件已装入 DOM 后,测量才有意义。在此之前,DOM 节点将不存在,尝试测量它也没有多大意义。

class Foo extends Component {
  state = {
    width: 0,
    height: 0,
  };

  ref = createRef();

  componentDidMount() {
    // For safety: Check if a ref was supplied
    if (this.ref.current) {
      const dimensions = this.ref.current.getBoundingClientRect();
      this.setState({
        width: dimensions.width,
        height: dimensions.height,
      });
    }
  }

  render(_, { width, height }) {
    return (
      <div ref={this.ref}>
        Width: {width}, Height: {height}
      </div>
    );
  }
}
在 REPL 中运行

就是这样!现在,组件在装入时将始终显示宽度和高度。