@adobe/react-webcomponent

中文文档
0.1.3发布于 2020/05/07Apache-2.0CommonJS零依赖近 30 天下载 6304

该项目旨在连接反应组件和自定义元素之间的联系。 库所采取的策略是创建一个模型,定义DOM如何被翻译为React道具.

中文使用文档
文档目录3 节
  1. 安装库
  2. 定义自定义元素
  3. DOM 模式

反应网络组件

该项目旨在连接反应组件和自定义元素之间的联系. 库所采取的策略是创建一个模型,定义DOM如何被翻译为React道具.

由于目标是支持作为自定义元素的 React 组件, 我们并不支持从段落, 选择等已建元素扩展 .

它支持:

  • 当属性被更改时自动更新 React 组件
  • 支持自动登记和触发事件
  • 支持多重渲染目标,自定义元素本身,容器分录或阴影根.
  • 允许解析和更新 DOM 的嵌入式结构,例如:
    <select>
        <option value="something">Else</option>
        <option value="certain">Value</option>
    </select>

这种DOM结构可以被转化为模型并自动注入回放组件. 你可以变身 任意 DOM结构为模式,将传递给反应组件. 这使得您可以使用大多数 DOM api 并封装 React 作为执行细节.

安装库

npm install @adobe/react-webcomponent

如果你在使用 Babel 6 : 因为我们的目标是自定义元素V1 我们用巴贝尔来转换我们的代码 即时操作自定义元素会有问题. 见 这个问题 讨论. 包含 自定义元素- es5- 适应器 在你装上这个librabry来解决这个问题之前.

你是在用"Babel"7号吗? 问题已经解决了 所以你不需要别的了.

我们正在使用类属性和装饰器,以确保您包括 appropiat bail 插件来使用这个.

定义自定义元素

首先需要的是一个反应组件,作为自定义元素曝光

import React, { Component } from 'react';

import { createCustomElement, DOMModel, byContentVal, byAttrVal, registerEvent } from "@adobe/react-webcomponent";

class ReactButton extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (<div>
            <button weight={ this.props.weight }>{ this.props.label }</button>
            <p>Text</p>
        </div>)
    }
}

然后,您需要创建一个模型来定义 DOM 如何解析成反应属性 .

class ButtonModel extends DOMModel {
    @byContentVal text = "something";
    @byAttrVal weight;
    @registerEvent("change") change;
}

您创建自定义元素

const ButtonCustomElement = createCustomElement(ReactButton, ButtonModel, "container");

然后注册

window.customElements.define("test-button", ButtonCustomElement);

确定反应部分将在哪里提供

在定义自定义元素时,您可以通过指定 renderRoot 属性. 可能的价值是:

  • 集装箱
    这将在自定义元素内产生额外的 div , 反应组件将在那里提供 .   这样做是有用的,因为React会移除它所制成的容器元件的所有儿童.
    所以,如果您想要从自定义元素的标记中解析值并修改它们,则元素会在初始渲染后丢失.
    例如:
<my-button>
  <my-button-label>My Button</my-button-label>
</my-button>

如果我们不在一个容器里做 my-button-label 元素会在渲染时被 React 移除 .

  • 阴影旋转
    这将决定自定义元素"影子"的创建,并将在其中提供"反应"组件

  • 元素
    React 组件将在自定义元素中直接渲染出.

扩展自定义元素

默认情况下, 我们提供创建自定义元素的功能 createCustomElement。此选项包含默认行为,但不允许元素扩展.
这可以被绕过,而自定义Element可以以新的能力来扩展.

import { CustomElement } from "@adobe/react-webcomponent";

class ButtonCustomElement extends CustomElement {
    constructor() {
        super();
        this._custom = 3;
    }
    get custom() {
        return this._custom;
    }

    set custom(value) {
        this._custom = value;
    }
};
ButtonCustomElement.observedAttributes = Model.prototype.attributes;
ButtonCustomElement.domModel = Model;
ButtonCustomElement.ReactComponent = ReactComponent;
ButtonCustomElement.renderRoot = "container"; // optional, defaults to "element"
window.customElements.define("test-button", ButtonCustomElement);

DOM 模式

从将一个 DOM 节点转换为模型,这种功能是可逆的. 该型号由一系列专业的装饰师来装饰. 每个装饰者将解析圆顶并构建模型:

校对:Soup.

解析元素并设置与元素属性值对应的值

@byAttrVal(attrName:string) - defaults to the name of the property that it decorates.
class Model extends DOMModel {
    @byAttrVal() weight;
    @byAttrVal("custom-attribute-name") reactPropName;
}

用法 :

<div id="elem" weight="3" custom-attribute-name="some value"/>
const model = new Model().fromDOM(document.getElementById("elem"));
model ~ {
    weight: "3",
    reactPropName: "some value"
}

由 Boolean AttrVal 编辑

解析元素,并设定元素上属性存在的对应值.
属性的值被忽略,只有属性的存在决定了值

@byBooleanAttrVal(attrName:string) - defaults to the name of the property it decorates
class Model extends DOMModel {
    @byBooleanAttrVal() checked;
    @byBooleanAttrVal("is-required") required;
}

用法 :

<div id="elem" checked/>
const model = new Model().fromDOM(document.getElementById("elem"));
model ~ {
    checked: true,
    required: undefined
}
<div id="elem" checked is-required/>
model.fromDOM(document.getElementById("elem"));
model ~ {
    checked: true,
    required: true
}

由 JsonAttrVal 编辑

通过使用 JSON.parse。 。 。 .

class Model extends DOMModel {
    @byJsonAttrVal() obj;
    @byJsonAttrVal("alias-attr") anotherObj;
}

<div id="elem" obj='[{"example":1},{"test":2}]' alias-attr='[{"other":"example},{"test":3}]'/>
const model = new Model().fromDOM(document.getElementById("elem"));
model ~ {
    obj: [{"example":1},{"test":2}],
    anotherObj: [{"other":"example},{"test":3}]
}

ưμ㼯A

解析元素并设定值到 innerText ,该元素.

class Model extends DOMModel {
    @byContentVal() label;
}
<div id="elem">My Label</div>
const model = new Model().fromDOM(document.getElementById("elem"));
model ~ {
    label: "My Label"
}

按内容

此装饰器允许您捕获一个由 CSS 选择器匹配的 DOM 节点 . 这可用于再现儿童专断的DOM内容,可能不是 与 React 一起转换,输入您的网页组件。 一旦解析完成, 字段 在模型中将包含一个反应组件,代表 DOM 内容 将重新做父母.

当 React 组件被挂起时会移动 DOM 内容 。 还有,内容 如果反应组件后来被卸载,则将被放回原位置.

@byContent(attrName:selector) - the CSS selector that will match the child node.
class Model extends DOMModel {
    @byContent('.content') content;
}
<div id="elem">
    <div class="content">
        This will be reparented
    </div>
</div>
<div id="mount-point"/>

const model = new Model().fromDOM(document.getElementById("elem"));
ReactDOM.render(<div>{ model.content }</div>, document.getElementById("mount-point"))

// Once React has rendered the above component, the DOM will look like this

<div id="elem">
    <!-- placeholder for DIV -->
</div>
<div id="mount-point">
    <div class="content">
        This will be reparented
    </div>
</div>

按儿童状况分类

分析元素寻找匹配给定选择器并设定值的元素 innerText 内容

class Model extends DOMModel {
    @byChildContentVal("custom-label") label;
}
<div id="elem"><custom-label>My Label</custom-label></div>
const model = new Model().fromDOM(document.getElementById("elem"));
model ~ {
    label: "My Label"
}

按儿童参考资料

解析元素并寻找一个匹配给定选择器的子元素, 并设定以给定模型解析子元素的结果值

class CustomLabelModel extends DOMModel {
    @byContentVal() value;
    @byAttrVal() required;
}
class Model extends DOMModel {
    @byChildContentVal("custom-label", CustomLabelModel) label;
}

<div id="elem"><custom-label required>My Label</custom-label></div>
const model = new Model().fromDOM(document.getElementById("elem"));
model ~ {
    label: {
        value: "My Label",
        required: true
    }
}

按模式

指定在元素上运行一个给定模型的值. 这使得元素模型可以保存在不同的属性上而不是直接保存在模型上.

class CustomModel extends DOMModel {
    @byContentVal() value;
    @byAttrVal() required;
}

class Model extends DOMModel {
    @byModelVal() item;
}

<div id="elem" required>Content</div>
const model = new Model().fromDOM(document.getElementById("elem"));
model ~ {
    item: {
        value: "Content",
        required: true
    }
}

按“儿童模式”

通过从自定义 elem 中获取模型值来解析元素并设定值. 此属性仅在有自定义元素解析时返回 .

使用开头定义的按钮 :

window.customElements.define("test-button", ButtonCustomElement);

我们定义一个模型

class Model extends DOMModel {
    @byChildModelVal("test-button") button;
}

<div><test-button weight="3">Click me</test-button></div>
const model = new Model().fromDOM(document.getElementById("elem"));
model ~ {
    button: {
        weight: 3,
        text: "Click me"
    }
}

这里的根本区别在于模型在另一个自定义元素中被定义,并在这个模型中被再用. 所以它不会被重新定义.

儿童参考文件

解析元素子并选择所有匹配所提供选择器的元素.
对于每个元素,它使用被引用的模型来解析元素的值.
由此而来的所有数值阵列被存储为被装饰的地产上的价值.

class OptionModel extends DOMModel {
    @byContentVal() content;
    @byAttrVal() value;
    @byBooleanAttrVal() selected;
}

class SelectModel extends DOMModel {
    @byChildrenRefArray("option", OptionModel) options;
}

<select id="elem">
    <option value="1">Amsterdam</option>
    <option value="2">Berlin</option>
    <option value="3">London</option>
</select>
const model = new Model().fromDOM(document.getElementById("elem"));
model ~ {
    options: [{value: 1, content: "Amsterdam"}, {value: 2, content: "Berlin"}, {value: 3, content: "London"}]
}

由儿童Type阵列

如果节点Name与所提供地图中的节点相匹配, 则该节点将对该孩子进行相应的模型分析 .

class Child1Model extends DOMModel {
    @byAttrVal() checked;
}

class Child2Model extends DOMModel {
    @byAttrVal() selected;
}

class Model extends DOMModel {
    @byChildrenTypeArray({
        "child-one": Child1Model,
        "child-two": Child2Model
    }) items;
}

<div id="elem">
    <child-one checked/>
    <child-two selected/>
</div>
const model = new Model().fromDOM(document.getElementById("elem"));
model ~ {
    items: [{checked: true}, {selected: true}]
}

注册事件

注册要注册在 React 组件上的事件, 当它被称作自定义 Event 时, 将会在自定义元素上被触发 . 事件名称会自动转换成骆驼 Case , 并用 on 这种行为发生在自定义元素而不是DOM模型上,DOM模型只登记事件

class Model extends DOMModel {
    @registerEvent("change") change;
}

最终将转换为自定义元素 a onChange 属性.

版本与发布记录

@adobe/react-webcomponent 共发布 4 个版本,首次发布于 2018/11/23;过去 12 个月发布了 0 个版本。

版本发布日期距今
0.1.3latest2020/05/076 年前
0.1.22019/03/267 年前
0.1.12018/12/197 年前
0.1.02018/11/237 年前

关于 @adobe/react-webcomponent 的常见问题

@adobe/react-webcomponent 是什么?

该项目旨在连接反应组件和自定义元素之间的联系。 库所采取的策略是创建一个模型,定义DOM如何被翻译为React道具.

如何安装 @adobe/react-webcomponent?

在项目目录运行 npm install @adobe/react-webcomponent,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=14.2.0)、react-dom(>=14.2.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@adobe/react-webcomponent 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/adobe__react-webcomponent 是否存在。

@adobe/react-webcomponent 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@adobe/react-webcomponent 可以商用吗?

@adobe/react-webcomponent 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@adobe/react-webcomponent 的下载量有多少?

根据 npm 官方下载统计,@adobe/react-webcomponent 在 2026/10/05 – 2026/11/03 这 30 天内被下载 6,304 次,日均约 210 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@adobe/react-webcomponent 还在维护吗?

最新版本 0.1.3 发布于 2020/05/07(6 年前);至今共发布 4 个版本,其中过去 12 个月发布了 0 个;首次发布于 2018/11/23。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。