1.1.0 • Published 5 months ago

@knno/jsx v1.1.0

Weekly downloads
-
License
MIT
Repository
-
Last release
5 months ago

@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>
  ))
))
1.1.0

5 months ago

1.0.9

6 months ago

1.0.8

6 months ago

1.0.7

6 months ago

1.0.6

6 months ago

1.0.5

6 months ago

1.0.4

7 months ago

1.0.3

7 months ago

1.0.2

8 months ago

1.0.1

8 months ago

1.0.0

8 months ago