在 JSX 中呈现 <img attribute={false} />

Rendering <img attribute={false} /> in JSX

我有一个模板组件可以接受 "draggable" 道具,我想在应用时将这个道具的值传递给子 img 标签。

  render() {
    // this.el = Host Element
    // this.loadSrc = Image URL as String
    // draggable has to be type 'boolean | undefined'

    const shouldBeDraggable = (this.el.hasAttribute('draggable') ? this.el.draggable : undefined);

    console.log("render -> shouldBeDraggable", shouldBeDraggable); // Logs Correct Value

    return (
      <Host>
        <img
          src={this.loadSrc}
          draggable={shouldBeDraggable}
        />
      </Host>
    );
  }

它仅在宿主属性值为真时呈现 draggable="true",但在宿主属性值为假时不呈现 draggable="false"

另一个简化的示例;

 render() {
    // this.loadSrc = Image URL as String
    // draggable has to be type 'boolean | undefined'
    return (
      <Host>
        <img src={this.loadSrc} draggable={false} />
      </Host>
    );
  }

不幸的是,img.draggable 属性的类型是布尔值。 (JSX 属性)JSXBase.HTMLAttributes.draggable?: 布尔值 |未定义

作为字符串传递;

 render() {
    // this.loadSrc = Image URL as String
    // draggable has to be type 'boolean | undefined'
    return (
      <Host>
        <img src={this.loadSrc} draggable={"false" as any} />
      </Host>
    );
  }

这确实将 draggable="true" 渲染到 img 标签,因为 "false" 字符串变为真布尔值,不渲染。


如何成功将 draggable 属性的 falsy 情况传递给子 img 标签?

undefined替换为false:

const shouldBeDraggable = (this.el.hasAttribute('draggable') ? this.el.draggable : false);

但是既然你想传递truefalse,你可以定义:

const shouldBeDraggable = this.el.hasAttribute('draggable') // true or false

进一步,设置一个class并使用样式:

<img
  src={this.loadSrc}
  draggable={shouldBeDraggable}
  className={shouldBeDraggable ? 'draggable' : 'no-draggable'}
/>

.no-draggable {
  pointer-events: none;
}

或者,使用风格:user-drag:none; user-select:none;任何适合你的风格。

要了解此行为,您必须了解无值属性在 HTML 中的工作原理。虽然没有太多这样的属性,但想象一下(例如)disabled 属性:

<input disabled />

注意不是:

<input disabled="true" />

同样,常规 enabled input 不是:

<input disabled="false" />

...只是:

<input />

但是在 React 中,您可能希望使用 Javascript 布尔值来控制 disabled 属性是否存在。这一点,当你给一个属性一个布尔值时,React 模拟 HTML 包含或不包含该属性的行为,允许你做:

<input disabled={aBoolean} />

尽管 HTML 并非如此。因此,如果您这样做:

draggable={false}

你告诉 JSX 不要 添加 HTML 属性。

现在奇怪的是 draggable 不是 正常的无值属性,所以它 确实 期望你实际上说,在 HTML, draggable="false".

如果您想要实际的字符串 "true" 和 "false",一个简单的解决方法(未经测试)是使用三元组:

draggable={aBoolean ? 'true' : 'false'}

这在提出问题时是不可能的,因为当在模板中呈现 draggable={false} 时,它不会传递 draggable 属性,以便浏览器将缺少的属性评估为 false。当浏览器实际上默认为 true 时,这仅对某些元素如 <img> 标签的可拖动是错误的。


但是,此行为随此更新而改变; 0d72aee

在 Stencil 1.15.0-1 和更新版本上;

<img src="http://place-hold.it/200" alt="Placeholder" draggable={false} />

呈现为;

<img src="http://place-hold.it/200" alt="Placeholder" draggable="false" />