innerHTML易出错、document.createElement繁琐,能否用类JSX方式定义Web Component?
问题:是否存在类JSX的方式定义Web Component的HTML内容?
用innerHTML字符串定义Web Component的HTML内容极易出错,而document.createElement的写法又十分繁琐。想找一种类JSX的写法来替代原生的字符串拼接方式。
原有的innerHTML字符串写法:
class Foo extends HTMLElement { constructor() { super(); } connectedCallback() { this.innerHTML = `<p>foo</p>`; } }
期望的类JSX写法(无需字符串包裹):
class Foo extends HTMLElement { constructor() { super(); } connectedCallback() { this.innerHTML = (<p>foo</p>); } }
可行方案
1. 自定义标签函数实现类JSX语法
自己实现一个标签函数,既能贴近JSX的写法,还能自动转义插值内容避免XSS:
function html(strings, ...values) { let htmlStr = strings[0]; for (let i = 0; i < values.length; i++) { // 转义用户输入内容 const escapedValue = String(values[i]) .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"'); htmlStr += escapedValue + strings[i + 1]; } return htmlStr; } // 使用示例 class Foo extends HTMLElement { connectedCallback() { const userName = 'Alice'; this.innerHTML = html`<p>Hello, ${userName}</p>`; } }
这种写法和JSX类似,且无需额外构建工具,直接在浏览器中运行。
2. 用Babel转译JSX到原生DOM操作
如果项目已经使用Babel,可以配置它将JSX转换成原生document.createElement调用,完全脱离React:
- 安装
@babel/plugin-transform-react-jsx - 在Babel配置中指定自定义的元素创建函数:
{ "plugins": [ ["@babel/plugin-transform-react-jsx", { "pragma": "h", "pragmaFrag": "DocumentFragment" }] ] }
- 实现简单的
h函数:
function h(tag, props = {}, ...children) { const element = document.createElement(tag); // 处理属性和事件 Object.entries(props).forEach(([key, value]) => { if (key.startsWith('on')) { element.addEventListener(key.slice(2).toLowerCase(), value); } else { element.setAttribute(key, value); } }); // 处理子元素 children.forEach(child => { element.appendChild( typeof child === 'string' ? document.createTextNode(child) : child ); }); return element; } // 现在可以直接用JSX写法 class Foo extends HTMLElement { connectedCallback() { this.appendChild(<p onClick={() => alert('clicked')}>foo</p>); } }
3. 轻量级库简化开发
如果不想自己造轮子,可以用专门为Web Component设计的轻量级库,比如lit-html:
import { html, render } from 'lit-html'; class Foo extends HTMLElement { connectedCallback() { const count = 10; render(html`<p>Count: ${count}</p>`, this); } }
lit-html不仅提供类JSX的语法,还支持响应式更新和自动XSS防护,体积小巧,非常适合Web Component场景。
内容的提问来源于stack exchange,提问作者Rofls
相关产品推荐
相关产品推荐

