Skip to content
This repository has been archived by the owner on Jan 21, 2024. It is now read-only.

januwA/react-rxservice

Repository files navigation

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时初始化局部服务

RxServiceservices属性用于添加局部服务,global设置为fasle将不会订阅全局服务,如果你需要局部服务并且也需要全局服务可以无视此选项

RxService 被销毁时,services中的所有局部服务也会自动销毁,销毁前会调用 OnDestroy

OnCreate 在组件渲染完成之前触发

其他问题

不想监听服务中的某个属性的变更?

  1. 使用@Ignore装饰器
@Injectable({ global: false })
class PS implements ServiceProxy {

  @Ignore()
  ref_ = React.createRef<any>();
}
  1. 使用autoIgnore配置选项,会自动无视以_结尾的属性
@Injectable({ global: false, autoIgnore: true })
class PS implements ServiceProxy {
  ref_ = React.createRef<any>();
}

在服务中使用其它服务?

  1. 使用constructor依赖注入
import "reflect-metadata";

@Injectable()
class UserinfoService {}

@Injectable()
class AppService {
  constructor(public readonly userinfo: UserinfoService) {}
}
  1. 使用静态属性
@Injectable()
class UserinfoService {
  static ins: UserinfoService;
}

@Injectable()
class AppService {
  userinfo = UserinfoService.ins;
  i = 0;
}
  1. 使用@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)

  1. 在组件中使用多个服务?
@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() {
     NoReactBegin(this);
     this.i++;
     NoReactEnd(this);
  }
}

NoReactBegin当前服务的所有状态变更都不会通知订阅者

监听属性的变更

  1. 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);
  }
}
  1. 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

About

react rx service

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published