1.1.0-alpha.60 • Published 10 months ago

@loong-js/core v1.1.0-alpha.60

Weekly downloads
-
License
MIT
Repository
-
Last release
10 months ago

@loong-js/core

通过依赖注入的方式搭建 React 应用。

安装

yarn add @loong-js/core

# 需要前置安装 react mobx mobx-react-lite
yarn add react mobx mobx-react-lite

环境配置

首先需要配置 typescript 输出元信息,如果使用 Babel 还需要额外配置。

typescript.json

{
  "compilerOptions": {
    "experimentalDecorators": true,
    // 输出编译信息
    "emitDecoratorMetadata": true
  }
}

Babel

如果使用 Babel 编译 ts,需要添加 babel-plugin-transform-typescript-metadata,并且顺序如下(如果涉及装饰器的 Babel 插件还没装,也需要安装)。

{
  "plugins": [
    "babel-plugin-transform-typescript-metadata",
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose": true }]
  ]
}

使用

一个简单的例子(代码地址

  • bind,用来绑定使用 Component 注解的 UI 控制类;
  • connect,连接最近绑定的 UI 控制类。
  • Component,注解一个 UI 控制类,接受 { providers: [...Services] } 配置,Services 是服务类集合;
  • Injectable,注解一个服务。

npm.io

使用 Component 或者 Injectable 注解的类,可以通过在构造函数中声明来使用 Component 注解配置的服务类,服务类之间也可相互调用。

API 参考

bind

在组件上绑定使用 Component 注解的 UI 控制类,执行 bind 会返回 binder 函数。使用方法:

import { Component, bind } from '@loong-js/core';

// 1. 注解一个 UI 控制类
@Component()
class AppCompnent {
  constructor() {}
}

// 2. 生成 binder 函数
const binder = bind(Component);

// 3. 使用 binder 绑定组件
const App = binder(() => <div>App</div>);

const App2 = binder(() => <div>App</div>);

binder

binder 函数接受两个参数,第一个函数组件,第二个 options 的接口定义是:

interface IBinderOptions {
  // 使用 ref
  forwardRef?: boolean;
}

使用方式:

// binder 接受两个泛型,第一个定义了 Props 的类型,第二个定义了 Ref 的类型
const App = binder<Record<string, unknown>, HTMLDivElement>(
  (props, ref) => <div ref={ref}>App</div>,
  {
    forwardRef: true,
  }
);

简单的例子

import { FC } from 'react';
import { Component, BoundProps, bind } from '@loong-js/core';

@Component()
class AppCompnent {
  count = 0;

  constructor() {}
}

// 1. 直接使用
interface IAppProps {
  name?: string;
}

const App = bind(AppCompnent)<IAppProps>(({ $this }) => <div>Count: {$this.count}</div>);

// 2. 生成 binder
const binder = bind(AppComponent);

type PropsFromBinder = BoundProps<typeof binder>;

interface IApp2Props extends PropsFromBinder {
  name?: string;
}

const App2FC: FC<IApp2Props> = ({ $this }) => <div>{$this.count}</div>;

const App2 = binder(App2FC);

Component

注解一个 UI 控制类,具体看 bind 的使用方式,Component 接受的 options 接口:

// IClassType 指的是服务类或者 UI 控制类
interface IComponentOptions {
  providers: IClassType[];
}

Injectable

注解一个服务,使用方式很简单:

import { Injectable } from '@loong-js/core';

@Injectable()
class Service {}

connect

连接最近绑定的 UI 控制类,connect 接受三个泛型,第一个是 UI 控制类,第二个定义了 Props 的类型,第三个定义了 Ref 的类型,使用方式:

import { Component, connect, bind } from '@loong-js/core';

@Component()
class AppCompnent {
  count = 0;

  constructor() {}
}

const Child = connect<AppCompnent, Record<string, unknown>, HTMLDivElement>(({ $this }, ref) => (
  <div ref={ref}>Child {$this.count}</div>
));

const App = bind(AppCompnent)(({ $this }) => (
  <div>
    <p>Count = {$this.count}</p>
    <Child />
  </div>
));

Prop

在 UI 控制类或者服务上绑定组件的 props,使用方式:

import ReactDOM from 'react-dom';
import { Component, bind, Prop } from '@/index';

@Component()
class AppCompnent {
  // 默认使用属性名作为绑定的 prop 名称
  @Prop()
  name!: string;

  // 如果属性名与 prop 名称不一样,传入绑定的 prop 名称
  @Prop('name')
  nameAlias!: string;

  constructor() {
    console.log(this.name, this.nameAlias);
  }

  printName = () => {
    console.log(this.name);
  };
}
const App = bind(AppCompnent)<{ name: string }>(({ $this }) => (
  <div>
    <button onClick={$this.printName}>printName</button>
  </div>
));

ReactDOM.render(<App name="app" />, document.getElementById('root'));

Hook

在 UI 控制类或者服务上绑定组件的钩子,使用方式:

import { Component, bind, Hook } from '@/index';

@Component()
class AppCompnent {
  // 默认传入方法的名称作为钩子名
  @Hook()
  mounted() {
    console.log('mounted');
  }

  // 如果方法与 hook 名称不一样,传入绑定的 hook 名称
  @Hook('unmount')
  unmountAlias() {
    console.log('unmountAlias');
  }
}
const App = bind(AppCompnent)(({ $this }) => <div>App</div>);

Watch

观察值的变化,第一次执行或者满足条件都会执行注解的方法,注解接受一个函数,函数类型是:

// $this 是注解的类的实例,可以返回 boolean 或者依赖的属性数组
type Data = ($this: any) => boolean | any[];

export function Watch(data: Data): any;
// 接受依赖的属性字符串
export function Watch(...names: string[]): any;
export function Watch(...args: (Data | string)[]): any;

使用方式:

@Component()
class AppCompnent {
  count = 0;

  count2 = 0;

  @Prop()
  name!: string;

  constructor() {
    makeAutoObservable(this);
  }

  increase = () => {
    this.count++;
  };

  increase2 = () => {
    this.count2++;
  };

  // 依赖的两个属性某个变化,就会触发方法
  @Watch('count', 'count2')
  change() {
    console.log('change >>>', this.count, this.count2);
  }

  // 依赖的三个属性某个变化,就会触发方法
  @Watch(({ count, count2, name }) => [count, count2, name])
  change2() {
    console.log('change2 >>>', this.count, this.count2, this.name);
  }

  // 满足条件才会触发方法
  @Watch(({ count }) => count >= 1)
  change3() {
    console.log('change3 >>>', this.count);
  }
}

🐛 Issues

If you find a bug, please file an issue on our issue tracker on GitHub.

🏁 Changelog

Changes are tracked in the CHANGELOG.md.

📄 License

@loong-js/core is available under the MIT License.

1.1.0-alpha.59

10 months ago

1.1.0-alpha.60

10 months ago

1.1.0-alpha.51

1 year ago

1.1.0-alpha.50

1 year ago

1.1.0-alpha.55

12 months ago

1.1.0-alpha.53

1 year ago

1.1.0-alpha.52

1 year ago

1.1.0-alpha.56

12 months ago

1.1.0-alpha.47

1 year ago

1.1.0-alpha.46

1 year ago

1.1.0-alpha.49

1 year ago

1.1.0-alpha.44

2 years ago

1.1.0-alpha.42

2 years ago

1.1.0-alpha.26

2 years ago

1.1.0-alpha.28

2 years ago

1.1.0-alpha.24

2 years ago

1.1.0-alpha.23

2 years ago

1.1.0-alpha.19

2 years ago

1.1.0-alpha.18

2 years ago

1.1.0-alpha.17

2 years ago

1.1.0-alpha.22

2 years ago

1.1.0-alpha.21

2 years ago

1.1.0-alpha.20

2 years ago

1.1.0-alpha.14

3 years ago

1.1.0-alpha.16

3 years ago

1.1.0-alpha.11

3 years ago

1.1.0-alpha.10

3 years ago

1.1.0-alpha.9

3 years ago

1.1.0-alpha.12

3 years ago

1.1.0-alpha.1

3 years ago

1.1.0-alpha.2

3 years ago

1.1.0-alpha.0

3 years ago

1.1.0-alpha.3

3 years ago

1.1.0-alpha.4

3 years ago

0.0.1

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.4

3 years ago

0.5.0

4 years ago

0.4.0

4 years ago

0.3.0

4 years ago

0.2.0

4 years ago

0.1.0

4 years ago