Skip to content

Commit

Permalink
chore: 更改SpecificType为DetailedType
Browse files Browse the repository at this point in the history
Release-As: 1.0.5
  • Loading branch information
missannil committed Dec 2, 2023
1 parent 4d4a6ac commit b56a920
Show file tree
Hide file tree
Showing 44 changed files with 344 additions and 205 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

### Bug Fixes

* 解决SpecificType不接收接口类型的错误 ([ae8acbf](https://github.com/missannil/annil/commit/ae8acbfc2e62f99db565c448ad9253aa549e78bb))
* 解决DetailedType不接收接口类型的错误 ([ae8acbf](https://github.com/missannil/annil/commit/ae8acbfc2e62f99db565c448ad9253aa549e78bb))

## [1.0.4](https://github.com/missannil/annil/compare/v1.0.3...v1.0.4) (2023-11-30)

Expand Down
89 changes: 79 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,87 @@

### 简介

annil(安奈儿)是微信小程序原生开发插件,她把组件的逻辑部分解耦为根组件和子组件,与wxml元素一一对应,提高了组件的可读性,更方便拓展和维护。另外annil的类型系统无与伦比,一个页面好比一个类型,无论嵌套多少层组件,无论哪层数据类型发生改变,所有相关类型都会得到感知。当您修改,拓展,重构代码时,只要无类型报错就不会有运行时报错
annil(安奈儿)是微信小程序原生开发插件,提供了新的组件构建API,旨在提高原生开发效率及代码质量

### 特点

- API功能更全面
- 极致的类型约束
- 更严格的书写规范
- 子组件逻辑分离
- 渐进式更新
- **API功能更全面**

## 安装
新的组件API(相较原生Component/Page)加入了`computed``watch``store(全局响应式数据基于mobx)`等功能,使开发更便捷。

```bash
npm i annil --save-dev
```
```ts
```
- **复杂组件解决方案**

新的组件API把组件逻辑部分解耦为根组件逻辑和子组件逻辑,与wxml元素一一对应。彻底解决原生API书写复杂组件时代码逻辑耦合的问题。

- **革命性的组件类型模型**

每个组件(页面)都是唯一的类型(文档描述->类型描述),在使用子组件构建新组件(页面)时,根组件和子组件类型相互关联(提供字段提示、类型约束),无论组件(页面)嵌套多少层,无论哪层数据类型发生改变,所有相关组件类型都会得到感知。当您修改、重构代码时,只要无类型报错就不会有运行时报错的心智负担。

- **更合理的书写规范**

原生开发时,很容易写出不易维护的代码,比如任意`setData`一个未声明变量或通过`this.triggerEvent('name',unknown)`触发组件自定义事件。插件通过类型约束和提前声明变量等方式给出了可选方案。

- **渐进式更新**

此插件提供的API都是原生API的语法糖,不具有强制性和全局性,来去自如。

- **完美融合第三方库**

通过插件提供的泛型[GenerateDoc](./src/types/GenerateDoc.ts)即可根据组件文档生成组件类型,插件也内置了一些原生和第三方组件库类型,欢迎PR您写的第三方组件类型,我为人人,人人为我。

### 安装

1. 依赖安装

- 必装

```bash
npm i annil
```

- 可选

```bash
# 推荐使用 ts开发
npm typescript --save-dev
```

```bash
# 使用全局响应式数据
npm i mobx
```

2. 构建npm

开发者工具左上部工具栏——工具——构建npm
> 若使用mobx,在构建npm前需要手动更改`node_modules/mobx/dist/index.js`文件
> 避免使用时出现 `ReferenceError: process is not defined` 错误。
```js
// 更改前
"use strict";

if (process.env.NODE_ENV === "production") {
module.exports = require("./mobx.cjs.production.min.js");
} else {
module.exports = require("./mobx.cjs.development.js");
}
```
```js
// 更改后
"use strict";
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依赖的另一个类型库)。确保annil和mobx目录构建成功即可。
### 使用文档

### 更新日志

[CHANGELOG](./CHANGELOG.md)

### 协议

[MIT](./LICENSE)
4 changes: 2 additions & 2 deletions doc/demo/componentA.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { User } from "../../jest/common";
import { DefineComponent, RootComponent, type SpecificType } from "../../src";
import { DefineComponent, type DetailedType, RootComponent } from "../../src";

// const subB = SubComponent<RootDoc, { properties: { subA_name: string; subA_age: number } }>()({
// computed: {
Expand All @@ -16,7 +16,7 @@ import { DefineComponent, RootComponent, type SpecificType } from "../../src";

const rootComponent = RootComponent()({
properties: {
user: Object as SpecificType<User>,
user: Object as DetailedType<User>,
},
computed: {
age() {
Expand Down
4 changes: 2 additions & 2 deletions doc/demo/componentB.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { DefineComponent, RootComponent, type SpecificType } from "../../src";
import { DefineComponent, type DetailedType, RootComponent } from "../../src";

const rootComponent = RootComponent()({
properties: {
_age: Number as SpecificType<number>,
_age: Number as DetailedType<number>,
},
computed: {
age() {
Expand Down
51 changes: 43 additions & 8 deletions doc/demo/page.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,66 @@
import type { User } from "../../jest/common";
import { DefineComponent, RootComponent, type SpecificType, SubComponent } from "../../src";
import { observable } from "mobx";
import { DefineComponent, type DetailedType, RootComponent, SubComponent } from "../../src";
import type { CompA } from "./componentA";
import type { User } from "./types";

const compA = SubComponent<RootDoc, CompA>()({
const compA = SubComponent<Root, CompA>()({
computed: {
subA_user() {
return this.data.user;
},
},
});

type RootDoc = typeof rootComponent;
// 根组件类型
type Root = typeof rootComponent;

const cart = observable({
count: 1,
add() {
this.count++;
},
});

const rootComponent = RootComponent()({
// 表示组件是否为页面,可选,默认false
isPage: true,

properties: {
user: Object as SpecificType<User>,
// 通过DetailedType明确具体类型。
user: Object as DetailedType<User>,
},
data: {
num: 1,
},
store: {
// store数据使用箭头函数写法
goodsCount: () => cart.count,
},
computed: {
age() {
return this.data.user.age;
// 计算属性字段 可对所有数据计算
goodsCountAddNum() {
return this.data.goodsCount + this.data.num;
},
},
// 事件和方法分离书写的
events: {
onTap() {
// 调用store方法,修改store数据
cart.add();

// 组件store数据自动相应
console.log(this.data.goodsCount === 2); // true
},
},
watch: {
goodsCountAddNum(newValue: number, oldValue: number) {
console.log(newValue, oldValue); // 3 2
},
},
});

DefineComponent({
path: "/pages/index/index",
path: "/pages/path",
rootComponent,
subComponents: [compA],
});
2 changes: 1 addition & 1 deletion doc/demo/types → doc/demo/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export interface User {
name: string;
age: number;
}
}
8 changes: 4 additions & 4 deletions jest/computed/asyncProperties/asyncProperties.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefineComponent, RootComponent, type SpecificType, SubComponent } from "../../../src";
import { DefineComponent, type DetailedType, RootComponent, SubComponent } from "../../../src";
import { type CompDoc, type User, user } from "../../common";

const subA = SubComponent<Root, CompDoc>()({
Expand All @@ -17,13 +17,13 @@ type Root = typeof rootComponent;

const rootComponent = RootComponent()({
properties: {
requiredUser: Object as SpecificType<User>,
requiredUser: Object as DetailedType<User>,
optionalUser: {
type: Object as SpecificType<User>,
type: Object as DetailedType<User>,
value: user,
},
optionalUser1: {
type: Object as SpecificType<{ user: { user: User } }>,
type: Object as DetailedType<{ user: { user: User } }>,
value: { user: { user } },
},
},
Expand Down
6 changes: 3 additions & 3 deletions jest/computed/syncProperties/syncProperties.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefineComponent, RootComponent, type SpecificType, SubComponent } from "../../../src";
import { DefineComponent, type DetailedType, RootComponent, SubComponent } from "../../../src";
import { type CompDoc, type User, user } from "../../common";

const subA = SubComponent<Root, CompDoc>()({
Expand All @@ -17,9 +17,9 @@ type Root = typeof rootComponent;

const rootComponent = RootComponent()({
properties: {
requiredUser: Object as SpecificType<User>,
requiredUser: Object as DetailedType<User>,
optionalUser: {
type: Object as SpecificType<User>,
type: Object as DetailedType<User>,
value: user,
},
},
Expand Down
4 changes: 2 additions & 2 deletions jest/customEvents/customEvents.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { DefineComponent, RootComponent, type SpecificType } from "../../src";
import { DefineComponent, type DetailedType, RootComponent } from "../../src";
import type { User } from "../common";

const rootComponent = RootComponent()({
customEvents: {
str: String,
union: {
detailType: [Array as SpecificType<string[]>, Object as SpecificType<User>],
detail: [Array as DetailedType<string[]>, Object as DetailedType<User>],
options: { bubbles: true },
},
},
Expand Down
4 changes: 2 additions & 2 deletions jest/watch/properties/properties.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefineComponent, RootComponent, type SpecificType, SubComponent } from "../../../src";
import { DefineComponent, type DetailedType, RootComponent, SubComponent } from "../../../src";

type User = { name: string; age: number };

Expand All @@ -25,7 +25,7 @@ type Root = typeof rootComponent;
const rootComponent = RootComponent()({
properties: {
num: Number,
user: Object as SpecificType<User>,
user: Object as DetailedType<User>,
},

watch: {
Expand Down
24 changes: 12 additions & 12 deletions src/api/DefineComponent/ReturnType/test/normalComponentDoc.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Checking, type Test } from "hry-types";
import { type ComputeIntersectionDeep } from "hry-types/src/Object/ComputeIntersectionDeep";
import { RootComponent, type SpecificType } from "../../../..";
import { type DetailedType, RootComponent } from "../../../..";
import type { CustomEventConstraint } from "../../../RootComponent/CustomEvents/CustomEventConstraint";
import type {
Bubbles,
Expand All @@ -20,43 +20,43 @@ import { DefineComponent } from "../..";

const properties = {
str: String,
obj: Object as SpecificType<Mock_User>,
obj: Object as DetailedType<Mock_User>,
optionalObj: {
type: Object as SpecificType<Mock_User>,
type: Object as DetailedType<Mock_User>,
value: {} as Mock_User,
},
optionalObjOrNull: {
type: Object as SpecificType<Mock_User | null>,
type: Object as DetailedType<Mock_User | null>,
value: null,
},
} satisfies PropertiesConstraint;
const customEvents = {
str: String,
null: null,
unionStr: String as SpecificType<"male" | "female">,
list: [String, Number as SpecificType<0 | 1 | 2>, null],
unionStr: String as DetailedType<"male" | "female">,
list: [String, Number as DetailedType<0 | 1 | 2>, null],
bubbles: {
detailType: String,
detail: String,
options: { bubbles: true },
},
capturePhase: {
detailType: null,
detail: null,
options: { capturePhase: true },
},
bubbles_capturePhase: {
detailType: [String, Number],
detail: [String, Number],
options: { bubbles: true, capturePhase: true },
},
bubbles_composed: {
detailType: String as SpecificType<"male" | "female">,
detail: String as DetailedType<"male" | "female">,
options: { bubbles: true, composed: true },
},
capturePhase_composed: {
detailType: [String, Number as SpecificType<0 | 1 | 2>, null],
detail: [String, Number as DetailedType<0 | 1 | 2>, null],
options: { capturePhase: true, composed: true },
},
bubbles_capturePhase_composed: {
detailType: Boolean,
detail: Boolean,
options: { bubbles: true, capturePhase: true, composed: true },
},
} satisfies CustomEventConstraint;
Expand Down
8 changes: 4 additions & 4 deletions src/api/DefineComponent/ReturnType/test/normalPageDoc.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Checking, type Test } from "hry-types";
import { RootComponent, type SpecificType } from "../../../..";
import { type DetailedType, RootComponent } from "../../../..";

import type { Mock_User } from "../../../RootComponent/Properties/test/normalRequired.test";
import { DefineComponent } from "../..";
Expand All @@ -8,13 +8,13 @@ const OnlyPropsRootDoc = RootComponent()({
isPage: true,
properties: {
str: String,
obj: Object as SpecificType<Mock_User>,
obj: Object as DetailedType<Mock_User>,
optionalObj: {
type: Object as SpecificType<Mock_User>,
type: Object as DetailedType<Mock_User>,
value: {} as Mock_User,
},
optionalObjOrNull: {
type: Object as SpecificType<Mock_User | null>,
type: Object as DetailedType<Mock_User | null>,
value: null,
},
},
Expand Down
4 changes: 2 additions & 2 deletions src/api/RootComponent/Computed/test/normal.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Checking, type Test } from "hry-types";
import type { ReadonlyDeep } from "hry-types/src/Any/_api";
import type { SpecificType } from "../../../../types/SpecificType";
import type { DetailedType } from "../../../../types/DetailedType";
import { RootComponent } from "../..";
import type { Mock_User } from "../../Properties/test/normalRequired.test";

Expand Down Expand Up @@ -88,7 +88,7 @@ Checking<typeof EmptyComputedFieldDoc, { methods: { M1: () => void } }, Test.Pas
RootComponent()({
isPage: true,
properties: {
obj: Object as SpecificType<{ name: string; age: number }>,
obj: Object as DetailedType<{ name: string; age: number }>,
},
computed: {
age() {
Expand Down

0 comments on commit b56a920

Please sign in to comment.