Template
模板引擎使编写类型安全、快速和安全的HTML模板成为可能。它基于TSX,只要你使用文件扩展名`.tsx`并相应调整`tsconfig.json`,就可以使用。
重要的是,它与React不兼容。一旦要使用React,`@deepkit/template`就不兼容了。Deepkit的模板引擎只用于SSR(服务器端渲染)。
Installation
在你的tsconfig中,你必须调整以下设置:jsx`和`jsxImportSource
。
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "ES2020",
"moduleResolution": "node",
"jsx": "react-jsx",
"jsxImportSource": "@deepkit/template"
}
}
现在你可以在你的控制器中直接使用TSX。
#!/usr/bin/env ts-node-script
import { App } from '@deepkit/app';
import { FrameworkModule } from '@deepkit/framework';
import { http } from '@deepkit/http';
@http.controller('my-base-url/')
class MyPage {
@http.GET('hello-world')
helloWorld() {
return <div style="color: red">Hello World</div>;
}
}
new App({
controllers: [MyPage],
imports: [
new FrameworkModule({
debug: true,
})
]
}).run();
如果你在路由方法中返回这样的TSX,HTTP内容类型会自动设置为`text/html; charset=utf-8`。
Components
你可以按照你在React中习惯的方式构造你的模板。要么将你的布局模块化为几个功能或类组件。
Function Components
最简单的方法是使用一个返回TSX的函数。
async function Website(props: {title: string, children?: any}) {
return <html>
<head>
<title>{props.title}</title>
</head>
<body>
{props.children}
</body>
</html>;
}
class MyPage {
@http.GET('hello-world')
helloWorld() {
return <Website title="Hello world">
<h1>Great page</h1>
</Website>;
}
}
$ curl http://localhost:8080/hello-world
<html><head><title>Hello world</title></head><body><h1>Great page</h1></body></html>
函数组件可以是异步的(与React不同)。这与你可能知道的其他模板引擎,如React,是一个重要的区别。
所有的函数都可以访问依赖注入容器,并且可以引用从第三个参数开始的任何依赖关系。
class Database {
users: any[] = [{ username: 'Peter' }];
}
function UserList(props: {}, children: any, database: Database) {
return <div>{database.users.length}</div>;
}
class MyPage {
@http.GET('list')
list() {
return <UserList/>
}
}
new App({
controllers: [MyPage],
providers: [Database],
imports: [new FrameworkModule()]
}).run();
Class Components
另一种编写组件的方式是类组件。它们在依赖注入容器中被处理和实例化,因此可以访问在容器中注册的所有服务。这使得在你的组件中直接访问数据源(如数据库)成为可能,例如。
class UserList {
constructor(
protected props: {},
protected children: any,
protected database: SQLiteDatabase) {
}
async render() {
const users = await this.database.query(User).find();
return <div class="users">
{users.map((user) => <UserDetail user={user}/>)}
</div>;
}
}
class MyPage {
@http.GET('')
listUsers() {
return <UserList/>;
}
}
第一个构造函数参数是为类组件保留的。`props`可以任意定义,`children`总是 "any",然后是可选的依赖关系,你可以任意选择。由于类组件在依赖注入容器中被实例化,你可以访问你的所有服务。