快速使用 vite 创建一个react-ts项目
λ npm init vite@latest
npx: 6 安装成功,用时 2.033 秒
√ Project name: ... myapp
√ Select a framework: » react
√ Select a variant: » react-ts
λ cd myapp
λ npm install
下载 rxjs 和 react-rxbuilder
λ npm i rxjs react-rxbuilder
使用编辑器向 tsconfig.json 添加两项,用于支持装饰器语法和Metadata元数据
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
},
}
在根组件挂载 RxService
import { RxService } from "react-rxbuilder";
ReactDOM.render(
<React.StrictMode>
<RxService>{() => <App />}</RxService>
</React.StrictMode>,
document.getElementById("root")
);
通常你只需要在你的程序中使用一次 RxService
在 App 组件中创建 Service
import { Injectable } from "react-rxbuilder";
@Injectable()
class CountService {
i = 0;
inc() {
this.i++;
}
}
使用 Injectable 将一个类快速注册为 Service
在组件中使用 CountService
function App() {
const [count] = useService(CountService);
return (
<>
<h2>{count.i}</h2>
<button onClick={count.inc}>Inc</button>
</>
);
}
现在你的 App.tsx
文件应该是这样
import React from "react";
import { Injectable, useService } from "react-rxbuilder";
@Injectable()
class CountService {
i = 0;
inc() {
this.i++;
}
}
function App() {
const [count] = useService(CountService);
return (
<>
<h2>{count.i}</h2>
<button onClick={count.inc}>Inc</button>
</>
);
}
export default App;
启动开发服务器,然后在页面中点击 button 看看
λ npm run dev
在组件中使用多个 Service
继续使用 Injectable 创建 LogService
@Injectable()
class LogService {
log() {
console.log(new Date().toLocaleString());
}
}
然后在 App 组件中使用
function App() {
const [count, log] = useService(CountService, LogService);
return (
<>
<h2>{count.i}</h2>
<button onClick={() => (count.inc(), log.log())}>
Inc
</button>
</>
);
}
现在点击按钮的同时,在控制台记录消息
为了简化代码,我们可以在 CountService 中使用 LogService
@Injectable()
class CountService {
constructor(public readonly logService: LogService) {}
i = 0;
inc() {
this.i++;
this.logService.log();
}
}
上面使用了 constructor 依赖注入,但是你打开服务器可能会遇到 this.logService 是 undefined 的错误,因为 vite 使用的是 esbuild 可以使用 swc代替 esbuild
还有一种解决方案是使用静态属性代替 constructor 依赖注入
最后的代码如下
import React from "react";
import { Injectable, useService } from "react-rxbuilder";
@Injectable()
class LogService {
static ins: LogService;
log() {
console.log(new Date().toLocaleString());
}
}
@Injectable()
class CountService {
readonly logService = LogService.ins;
i = 0;
inc() {
this.i++;
this.logService.log();
}
}
function App() {
const [count] = useService(CountService);
return (
<div>
<h2>{count.i}</h2>
<button onClick={count.inc}>Inc</button>
</>
);
}
export default App;