本篇文章对于preact
不做过深介绍,仅仅介绍其基础的使用方法。使用Preact,我们可以通过组装组件和元素的树来创建用户界面。组件是返回其树应该输出的内容的描述的函数或类。这些描述通常是用JSX
(如下所示)或HTML
编写的,它利用了标准的JavaScript
标记模板。这两种语法都可以表示具有"props
"(类似于HTML属性)和子元素的树。
preact
支持通过多种方式引入使用。
直接使用
Preact
被打包为直接在浏览器中使用,不需要任何构建或工具:
<script type="module">
import { h, render } from 'https://esm.sh/preact';
// Create your app
const app = h('h1', null, 'Hello World!');
render(app, document.body);
</script>
需要注意的是使用这种方式来使用preact
是不支持jsx
语法格式的。
使用Vite
在过去的几年里,Vite
已经成为一种非常流行的工具,用于跨许多框架构建应用程序,Preact
也不例外。它建立在流行的工具之上,如ES
模块、Rollup
和ESBuild
。Vite
,通过我们的初始化器或他们的Preact
模板,不需要任何配置或先验知识就可以开始,这种简单性使它成为一种非常流行的使用Preact
的方式。
创建项目
为了快速启动并运行Vite,您可以使用我们的初始化器create-precast。这是一个交互式命令行界面(CLI)应用程序,可以在您机器上的终端中运行。使用它,您可以通过运行以下程序来创建新的应用程序:
$ npm install -g create-preact
$ npm init preact
这将引导您创建一个新的Preact应用程序,并为您提供一些选项,如TypeScript、路由(通过Preact iso)和ESLint支持。
配置JSX
要转换JSX
,您需要一个Babel
插件将其转换为有效的JavaScript
代码。我们都使用的是@babel/plugin-transform-react-jsx
。安装后,需要为JSX
指定应使用的函数:
{
"plugins": [
["@babel/plugin-transform-react-jsx", {
"pragma": "h",
"pragmaFrag": "Fragment",
}]
]
}
无缝衔接React
在某个时刻,您可能会想利用庞大的React生态系统。最初为React编写的库和组件与我们的兼容层无缝工作。为了利用它,我们需要将所有的react和react dom导入指向Preact。此步骤称为混叠。
在webpack中使用
要对Webpack中的任何包进行别名,您需要在配置中添加resolve.alias部分。根据您使用的配置,此部分可能已经存在,但缺少Preact的别名。
const config = {
//...snip
"resolve": {
"alias": {
"react": "preact/compat",
"react-dom/test-utils": "preact/test-utils",
"react-dom": "preact/compat", // Must be below test-utils
"react/jsx-runtime": "preact/jsx-runtime"
},
}
}
在Node中使用
在Node
中运行时,bundler
别名(Webpack
、Rollup
等)将不起作用,如NextJS
中所示。要解决此问题,我们可以在package.json
中直接使用别名::
{
"dependencies": {
"react": "npm:@preact/compat",
"react-dom": "npm:@preact/compat",
}
}
在Parcel中使用
Parcel
使用标准的package.json
文件读取别名键下的配置选项。
{
"alias": {
"react": "preact/compat",
"react-dom/test-utils": "preact/test-utils",
"react-dom": "preact/compat",
"react/jsx-runtime": "preact/jsx-runtime"
},
}
在Rollup中使用
要在Rollup
中使用别名,需要安装@Rollup/plugin-alias
。在您的@rollup/plugin
节点解析之前,需要放置插件
import alias from '@rollup/plugin-alias';
module.exports = {
plugins: [
alias({
entries: [
{ find: 'react', replacement: 'preact/compat' },
{ find: 'react-dom/test-utils', replacement: 'preact/test-utils' },
{ find: 'react-dom', replacement: 'preact/compat' },
{ find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }
]
})
]
};
在TypeScript中使用
TypeScript
,即使与bundler
一起使用,也有自己的解析类型的过程。为了确保使用Preact
的类型来代替React
的类型,您需要将以下配置添加到tsconfig.json
(或jsconfig.json
)中:
{
"compilerOptions": {
...
"skipLibCheck": true,
"baseUrl": "./",
"paths": {
"react": ["./node_modules/preact/compat/"],
"react-dom": ["./node_modules/preact/compat/"]
}
}
}
使用Preact创建页面
import { h, render } from 'preact';
// Tells babel to use h for JSX. It's better to configure this globally.
// See https://babeljs.io/docs/en/babel-plugin-transform-react-jsx#usage
// In tsconfig you can specify this with the jsxFactory
/** @jsx h */
// create our tree and append it to document.body:
render(
<main>
<h1>Hello</h1>
</main>,
document.body
);
// update the tree in-place:
render(
<main>
<h1>Hello World!</h1>
</main>,
document.body
);
// ^ this second invocation of render(...) will use a single DOM call to update the text of the <h1>
创建组件
import { render, h } from 'preact';
import { useState } from 'preact/hooks';
/** @jsx h */
const App = () => {
const [input, setInput] = useState('');
return (
<div>
<p>Do you agree to the statement: "Preact is awesome"?</p>
<input value={input} onInput={e => setInput(e.target.value)} />
</div>
);
};
render(<App />, document.body);
如上示例,基本可以看出,和react
的使用差异不大,但更小,对于一些轻量级的项目不妨尝试使用看看效果如何。