1.1.0 • Published 5 months ago
@knno/jsx v1.1.0
@knno/jsx
简介
@knno/jsx 是一个简单的 JSX 运行时库,没有虚拟 DOM。
安装
npm install @knno/jsx配置 tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "@knno/jsx"
}
}或使用旧的 jsx factory 方式:
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "h",
"jsxFragmentFactory": "fragment"
}
}渲染
import { render } from '@knno/jsx';
// 默认渲染到 body 里
render(() => <div>Hello world!</div>);
// 或指定容器
render(() => <div>Hello world!</div>, '#app');自定义组件
自定义组件需要继承 Component 类,并实现 render 方法。以下是一个示例:
import { render, Props, CSSStyle } from '@knno/jsx';
type MyProps = Props<MyComponent> & {
style?: CSSStyle;
};
class MyComponent extends Component<MyProps> {
render() {
return (
<div style={this.props.style}>
<h2>MyComponent {new Date()}</h2>
<button onclick={() => this.update()}>
Update Completely
</button>
</div>
);
}
}
render(() => (
<MyComponent
style={{ fontSize: '20pt', color: 'red' }}
ref={(m) => console.log('jsx component:', m)} />
)
);函数组件
import { render, Child, BaseProps, CSSStyle } from '@knno/jsx';
type Prop = BaseProps & {
name?: string;
style?: string | CSSStyle;
};
function MyFunction(props: Prop) {
return (
<div name={props.name} style={props.style}>
<h2>MyFunction</h2>
Children: {[...props.children]}
</div>
);
}
render(() => (
<MyFunction
name="MyFunction"
style={{ fontSize: '18pt' }}
>
{[1, 2, 3, 4].map((i) => (
<button>button{i}</button>
))}
</MyFunction>
));可以使用 WebComponent 组件
import { render, WebComponents } from '@knno/jsx';
class MyWebComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot?.append(<h2>MyWebComponent</h2>);
}
connectedCallback() {
console.log('connectedCallback');
}
}
// 注册并获得 WebComponent 组件的包装器类型
const MyComponentWrapper = WebComponents.register(MyWebComponent, 'my-component');
render(() => (
<>
使用包装器类型:
<br />
<MyWebComponent ref={(el) => {
// 这里 el 是 MyWebComponent 组件的实例
console.log(el);
}} />
<br />
使用 webcomponent 标签:
<br />
<my-component />
</>
));SSR (用 jsdom 举例)
import { JSDOM } from 'jsdom';
import { render } from '@knno/jsx';
// 创建一个 jsdom 实例
const dom = new JSDOM();
// 定义一个组件
function App() {
return (
<div>
<h1>Hello, SSR!</h1>
</div>
);
}
// 渲染组件
useContext(dom.window, () => {
render(() => (<App />));
});
// 获取渲染后的 HTML
const html = dom.serialize();
console.log(html);避免 SVG 或 MathML 标签冲突
如 title、script 等标签,既是 svg 标签同时也是 html 标签,此时需要使用命名空间来区分。
import { render, NS } from '@knno/jsx';
render(() => (
<svg>
<svg:title>SVG title 标签 </svg:title>
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
))
// 或指定命名空间
render(() => (
NS.svg(() => (
<svg>
<title>SVG title 标签 </title>
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
))
))