nine-9 1.11.0 → 1.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -47
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -915
- package/package.json +3 -2
- package/dist/index.js.map +0 -1
- package/dist/test.d.ts +0 -2
- package/dist/test.js +0 -823
- package/dist/test.js.map +0 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
一个轻量、高性能、类型安全的 Vanilla DOM 响应式 UI 框架。
|
|
4
4
|
|
|
5
5
|
融合了 Vue 模板指令和 React Hooks 的优点,取两者之长。
|
|
6
|
-
同时运行及其轻量,甚至打包后可以用于
|
|
6
|
+
同时运行及其轻量,甚至打包后可以用于 **UserScript**。
|
|
7
7
|
|
|
8
8
|
## 特性
|
|
9
9
|
|
|
@@ -25,67 +25,119 @@ npm install nine-9
|
|
|
25
25
|
## 示例用法
|
|
26
26
|
|
|
27
27
|
```typescript
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
//Selector.ts
|
|
29
|
+
|
|
30
|
+
import {
|
|
31
|
+
$,
|
|
32
|
+
createComponent,
|
|
33
|
+
defineEvent,
|
|
34
|
+
defineSlot,
|
|
35
|
+
defineTemplate,
|
|
36
|
+
typed,
|
|
37
|
+
styleSet,
|
|
38
|
+
sync,
|
|
39
|
+
tree,
|
|
40
|
+
when,
|
|
41
|
+
wrap
|
|
42
|
+
} from "@";
|
|
43
|
+
|
|
44
|
+
export default createComponent({
|
|
32
45
|
props: {
|
|
33
|
-
|
|
34
|
-
validate:
|
|
35
|
-
transform:
|
|
36
|
-
required:
|
|
37
|
-
shadow:
|
|
38
|
-
downloadable: true,
|
|
39
|
-
uploadable:
|
|
46
|
+
items: {
|
|
47
|
+
validate: Array.isArray, //验证参数是否合法
|
|
48
|
+
transform: typed<string[]>(), //将输入的参数进行标准化,typed()函数不进行任何处理,只是类型投射
|
|
49
|
+
required: true, //参数是否必填
|
|
50
|
+
shadow: ["OptionA", "OptionB", "OptionC"], //默认值
|
|
51
|
+
downloadable: true, //是否可下载,即上游组件向下游传递值
|
|
52
|
+
uploadable: false //是否可上传,即下游组件向上游传递值
|
|
53
|
+
},
|
|
54
|
+
value: {
|
|
55
|
+
transform: Number,
|
|
56
|
+
uploadable: true, //组件的参数🉑上传,即v-model
|
|
57
|
+
required: true
|
|
40
58
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
59
|
+
},
|
|
60
|
+
events: [
|
|
61
|
+
defineEvent("select", {
|
|
62
|
+
template: defineTemplate<number>() //定义事件被触发时需要传递的数据类型
|
|
63
|
+
}),
|
|
64
|
+
defineEvent("toggleState", { template: defineTemplate<boolean>() })
|
|
65
|
+
],
|
|
66
|
+
styles: [ //这些样式会被封装在组件所在的DOM域
|
|
67
|
+
styleSet(".item")
|
|
68
|
+
.backgroundColor("blue")
|
|
69
|
+
.color("white"),
|
|
70
|
+
styleSet(".flexdown")
|
|
71
|
+
.display("flex")
|
|
72
|
+
.flexDirection("column")
|
|
73
|
+
],
|
|
74
|
+
slots: [
|
|
75
|
+
defineSlot("title", {
|
|
76
|
+
template: defineTemplate<string>(), //插槽作用域传值的数据类型
|
|
77
|
+
required: false, //插槽是否必填
|
|
78
|
+
})
|
|
79
|
+
]
|
|
80
|
+
}, (props, slot, emit) => {
|
|
81
|
+
const showing = wrap(false); //ref包装一个数据,基于事件订阅的响应式系统
|
|
82
|
+
const text = sync(() => //computed同步一个数据,任何一个依赖更新时都会引起自身的重新渲染
|
|
83
|
+
props.items.get()[props.value.get()]
|
|
84
|
+
, [props.items, props.value]); //🉑灵活的配置依赖列表
|
|
85
|
+
|
|
86
|
+
const select = (index: number) => {
|
|
87
|
+
props.value.set(index);
|
|
88
|
+
showing.set(false);
|
|
89
|
+
emit("select", props.value.get());
|
|
90
|
+
};
|
|
91
|
+
showing.event.subcribe(e => { //订阅一个包装器的更新事件
|
|
92
|
+
emit("toggleState", e); //发布组件的自定义事件
|
|
93
|
+
});
|
|
94
|
+
|
|
44
95
|
return tree("div")
|
|
45
|
-
.
|
|
96
|
+
.class("flexdown")
|
|
97
|
+
.ariaAtomic("false")
|
|
46
98
|
.append(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.
|
|
50
|
-
.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
), //条件渲染v-if
|
|
99
|
+
tree("span")
|
|
100
|
+
.class("item")
|
|
101
|
+
.use(styleSet().backgroundColor("red")) //通过style赋值
|
|
102
|
+
.append(
|
|
103
|
+
tree("div").append($(text)), //引用响应式包装器的值
|
|
104
|
+
slot.title(text) //像正常元素一样,把插槽查到想要的位置(参数类型在定义时给出)
|
|
105
|
+
)
|
|
106
|
+
.on("click", () => showing.set(!showing.get())),
|
|
107
|
+
when(showing, () =>
|
|
108
|
+
tree("div")
|
|
109
|
+
.class("flexdown")
|
|
110
|
+
.append(
|
|
111
|
+
$(sync(() => //只要包装器返回的数据可以被渲染,就可以通过$函数进行引用
|
|
112
|
+
props.items.get().map((label, index) =>
|
|
113
|
+
tree("span")
|
|
114
|
+
.class("item")
|
|
115
|
+
.append(label)
|
|
116
|
+
.on("click", () => select(index))
|
|
117
|
+
), [props.items]))
|
|
118
|
+
)
|
|
119
|
+
)
|
|
69
120
|
);
|
|
70
121
|
});
|
|
71
122
|
```
|
|
72
123
|
|
|
73
124
|
## 与 Vue 对比
|
|
74
125
|
|
|
75
|
-
| nine-9
|
|
76
|
-
|
|
77
|
-
| `wrap()`
|
|
78
|
-
| `sync()`
|
|
79
|
-
| `when(condition, tree)`
|
|
80
|
-
| `sync(() =>
|
|
81
|
-
| `Property.uploadable`
|
|
126
|
+
| nine-9 | Vue | 说明 |
|
|
127
|
+
|--------------------------|--------------|----------------|
|
|
128
|
+
| `wrap()` | `ref()` | 创建响应式引用 |
|
|
129
|
+
| `sync()` | `computed()` | 响应式计算值 |
|
|
130
|
+
| `when(condition, tree)` | `v-if` | 条件渲染 |
|
|
131
|
+
| `sync(() => Array<...>)` | `v-for` | 列表渲染 |
|
|
132
|
+
| `Property.uploadable` | `v-model` | 双向绑定 |
|
|
82
133
|
|
|
83
134
|
## 运行时特性
|
|
84
135
|
|
|
85
136
|
### 性能
|
|
86
137
|
|
|
87
|
-
1.
|
|
88
|
-
2. 框架处理动态的节点树时,本质上是通过对新旧节点的CRUD
|
|
138
|
+
1. 框架不需要使用 **Runtime** 伴随运行,也无需通过虚拟节点定义,编译结果非常轻量。
|
|
139
|
+
2. 框架处理动态的节点树时,本质上是通过对新旧节点的CRUD实现。由于不需要分析diff树,刷新组件的节点树时完全采用原生DOM操作命令,所以替换树的效率极其高。
|
|
140
|
+
3. 框架的一切状态都是事件驱动的,只要包装器事件触发就能引起App视图更新。编写自定义的响应式封装器也相当灵活。
|
|
89
141
|
|
|
90
142
|
## 贡献指南
|
|
91
143
|
|
package/dist/index.d.ts
CHANGED
|
@@ -199,8 +199,12 @@ declare const _default: {
|
|
|
199
199
|
}, (EventDescriptor<string, "up"> | EventDescriptor<number, "down">)[], SlotDescriptor[]>;
|
|
200
200
|
Selector: Component<{
|
|
201
201
|
items: {
|
|
202
|
+
validate: (arg: any) => arg is any[];
|
|
202
203
|
transform: PropertyTransformer<unknown, string[]>;
|
|
204
|
+
required: true;
|
|
203
205
|
shadow: string[];
|
|
206
|
+
downloadable: true;
|
|
207
|
+
uploadable: false;
|
|
204
208
|
};
|
|
205
209
|
value: {
|
|
206
210
|
transform: NumberConstructor;
|