Skip to content

Commit

Permalink
feat: 新增组件实例全局注入功能
Browse files Browse the repository at this point in the history
fix: 修复依赖,把hry-types放到peer中
  • Loading branch information
missannil committed Dec 18, 2023
1 parent 98d70ca commit 2e44e57
Show file tree
Hide file tree
Showing 38 changed files with 420 additions and 186 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ annil(安奈儿)是微信小程序原生开发插件,其提供的API功能更强
- 可选

```bash
npm typescript miniprogram-api-typings --save-dev
npm typescript --save-dev
```

```bash
Expand Down Expand Up @@ -93,16 +93,16 @@ annil(安奈儿)是微信小程序原生开发插件,其提供的API功能更强
module.exports = require("./mobx.cjs.production.min.js");
```
> 另外,构建时会出现`node_modules/miniprogram-api-typings/index.d.ts.js: Npm package entry file not found`错误,这是因为annil插件把官方类型库`miniprogram-api-typings`加入到生产依赖中,而npm构建时找不到它的生产目录所致,无视即可。还需删除`miniprogram_npm`下的`hry-types`目录(annil依赖的类型工具库)。
3. 配置tsconfig.json(使用ts开发时)
```json
{
"compilerOptions": {
// ...
"lib": ["ES2022"],
"skipLibCheck": true,
"types": ["miniprogram-api-typings", "mobx"]
"strict": true,
"strictFunctionTypes": false, // 解决给事件参数e重定义类型报错的问题
"types": ["miniprogram-api-typings"]
}
// ...
}
Expand Down
1 change: 1 addition & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const config = {
"./src/**/*.ts",
"!src/**/*.test.ts",
"!src/api/navigateTo.ts",
"!src/inject.ts",
"!src/thirdLib/**",
],
testMatch: [
Expand Down
2 changes: 0 additions & 2 deletions jest/events/events.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */

import simulate from "miniprogram-simulate";
import path from "path";

Expand Down
2 changes: 1 addition & 1 deletion jest/events/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const subA = SubComponent<Root, CompDoc>()({

type Root = typeof rootComponent;

export const rootComponent = RootComponent()({
const rootComponent = RootComponent()({
data: {
id: "",
},
Expand Down
4 changes: 4 additions & 0 deletions jest/inject/duplicate/duplicate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
50 changes: 50 additions & 0 deletions jest/inject/duplicate/duplicate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import simulate from "miniprogram-simulate";
import path from "path";
import { instanceConfig } from "../../../src";
import { BBeforeCreate } from "../../../src/behaviors/BbeforeCreated";
import { BComputedAndWatch } from "../../../src/behaviors/BComputedAndWatch";
import { BStore } from "../../../src/behaviors/BStore";
export const checkData = {
options: {} as object | undefined,
data: {} as any,
behaviors: [] as string[],
};

const behavior = Behavior({});

// 注入options配置
// @ts-ignore
instanceConfig.setInjectInfo({
options: {
addGlobalClass: true,
multipleSlots: true,
pureDataPattern: /^_/,
virtualHost: true,
},
data: {
injectStr: "string",
},
behaviors: [behavior],
});

describe("inject数据被组件数据覆盖", () => {
const id = simulate.load(path.resolve(__dirname, "duplicate"));
const comp = simulate.render(id);
const parent = document.createElement("parent-wrapper");

comp.attach(parent);

test("注入options、data、behaviors", () => {
expect(checkData.options).toStrictEqual({
classPrefix: "main", // miniprogram-simulate 定义的
addGlobalClass: false,
multipleSlots: false,
pureDataPattern: /^__/,
virtualHost: false,
});

expect(checkData.data.injectStr).toBe("changed");

expect(checkData.behaviors).toStrictEqual([BStore, BComputedAndWatch, behavior, BBeforeCreate]);
});
});
28 changes: 28 additions & 0 deletions jest/inject/duplicate/duplicate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { DefineComponent, RootComponent } from "../../../src";
import { checkData } from "./duplicate.test";

const rootComponent = RootComponent()({
options: {
addGlobalClass: false,
multipleSlots: false,
pureDataPattern: /^__/,
virtualHost: false,
},
data: {
injectStr: "changed",
},
lifetimes: {
beforeCreate(opt) {
checkData.options = opt.options;

checkData.data = opt.data;

checkData.behaviors = opt.behaviors;
},
},
});

DefineComponent({
name: "injectNormal",
rootComponent,
});
Empty file.
4 changes: 4 additions & 0 deletions jest/inject/normal/normal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
44 changes: 44 additions & 0 deletions jest/inject/normal/normal.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import simulate from "miniprogram-simulate";
import path from "path";
import { instanceConfig } from "../../../src";

export const checkData = {
options: {} as object | undefined,
data: {} as any,
};

const options = {
addGlobalClass: true,
multipleSlots: true,
pureDataPattern: /^_/,
virtualHost: true,
};

// 注入options配置
// @ts-ignore
instanceConfig.setInjectInfo({
options,
data: {
injectStr: "string",
},
store: {
injectTheme: () => "dark",
},
});

describe("inject-无重复", () => {
const id = simulate.load(path.resolve(__dirname, "normal"));
const comp = simulate.render(id);
const parent = document.createElement("parent-wrapper");

comp.attach(parent);

test("注入options、data、store", () => {
expect(checkData.options).toStrictEqual({
classPrefix: "main", // miniprogram-simulate 定义的
...options,
});

expect(checkData.data).toStrictEqual({ injectTheme: "dark", injectStr: "string" });
});
});
17 changes: 17 additions & 0 deletions jest/inject/normal/normal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { DefineComponent, RootComponent } from "../../../src";
import { checkData } from "./normal.test";

const rootComponent = RootComponent()({
lifetimes: {
beforeCreate(opt) {
checkData.options = opt.options!;

checkData.data = opt.data;
},
},
});

DefineComponent({
name: "injectNormal",
rootComponent,
});
Empty file added jest/inject/normal/normal.wxml
Empty file.
9 changes: 4 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@
],
"author": "missannil",
"license": "MIT",
"dependencies": {
"hry-types": "^0.17.0"
},
"peerDependencies": {
"hry-types": "^0.17.0",
"miniprogram-api-typings": "^3.12.2"
}
}
58 changes: 47 additions & 11 deletions src/api/DefineComponent/collectOptionsForComponent.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { Func } from "hry-types/src/Misc/_api";
import { instanceConfig } from "../..";
import { BBeforeCreate } from "../../behaviors/BbeforeCreated";
import { BComputedAndWatch } from "../../behaviors/BComputedAndWatch";
import type { ComputedCache, Instance } from "../../behaviors/BComputedAndWatch/types";
import { BStore } from "../../behaviors/BStore";
import { Assign } from "../../types/Assign";
import type { WMComponent } from "../../types/OfficialTypeAlias";
import { INNERMARKER } from "../../utils/InnerMarker";
import { isEmptyObject } from "../../utils/isEmptyObject";
Expand Down Expand Up @@ -292,6 +294,44 @@ function collectRootComponentOption(
otherFieldsHandle(finalOptions, rootComponentOptions);
}

/**
* 合并 source 对象字段到 target字段
* @remarks 规则:
* 1. behaviors字段 源对象在前
* 2. 对象字段 源覆盖目标
* @param target - 目标对象
* @param source - 源对象
* @returns 按规则合并后的对象
*/
function merge<Target extends object, Source extends object>(target: Target, source: Source): Assign<Target, Source> {
for (const key in source) {
const sourceVal = source[key];
if (key in target) {
// @ts-ignore
const targetVal = target[key];
switch (key) {
case "behaviors":
{
// @ts-ignore
target[key] = [...sourceVal, ...targetVal];
}
break;

default:
{
// @ts-ignore 源覆盖目标
target[key] = Object.assign(targetVal, sourceVal);
}
break;
}
} else {
// @ts-ignore
target[key] = sourceVal;
}
}

return target as unknown as Assign<Target, Source>;
}
/**
* 返回一个由rootComponentOption和subComponentsList配置整合的对象
* @param rootComponentOption -
Expand All @@ -303,18 +343,14 @@ export function collectOptionsForComponent(
): FinalOptionsOfComponent {
const rootComponentOption = defineComponentOption.rootComponent;
const subComponentsList = defineComponentOption.subComponents;
const finalOptionsForComponent: FinalOptionsOfComponent = {
options: {
addGlobalClass: true, // "styleIsolation": "apply-shared"
multipleSlots: true,
pureDataPattern: /^_/,
virtualHost: true,
},
behaviors: [BStore, BComputedAndWatch],
methods: {},

const finalOptionsForComponent: FinalOptionsOfComponent = merge(instanceConfig.injectInfo || {}, {
observers: {},
data: {},
};
methods: {},
behaviors: [BStore, BComputedAndWatch],
});

/**
* 有些字段配置同时存在根组件和子组件当中(如pageLifetimes,lifetimes,watch字段), 且key相同值类型为函数。funcConfig对象用于收集这些配置为数组形式,最终再一起整合进finalOptionsForComponent配置中。即funcConfig是一个临时中介对象。
*/
Expand Down Expand Up @@ -350,7 +386,7 @@ export function collectOptionsForComponent(
/* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
finalOptionsForComponent.isPage
// 页面时删除预设的虚拟组件字段
&& Reflect.deleteProperty(finalOptionsForComponent.options!, "virtualHost");
&& finalOptionsForComponent.options && Reflect.deleteProperty(finalOptionsForComponent.options, "virtualHost");

// BBeforeCreate在最后面,让BeforeCreate生命周期运行在最终建立组件时。
finalOptionsForComponent.behaviors!.push(BBeforeCreate);
Expand Down
1 change: 1 addition & 0 deletions src/api/DefineComponent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export type DefineComponentOption = {
*/
export const DefineComponent: DefineComponentConstructor = function(options): any {
// console.log("---------------------------");

Component(
collectOptionsForComponent(options as DefineComponentOption) as any,
);
Expand Down
25 changes: 0 additions & 25 deletions src/api/InstanceInject/InstanceInject.ts

This file was deleted.

Loading

0 comments on commit 2e44e57

Please sign in to comment.