{"id":19020354,"url":"https://github.com/ambar/react-element","last_synced_at":"2025-07-03T19:07:38.393Z","repository":{"id":15866710,"uuid":"78847990","full_name":"ambar/react-element","owner":"ambar","description":null,"archived":false,"fork":false,"pushed_at":"2023-01-24T17:52:36.000Z","size":1869,"stargazers_count":2,"open_issues_count":13,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-27T11:06:59.461Z","etag":null,"topics":["cloneelement","createelement","react"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ambar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-13T12:37:10.000Z","updated_at":"2021-01-20T01:32:04.000Z","dependencies_parsed_at":"2023-02-14T00:01:02.584Z","dependency_job_id":null,"html_url":"https://github.com/ambar/react-element","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/ambar/react-element","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ambar%2Freact-element","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ambar%2Freact-element/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ambar%2Freact-element/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ambar%2Freact-element/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ambar","download_url":"https://codeload.github.com/ambar/react-element/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ambar%2Freact-element/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263097259,"owners_count":23413535,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloneelement","createelement","react"],"created_at":"2024-11-08T20:16:57.044Z","updated_at":"2025-07-03T19:07:38.362Z","avatar_url":"https://github.com/ambar.png","language":"JavaScript","readme":"# 元素替换\n\n合并 createElement 与 cloneElement 的使用 😉\n\n[![build status](https://badgen.net/travis/ambar/react-element)](https://travis-ci.org/ambar/react-element)\n[![npm version](https://badgen.net/npm/v/react-element)](https://www.npmjs.com/package/react-element)\n[![minzipped size](https://badgen.net/bundlephobia/minzip/react-element)](https://bundlephobia.com/result?p=react-element)\n\n\n## 基本用法\n\n```js\nimport Element from 'react-element'\n\n// 标签替换\n\u003cElement component='span'\u003etext\u003c/Element\u003e\n// 构造函数替换\n\u003cElement component={Header}\u003etext\u003c/Element\u003e\n// 实例替换\n\u003cElement component={\u003cLink to='/' /\u003e}\u003etext\u003c/Element\u003e\n```\n\n## 其他用例\n\n### 一、防止意外属性传递到 DOM 元素\n\n如防止 `to` 在条件不成立时到传递到 `div` 标签上：\n\n```js\n\u003cElement\n  className={styles.content}\n  component={purchased ? \u003cLink to={`/${live.id}`} /\u003e : 'div'}\n\u003e\n  Live\n\u003c/Element\u003e\n```\n\n### 二、多个组件共用相同 DOM 元素\n\n如一个组件有 Item \u003e ItemInner 两层结构，Item + Item 有并列样式，ItemInner 有 `padding`，需要替换外层的元素为链接时。\n\n```js\n// 一种组件两种特性\n\u003cListItem component={Link} /\u003e // =\u003e \u003ca class={ListItem}\u003e\u003cdiv class={ListItemContent}\u003e...\u003c/\n// 夸张的\n\u003cListItem component={\u003cCard component={Link} /\u003e} /\u003e\n// 好玩的\n\u003cElement component={\u003cElement component={\u003cElement component={\u003cElement component='span' /\u003e} /\u003e} /\u003e}\u003e\n```\n\n### 三、生成容器而不生成 DOM 元素\n\n如实现一个能触发弹层的组件，使它能包装在一个按钮上使用：\n\n```js\n// 定义 Tooltip\nconst Tooltip = ({children: child}) =\u003e (\n  \u003cElement component={child}\u003e\n    {child.props.children}\n    \u003cPopup /\u003e\n  \u003c/Element\u003e\n)\n\n// 使用 Tooltip\n\u003cTooltip\u003e\n  \u003cButton /\u003e\n\u003c/Tooltip\u003e\n```\n\n### 四、自动传播事件\n\n后定义属性覆盖先定义的（class 会始终连接起来），先定义的处理函数先执行：\n\n```js\n// 实现方：定义一个切换组件（比「三」更通用的实现）：\nconst \u003cToggle\u003e = ({popup, children: child}) =\u003e (\n  ...\n  \u003cElement\n    component={child}\n    onClick={handleClick} // 自动传播的 onClick\n  \u003e\n    {child.props.children}\n    \u003cElement\n      component={popup}\n      isOpen={isOpen} // 覆盖的属性，控制了 popup 显示\n      onOpen={handleOpen} // 自动传播的 onOpen\n    /\u003e\n  \u003c/Element\u003e\n)\n\n// 调用方：无论内外（调用方或实现方），属性都会传递，事件都会触发\n\u003cToggle popup={\u003cTooltip placement='top' onOpen={} /\u003e}\u003e\n  \u003cButton ghost onClick={} /\u003e // 先执行的 onClick\n\u003c/Toggle\u003e\n```\n\n## FAQ\n\n**`ref` 处理**\n\n```js\n// 原生标签使用 `onRef` 获取元素引用\n\u003cElement component='span' onRef={el =\u003e ...} /\u003e\n// 构造函数和实例也能自动传递 `onRef` —— Element 会传递任意的 `on***` handler\n\u003cElement component={MyComponent} onRef={handleRef} /\u003e\n```\n\n**`component={null}` 的含义是什么？**\n\n返回 children，不生成容器元素：\n\n```js\n\u003cElement component={null}\u003e\n  \u003cspan\u003espan\u003c/span\u003e\n\u003c/Element\u003e\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fambar%2Freact-element","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fambar%2Freact-element","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fambar%2Freact-element/lists"}