ajanuw-react-rxservice
v1.6.1
Published
react service is a react state manager
Downloads
163
Maintainers
Readme
react-rxservice
Use dependency injection to create services, inspired by Angular
Install
$ npm i ajanuw-react-rxservice
$ npm i rxjs
如果你想使用constructor
依赖注入
$ npm i reflect-metadata
配置 tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
},
}
全局服务
创建全局服务
@Injectable()
class AppService {
i = 0;
}
@Injectable
立即注册一个全局服务,当数据变化时通知订阅者
订阅全局服务
export default memo(() => {
const [as] = useService(AppService);
return (
<RxService
builder={() => {
return (
<div>
<p>{as.i}</p>
<button onClick={() => as.i++}>change</button>
</div>
);
}}
/>
);
});
RxService
组件会自动订阅全局服务,收到响应时触发更新
局部服务(非全局服务)
创建局部服务
@Injectable({ global: false })
class PS implements ServiceProxy {
i = 0;
OnCreate() {}
OnUpdate() {}
OnDestroy() {}
}
使用Injectable
时可以传入一些配置项,将global
设置为false
注册为局部服务,并且不会立即注册
提供了一些钩子函数,用于监听局部服务的生命周期
订阅局部服务
export default memo(() => {
const [ps] = useService(PS);
return (
<RxService
services={[PS]}
global={false}
builder={() => {
return (
<div>
<p>{ps.i}</p>
<button onClick={() => ps.i++}>change</button>
</div>
);
}}
/>
);
});
使用useService
时初始化局部服务
RxService
的services
属性用于添加局部服务,global
设置为fasle
将不会订阅全局服务,如果你需要局部服务并且也需要全局服务可以无视此选项
RxService
被销毁时,services
中的所有局部服务也会自动销毁,销毁前会调用 OnDestroy
OnCreate
在组件渲染完成之前触发
其他问题
不想监听服务中的某个属性的变更?
- 使用
@Ignore
装饰器
@Injectable({ global: false })
class PS implements ServiceProxy {
@Ignore()
ref_ = React.createRef<any>();
}
- 使用
autoIgnore
配置选项,会自动无视以_
结尾的属性
@Injectable({ global: false, autoIgnore: true })
class PS implements ServiceProxy {
ref_ = React.createRef<any>();
}
在服务中使用其它服务?
- 使用
constructor
依赖注入
import "reflect-metadata";
@Injectable()
class UserinfoService {}
@Injectable()
class AppService {
constructor(public readonly userinfo: UserinfoService) {}
}
- 使用静态属性
@Injectable()
class UserinfoService {
static ins: UserinfoService;
}
@Injectable()
class AppService {
userinfo = UserinfoService.ins;
i = 0;
}
- 使用
@Late
装饰器
@Injectable({ id: "UserinfoService" })
class UserinfoService {
i = 0;
}
@Injectable()
class AppService {
@Late("UserinfoService")
userinfo!: UserinfoService;
@Late("AfterService")
after!: any;
}
@Injectable({ id: "AfterService" })
class AfterService {}
@Late
装饰器需要提供一个服务的唯一id,如果这个服务已经被初始化则会立即初始化属性(userinfo),否则会一直等到服务初始化时才设置属性(after)
- 在组件中使用多个服务?
@Injectable()
class UserinfoService {}
@Injectable()
class AppService {}
@Injectable({ global: false })
class PS {}
export default memo(() => {
const [ps, as, us] = useService(PS, AppService, UserinfoService);
return (
<RxService
services={[PS]}
builder={() => {
return <div></div>;
}}
/>
);
});
使用上一次销毁的数据?
只能在局部服务中在这样做!
@Injectable({ global: false })
class PS implements ServiceProxy {
i = 0;
OnDestroy() {
return true;
}
}
如果在页面销毁时i=10
,并且在OnDestroy
钩子中返回true
,那么下次重启这个服务时,数据不会被初始化而是继续使用上一次的数据,再次进入页面你会直接看到i=10
而不是i=0
服务从第一次创建就一直存在于内存中,销毁只是一个状态,在销毁状态下所有的变更都不会通知订阅者
当再次启动销毁状态的服务时,只是取消了销毁状态,数据的初始化取决于上一次OnDestroy
钩子的返回值,如果返回true
将继续使用以前的数据,否则会重新初始化一个实例,并创建一个新的代理然后触发OnCreate
钩子
改变数据时,不想通知订阅者?
@Injectable()
class PS {
i = 0;
add() {
noreact(() => {
this.i++
})
}
}
在noreact
的钩子函数中,改变数据时不会通知订阅者
作为装饰器使用也可以达到同样的效果
@Injectable()
class PS {
i = 0;
@noreact()
add() {
this.i++
}
}
监听属性的变更
Watch
装饰器,监听一个或多个属性的变更
class PS {
i = 0;
obj = { i: 0 }
@Watch(['this.i', 'this.obj.i'])
watch(newVal: number, oldVal: number, key: string) {
console.log(key, newVal, oldVal);
}
}
AutoWatch
自动监听属性变化
class PS implements ServiceProxy {
i = 0;
j = 0;
@AutoWatch()
watch() {
this.j = this.i * 2
}
}
会自动代理哪些对象?
Array
[object Object]
[object Set]
[object Map]
[object WeakMap]
Run test
$ npm start
$ npm t