如何在Preact和TypeScript中使用Web组件(附代码)

244 阅读1分钟

如何在Preact和TypeScript中使用Web组件

Web组件为网络提供了一个可重用的UI组件模型。Web组件是通过几个独立的技术组合来创建的,如自定义元素、阴影DOM和HTML模板。

Web组件与Preact中的组件类似,通过属性和事件进行通信。属性可以被设置为向组件传递数据,而自定义事件允许组件向组件树上传递数据。

在这篇文章中,我们将学习如何使用一个简单的警报Web组件,并将其用于我们用TypeScript编写的Preact应用程序中。

A Web Component working in React

为了在我们的Preact组件中使用警报,我们导入该组件并添加x-alert 标签:

import { useState } from 'preact/hooks';
import './alert.js';

export default function App() {
  const [show, setShow] = useState(true);

  return (
    <div>
      <button onClick={() => setShow(!show)}>toggle alert</button>

      <x-alert hidden={show} status={'status'} closable oncloseChange={() => setShow(!show)}>
        This is a Web Component in Preact
      </x-alert>
    </div>
  );
}

如果我们使用TypeScript,我们很可能会在我们的TSX文件中看到像下面这样的错误:

Unknown Web Component in TSX file

TypeScript不能对我们的TSX模板进行类型检查,因为它不知道我们的自定义元素标签的CustomElement类引用。我们可以将我们的标签添加到JSX.IntrinsicElements 全局接口。这将把x-alertXAlert 类的引用联系起来。

import { useState } from 'preact/hooks';
import { XAlert } from './alert.js';
import './alert.js';

type CustomEvents<K extends string> = { [key in K] : (event: CustomEvent) => void };

type CustomElement<T, K extends string = ''> = Partial<T & { children: any } & CustomEvents<`on${K}`>>;

declare global {
  namespace preact.createElement.JSX {
    interface IntrinsicElements {
      ['x-alert']: CustomElement<XAlert, 'closeChange'>;
    }
  }
}

通过模板字面类型,我们可以创建一个字符串类型的列表,并为我们的事件生成一个带有on 前缀的新的字符串类型列表。接下来我们可以将事件字符串传递给CustomEvents 类型,它将添加函数签名。现在我们在Preact和TSX中为我们的Web组件进行了类型检查和自定义事件。

import { useState } from 'preact/hooks';
import { XAlert } from './alert.js';
import './alert.js';

// auto-generate these types using: https://github.com/coryrylan/custom-element-types
type CustomEvents<K extends string> = { [key in K] : (event: CustomEvent) => void };
type CustomElement<T, K extends string = ''> = Partial<T & { children: any } & CustomEvents<`on${K}`>>;

declare global {
  namespace preact.createElement.JSX {
    interface IntrinsicElements {
      ['x-alert']: CustomElement<XAlert, 'closeChange'>;
    }
  }
}

export function App() {
  const [show, setShow] = useState(true);

  return (
    <div>
      <button onClick={() => setShow(!show)}>toggle alert</button>

      <x-alert hidden={show} status={'success'} closable oncloseChange={() => setShow(!show)}>
        This is a Web Component in Preact
      </x-alert>
    </div>
  );
}