

本篇文章对于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的使用差异不大,但更小,对于一些轻量级的项目不妨尝试使用看看效果如何。


















