glass-easel 0.1.0
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 +40 -0
- package/dist/glass_easel.all.d.ts +1 -0
- package/dist/glass_easel.all.js +2 -0
- package/dist/glass_easel.all.js.map +1 -0
- package/dist/glass_easel.domlike.global.d.ts +1 -0
- package/dist/glass_easel.domlike.global.js +2 -0
- package/dist/glass_easel.domlike.global.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/types/src/backend/backend_protocol.d.ts +119 -0
- package/dist/types/src/backend/backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/composed_backend_protocol.d.ts +90 -0
- package/dist/types/src/backend/composed_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/domlike_backend_protocol.d.ts +76 -0
- package/dist/types/src/backend/domlike_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/mode.d.ts +46 -0
- package/dist/types/src/backend/mode.d.ts.map +1 -0
- package/dist/types/src/backend/suggested_backend_protocol.d.ts +30 -0
- package/dist/types/src/backend/suggested_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/behavior.d.ts +428 -0
- package/dist/types/src/behavior.d.ts.map +1 -0
- package/dist/types/src/class_list.d.ts +79 -0
- package/dist/types/src/class_list.d.ts.map +1 -0
- package/dist/types/src/component.d.ts +291 -0
- package/dist/types/src/component.d.ts.map +1 -0
- package/dist/types/src/component_params.d.ts +239 -0
- package/dist/types/src/component_params.d.ts.map +1 -0
- package/dist/types/src/component_space.d.ts +164 -0
- package/dist/types/src/component_space.d.ts.map +1 -0
- package/dist/types/src/data_path.d.ts +5 -0
- package/dist/types/src/data_path.d.ts.map +1 -0
- package/dist/types/src/data_proxy.d.ts +107 -0
- package/dist/types/src/data_proxy.d.ts.map +1 -0
- package/dist/types/src/data_utils.d.ts +3 -0
- package/dist/types/src/data_utils.d.ts.map +1 -0
- package/dist/types/src/element.d.ts +275 -0
- package/dist/types/src/element.d.ts.map +1 -0
- package/dist/types/src/element_iterator.d.ts +43 -0
- package/dist/types/src/element_iterator.d.ts.map +1 -0
- package/dist/types/src/event.d.ts +104 -0
- package/dist/types/src/event.d.ts.map +1 -0
- package/dist/types/src/external_shadow_tree.d.ts +20 -0
- package/dist/types/src/external_shadow_tree.d.ts.map +1 -0
- package/dist/types/src/func_arr.d.ts +39 -0
- package/dist/types/src/func_arr.d.ts.map +1 -0
- package/dist/types/src/global_options.d.ts +111 -0
- package/dist/types/src/global_options.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +43 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/mutation_observer.d.ts +79 -0
- package/dist/types/src/mutation_observer.d.ts.map +1 -0
- package/dist/types/src/native_node.d.ts +8 -0
- package/dist/types/src/native_node.d.ts.map +1 -0
- package/dist/types/src/node.d.ts +49 -0
- package/dist/types/src/node.d.ts.map +1 -0
- package/dist/types/src/relation.d.ts +47 -0
- package/dist/types/src/relation.d.ts.map +1 -0
- package/dist/types/src/render.d.ts +3 -0
- package/dist/types/src/render.d.ts.map +1 -0
- package/dist/types/src/selector.d.ts +32 -0
- package/dist/types/src/selector.d.ts.map +1 -0
- package/dist/types/src/shadow_root.d.ts +136 -0
- package/dist/types/src/shadow_root.d.ts.map +1 -0
- package/dist/types/src/template_engine.d.ts +18 -0
- package/dist/types/src/template_engine.d.ts.map +1 -0
- package/dist/types/src/text_node.d.ts +32 -0
- package/dist/types/src/text_node.d.ts.map +1 -0
- package/dist/types/src/tmpl/index.d.ts +18 -0
- package/dist/types/src/tmpl/index.d.ts.map +1 -0
- package/dist/types/src/tmpl/native_rendering.d.ts +45 -0
- package/dist/types/src/tmpl/native_rendering.d.ts.map +1 -0
- package/dist/types/src/tmpl/proc_gen_wrapper.d.ts +80 -0
- package/dist/types/src/tmpl/proc_gen_wrapper.d.ts.map +1 -0
- package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts +50 -0
- package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts.map +1 -0
- package/dist/types/src/tmpl/range_list_diff.d.ts +19 -0
- package/dist/types/src/tmpl/range_list_diff.d.ts.map +1 -0
- package/dist/types/src/trait_behaviors.d.ts +38 -0
- package/dist/types/src/trait_behaviors.d.ts.map +1 -0
- package/dist/types/src/virtual_node.d.ts +10 -0
- package/dist/types/src/virtual_node.d.ts.map +1 -0
- package/dist/types/tests/backend/domlike.test.d.ts +2 -0
- package/dist/types/tests/backend/domlike.test.d.ts.map +1 -0
- package/dist/types/tests/base/env.d.ts +29 -0
- package/dist/types/tests/base/env.d.ts.map +1 -0
- package/dist/types/tests/base/match.d.ts +9 -0
- package/dist/types/tests/base/match.d.ts.map +1 -0
- package/dist/types/tests/core/backend.test.d.ts +2 -0
- package/dist/types/tests/core/backend.test.d.ts.map +1 -0
- package/dist/types/tests/core/behavior.test.d.ts +2 -0
- package/dist/types/tests/core/behavior.test.d.ts.map +1 -0
- package/dist/types/tests/core/component_space.test.d.ts +2 -0
- package/dist/types/tests/core/component_space.test.d.ts.map +1 -0
- package/dist/types/tests/core/data_update.test.d.ts +2 -0
- package/dist/types/tests/core/data_update.test.d.ts.map +1 -0
- package/dist/types/tests/core/misc.test.d.ts +2 -0
- package/dist/types/tests/core/misc.test.d.ts.map +1 -0
- package/dist/types/tests/core/placeholder.test.d.ts +2 -0
- package/dist/types/tests/core/placeholder.test.d.ts.map +1 -0
- package/dist/types/tests/core/slot.test.d.ts +2 -0
- package/dist/types/tests/core/slot.test.d.ts.map +1 -0
- package/dist/types/tests/core/trait_behaviors.test.d.ts +2 -0
- package/dist/types/tests/core/trait_behaviors.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/binding_map.test.d.ts +2 -0
- package/dist/types/tests/tmpl/binding_map.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/event.test.d.ts +2 -0
- package/dist/types/tests/tmpl/event.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/expression.test.d.ts +2 -0
- package/dist/types/tests/tmpl/expression.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/lvalue.test.d.ts +2 -0
- package/dist/types/tests/tmpl/lvalue.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/native_rendering.test.d.ts +2 -0
- package/dist/types/tests/tmpl/native_rendering.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/structure.test.d.ts +2 -0
- package/dist/types/tests/tmpl/structure.test.d.ts.map +1 -0
- package/dist/types/tests/types/chaining.test.d.ts +2 -0
- package/dist/types/tests/types/chaining.test.d.ts.map +1 -0
- package/dist/types/tests/types/createElement.test.d.ts +2 -0
- package/dist/types/tests/types/createElement.test.d.ts.map +1 -0
- package/dist/types/tests/types/definition.test.d.ts +2 -0
- package/dist/types/tests/types/definition.test.d.ts.map +1 -0
- package/guide/zh_CN/advanced/binding_map_update.md +32 -0
- package/guide/zh_CN/advanced/build_args.md +28 -0
- package/guide/zh_CN/advanced/component_filter.md +70 -0
- package/guide/zh_CN/advanced/component_space.md +124 -0
- package/guide/zh_CN/advanced/custom_backend.md +53 -0
- package/guide/zh_CN/advanced/error_listener.md +32 -0
- package/guide/zh_CN/advanced/external_component.md +73 -0
- package/guide/zh_CN/advanced/template_engine.md +61 -0
- package/guide/zh_CN/appendix/backend_protocol.md +501 -0
- package/guide/zh_CN/appendix/list_diff_algorithm.md +406 -0
- package/guide/zh_CN/basic/beginning.md +94 -0
- package/guide/zh_CN/basic/component.md +156 -0
- package/guide/zh_CN/basic/event.md +169 -0
- package/guide/zh_CN/basic/lifetime.md +66 -0
- package/guide/zh_CN/basic/method.md +62 -0
- package/guide/zh_CN/basic/template.md +135 -0
- package/guide/zh_CN/data_management/advanced_update.md +170 -0
- package/guide/zh_CN/data_management/data_deep_copy.md +157 -0
- package/guide/zh_CN/data_management/data_observer.md +154 -0
- package/guide/zh_CN/data_management/property_early_init.md +31 -0
- package/guide/zh_CN/data_management/pure_data_pattern.md +21 -0
- package/guide/zh_CN/index.md +93 -0
- package/guide/zh_CN/interaction/behavior.md +52 -0
- package/guide/zh_CN/interaction/component_path.md +37 -0
- package/guide/zh_CN/interaction/generic.md +73 -0
- package/guide/zh_CN/interaction/placeholder.md +40 -0
- package/guide/zh_CN/interaction/relation.md +151 -0
- package/guide/zh_CN/interaction/slot.md +137 -0
- package/guide/zh_CN/interaction/template_import.md +94 -0
- package/guide/zh_CN/interaction/trait_behavior.md +117 -0
- package/guide/zh_CN/styling/external_class.md +46 -0
- package/guide/zh_CN/styling/style_isolation.md +54 -0
- package/guide/zh_CN/styling/virtual_host.md +52 -0
- package/guide/zh_CN/tree/element_iterator.md +54 -0
- package/guide/zh_CN/tree/mutation_observer.md +52 -0
- package/guide/zh_CN/tree/node_tree.md +142 -0
- package/guide/zh_CN/tree/node_tree_modification.md +78 -0
- package/guide/zh_CN/tree/selector.md +66 -0
- package/jest.config.js +6 -0
- package/jest.dts.config.js +9 -0
- package/jest.unit.config.js +14 -0
- package/package.json +28 -0
- package/src/backend/backend_protocol.ts +313 -0
- package/src/backend/composed_backend_protocol.ts +252 -0
- package/src/backend/domlike_backend_protocol.ts +370 -0
- package/src/backend/mode.ts +51 -0
- package/src/backend/suggested_backend_protocol.ts +83 -0
- package/src/behavior.ts +1655 -0
- package/src/bootstrap_dom_dev.js +22 -0
- package/src/class_list.ts +376 -0
- package/src/component.ts +1309 -0
- package/src/component_params.ts +461 -0
- package/src/component_space.ts +547 -0
- package/src/data_path.ts +225 -0
- package/src/data_proxy.ts +670 -0
- package/src/data_utils.ts +50 -0
- package/src/element.ts +1966 -0
- package/src/element_iterator.ts +158 -0
- package/src/event.ts +401 -0
- package/src/external_shadow_tree.ts +27 -0
- package/src/func_arr.ts +198 -0
- package/src/global_options.ts +242 -0
- package/src/index.ts +187 -0
- package/src/mutation_observer.ts +252 -0
- package/src/native_node.ts +74 -0
- package/src/node.ts +174 -0
- package/src/relation.ts +380 -0
- package/src/render.ts +25 -0
- package/src/selector.ts +218 -0
- package/src/shadow_root.ts +766 -0
- package/src/template_engine.ts +45 -0
- package/src/text_node.ts +149 -0
- package/src/tmpl/index.ts +199 -0
- package/src/tmpl/native_rendering.ts +175 -0
- package/src/tmpl/proc_gen_wrapper.ts +954 -0
- package/src/tmpl/proc_gen_wrapper_dom.ts +230 -0
- package/src/tmpl/range_list_diff.ts +443 -0
- package/src/trait_behaviors.ts +51 -0
- package/src/virtual_node.ts +51 -0
- package/tests/backend/domlike.test.ts +254 -0
- package/tests/base/env.ts +78 -0
- package/tests/base/match.ts +185 -0
- package/tests/core/backend.test.ts +144 -0
- package/tests/core/behavior.test.ts +546 -0
- package/tests/core/component_space.test.ts +212 -0
- package/tests/core/data_update.test.ts +461 -0
- package/tests/core/misc.test.ts +339 -0
- package/tests/core/placeholder.test.ts +180 -0
- package/tests/core/slot.test.ts +1495 -0
- package/tests/core/trait_behaviors.test.ts +153 -0
- package/tests/legacy/README.md +3 -0
- package/tests/legacy/behavior.test.js +293 -0
- package/tests/legacy/component.test.js +1247 -0
- package/tests/legacy/data_path.test.js +149 -0
- package/tests/legacy/data_proxy.test.js +759 -0
- package/tests/legacy/element_iterator.test.js +148 -0
- package/tests/legacy/event.test.js +849 -0
- package/tests/legacy/external.test.js +510 -0
- package/tests/legacy/extra_info.test.js +109 -0
- package/tests/legacy/generics.test.js +176 -0
- package/tests/legacy/mutation_observer.test.js +210 -0
- package/tests/legacy/relation.test.js +517 -0
- package/tests/legacy/selector.test.js +263 -0
- package/tests/legacy/slot.test.js +915 -0
- package/tests/legacy/virtual.test.js +394 -0
- package/tests/tmpl/binding_map.test.ts +208 -0
- package/tests/tmpl/event.test.ts +206 -0
- package/tests/tmpl/expression.test.ts +429 -0
- package/tests/tmpl/lvalue.test.ts +160 -0
- package/tests/tmpl/native_rendering.test.ts +155 -0
- package/tests/tmpl/structure.test.ts +998 -0
- package/tests/types/chaining.test.ts +614 -0
- package/tests/types/createElement.test.ts +82 -0
- package/tests/types/definition.test.ts +442 -0
- package/tsconfig.json +11 -0
- package/webpack.config.js +270 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# 事件
|
|
2
|
+
|
|
3
|
+
## 触发事件
|
|
4
|
+
|
|
5
|
+
子组件可以向父组件发送事件,事件中可以携带数据。这是子组件向父组件传递消息和数据的主要方式。
|
|
6
|
+
|
|
7
|
+
子组件触发事件时应使用组件实例的 `this.triggerEvent` 方法。例如:
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
export const childComponent = componentSpace.defineComponent({
|
|
11
|
+
lifetimes: {
|
|
12
|
+
attached() {
|
|
13
|
+
// 事件携带的数据
|
|
14
|
+
const detail = { someData: 'data' }
|
|
15
|
+
// 触发事件
|
|
16
|
+
this.triggerEvent('customEvent', detail)
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
事件的可以指定为不冒泡事件(默认)、冒泡事件或跨组件冒泡事件,由 `triggerEvent` 的第三个参数控制,例如:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
// 触发冒泡事件(冒泡范围仅限于父组件内部)
|
|
26
|
+
this.triggerEvent('customEvent', detail, { bubbles: true })
|
|
27
|
+
// 触发跨组件冒泡事件
|
|
28
|
+
this.triggerEvent('customEvent', detail, { bubbles: true, composed: true })
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
在 DOM 环境下, glass-easel 也会自动触发 DOM 事件。
|
|
32
|
+
|
|
33
|
+
## 用普通组件方法响应事件
|
|
34
|
+
|
|
35
|
+
`methods` 内定义的方法可以用于响应事件。例如:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
// 使用 Definition API 响应事件
|
|
39
|
+
export const myComponent = componentSpace.defineComponent({
|
|
40
|
+
using: {
|
|
41
|
+
child: childComponent,
|
|
42
|
+
},
|
|
43
|
+
template: compileTemplate(`
|
|
44
|
+
<child catch:customEvent="childEvent" />
|
|
45
|
+
`),
|
|
46
|
+
methods: {
|
|
47
|
+
childEvent({ detail }) {
|
|
48
|
+
detail.someData === 'data' // true
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
// 或使用 Chaining API 响应事件
|
|
53
|
+
export const myComponent = componentSpace.define()
|
|
54
|
+
.usingComponents({
|
|
55
|
+
child: childComponent,
|
|
56
|
+
})
|
|
57
|
+
.template(compileTemplate(`
|
|
58
|
+
<child catch:customEvent="childEvent" />
|
|
59
|
+
`))
|
|
60
|
+
.methods({
|
|
61
|
+
childEvent({ detail }) {
|
|
62
|
+
detail.someData === 'data' // true
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
.registerComponent()
|
|
66
|
+
// 或在 init 中响应事件
|
|
67
|
+
export const myComponent = componentSpace.define()
|
|
68
|
+
.template(compileTemplate(`
|
|
69
|
+
<child catch:customEvent="childEvent" />
|
|
70
|
+
`))
|
|
71
|
+
.init(function ({ method }) {
|
|
72
|
+
const childEvent = method(({ detail }) => {
|
|
73
|
+
detail.someData === 'data' // true
|
|
74
|
+
})
|
|
75
|
+
return { childEvent }
|
|
76
|
+
})
|
|
77
|
+
.registerComponent()
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 用 init 响应事件
|
|
81
|
+
|
|
82
|
+
如果使用 init ,也可以用 `listener` 包裹函数后将响应函数返回来响应事件。
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
export const myComponent = componentSpace.define()
|
|
86
|
+
.template(compileTemplate(`
|
|
87
|
+
<child catch:customEvent="childEvent" />
|
|
88
|
+
`))
|
|
89
|
+
.init(function ({ method }) {
|
|
90
|
+
const childEvent = listener(({ detail }) => {
|
|
91
|
+
detail.someData === 'data' // true
|
|
92
|
+
})
|
|
93
|
+
return { childEvent }
|
|
94
|
+
})
|
|
95
|
+
.registerComponent()
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
这样做的好处是,如果使用 TypeScript ,可以方便地指定 `detail` 数据类型:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
.init(function ({ method }) {
|
|
102
|
+
const childEvent = listener<{ someData: string }>(({ detail }) => {
|
|
103
|
+
detail.someData === 'data' // true
|
|
104
|
+
})
|
|
105
|
+
return { childEvent }
|
|
106
|
+
})
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## 绑定前缀
|
|
110
|
+
|
|
111
|
+
在模板中绑定事件时,除了 `catch:` 前缀,还可以使用 `bind:` 前缀,例如:
|
|
112
|
+
|
|
113
|
+
```xml
|
|
114
|
+
<div bind:customEvent="childEvent2">
|
|
115
|
+
<child bind:customEvent="childEvent1" />
|
|
116
|
+
</div>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`bind:` 的区别是它不会停止事件冒泡,使得节点的祖先也能够响应这个事件。(对于非冒泡事件,两者效果相同。)
|
|
120
|
+
|
|
121
|
+
为了保持与微信小程序 WXML 的兼容性, `catch:` 和 `bind:` 中的冒号 `:` 可以省略,但并不建议。
|
|
122
|
+
|
|
123
|
+
另一个绑定前缀是 `mut-bind:` ,它不会停止事件冒泡,但一个 `mut-bind:` 绑定的函数执行后,其他 `mut-bind:` 绑定的函数不会被执行。换而言之,所有 `mut-bind:` 绑定之间是互斥的。
|
|
124
|
+
|
|
125
|
+
## 事件捕获阶段
|
|
126
|
+
|
|
127
|
+
冒泡事件支持类似于 DOM 事件的捕获阶段。捕获阶段位于普通的冒泡阶段之前,且与冒泡经过的节点顺序正好相反。
|
|
128
|
+
|
|
129
|
+
事件需要具有捕获阶段时,需要指定 `capture` 选项,例如:
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
this.triggerEvent('customEvent', detail, { bubbles: true, capture: true })
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
在捕获阶段绑定响应函数时,可以使用 `capture-catch:` 或 `capture-bind:` ,例如:
|
|
136
|
+
|
|
137
|
+
```xml
|
|
138
|
+
<div capture-bind:customEvent="childEvent2">
|
|
139
|
+
<child capture-catch:customEvent="childEvent1" />
|
|
140
|
+
</div>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## 事件节点标记
|
|
144
|
+
|
|
145
|
+
在 `wx:for` 列表中绑定的事件,常常想要知道它具体是列表中的哪个节点,此时可以使用 `mark:` 为节点加上标记:
|
|
146
|
+
|
|
147
|
+
```xml
|
|
148
|
+
<block wx:for="{{ list }}">
|
|
149
|
+
<child mark:listIndex="{{ index }}" bind:customEvent="childEvent" />
|
|
150
|
+
</block>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
在响应函数中可以访问到:
|
|
154
|
+
|
|
155
|
+
```js
|
|
156
|
+
childEvent({ mark }) {
|
|
157
|
+
mark.listIndex // 列表中的 index
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`mark:` 也可以打在祖先节点上:
|
|
162
|
+
|
|
163
|
+
```xml
|
|
164
|
+
<block wx:for="{{ list }}">
|
|
165
|
+
<div mark:listIndex="{{ index }}">
|
|
166
|
+
<child bind:customEvent="childEvent" />
|
|
167
|
+
</div>
|
|
168
|
+
</block>
|
|
169
|
+
```
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# 生命周期
|
|
2
|
+
|
|
3
|
+
## 普通生命周期
|
|
4
|
+
|
|
5
|
+
组件可以定义一些生命周期回调函数。最常见的是 `attached` 生命周期,它在组件被添加到页面内后立刻触发,例如:
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
// 使用 Definition API 添加生命周期回调函数
|
|
9
|
+
export const myComponent = componentSpace.defineComponent({
|
|
10
|
+
lifetimes: {
|
|
11
|
+
attached() {
|
|
12
|
+
// 组件被添加到页面后触发
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
})
|
|
16
|
+
// 或使用 Chaining API 添加生命周期回调函数
|
|
17
|
+
export const myComponent = componentSpace.define()
|
|
18
|
+
.lifetime('attached', function () {
|
|
19
|
+
// 组件被添加到页面后触发
|
|
20
|
+
})
|
|
21
|
+
.registerComponent()
|
|
22
|
+
// 或在 init 中添加生命周期回调函数
|
|
23
|
+
export const myComponent = componentSpace.define()
|
|
24
|
+
.init(function ({ lifetime }) {
|
|
25
|
+
lifetime('attached', function () {
|
|
26
|
+
// 组件被添加到页面后触发
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
.registerComponent()
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
glass-easel 会自动触发的生命周期列表如下。
|
|
33
|
+
|
|
34
|
+
| 生命周期 | 触发时机 | 触发次数 |
|
|
35
|
+
| -------- | -------- | ------ |
|
|
36
|
+
| `created` | 组件实例刚刚被创建完时触发 | 每个实例触发一次 |
|
|
37
|
+
| `attached` | 组件实例被添加到页面后触发 | 每个实例最多触发一次 |
|
|
38
|
+
| `moved` | 组件实例在节点树中位置被移动后触发 | 只有 `wx:for` 内项目可能触发,次数不定 |
|
|
39
|
+
| `detached` | 组件实例被从页面内移除后触发 | 每个实例最多触发一次 |
|
|
40
|
+
|
|
41
|
+
也可以使用组件实例的 `this.triggerLifetime` 方法来触发生命周期。
|
|
42
|
+
|
|
43
|
+
## 页面生命周期
|
|
44
|
+
|
|
45
|
+
页面生命周期是一类特殊的生命周期。 glass-easel 不会主动触发页面生命周期,只能通过调用组件实例的 `this.triggerPageLifetime` 来触发。
|
|
46
|
+
|
|
47
|
+
触发时,页面生命周期会自动递归到所有子孙组件上。因而它主要用于广播一些全局事件。
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
// 使用 Definition API 添加页面生命周期回调函数
|
|
51
|
+
export const myComponent = componentSpace.defineComponent({
|
|
52
|
+
pageLifetimes: {
|
|
53
|
+
someLifetime() { /* ... */ },
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
// 或使用 Chaining API 添加页面生命周期回调函数
|
|
57
|
+
export const myComponent = componentSpace.define()
|
|
58
|
+
.pageLifetime('someLifetime', function () { /* ... */ })
|
|
59
|
+
.registerComponent()
|
|
60
|
+
// 或在 init 中添加页面生命周期回调函数
|
|
61
|
+
export const myComponent = componentSpace.define()
|
|
62
|
+
.init(function ({ pageLifetime }) {
|
|
63
|
+
pageLifetime('someLifetime', function () { /* ... */ })
|
|
64
|
+
})
|
|
65
|
+
.registerComponent()
|
|
66
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 方法
|
|
2
|
+
|
|
3
|
+
## 普通组件方法
|
|
4
|
+
|
|
5
|
+
可以通过 `methods` 来定义一些能在组件实例 `this` 对象上访问的函数:
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
// 使用 Definition API 添加方法
|
|
9
|
+
export const myComponent = componentSpace.defineComponent({
|
|
10
|
+
methods: {
|
|
11
|
+
aPlusB(a, b) {
|
|
12
|
+
return a + b
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
lifetimes: {
|
|
16
|
+
attached() {
|
|
17
|
+
this.aPlusB(1, 2) === 3 // true
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
// 或使用 Chaining API 添加方法
|
|
22
|
+
export const myComponent = componentSpace.define()
|
|
23
|
+
.methods({
|
|
24
|
+
aPlusB(a, b) {
|
|
25
|
+
return a + b
|
|
26
|
+
},
|
|
27
|
+
})
|
|
28
|
+
.lifetime('attached', function () {
|
|
29
|
+
this.aPlusB(1, 2) === 3 // true
|
|
30
|
+
})
|
|
31
|
+
.registerComponent()
|
|
32
|
+
// 或在 init 中添加方法
|
|
33
|
+
export const myComponent = componentSpace.define()
|
|
34
|
+
.init(function ({ lifetime, method }) {
|
|
35
|
+
const aPlusB = method((a, b) => {
|
|
36
|
+
return a + b
|
|
37
|
+
})
|
|
38
|
+
lifetime('attached', function () {
|
|
39
|
+
this.aPlusB(1, 2) === 3 // true
|
|
40
|
+
})
|
|
41
|
+
// 注意 method 需要返回
|
|
42
|
+
return { aPlusB }
|
|
43
|
+
})
|
|
44
|
+
.registerComponent()
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 使用 init 内函数代替
|
|
48
|
+
|
|
49
|
+
实际上,如果使用 init ,则通常不需要用普通组件方法,直接在 init 中定义函数即可。
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
export const myComponent = componentSpace.define()
|
|
53
|
+
.init(function ({ lifetime }) {
|
|
54
|
+
const aPlusB = (a, b) => a + b
|
|
55
|
+
lifetime('attached', function () {
|
|
56
|
+
aPlusB(1, 2) === 3 // true
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
.registerComponent()
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
这种做法可以让一些私有函数不能通过组件实例 `this` 来访问。
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# 模板
|
|
2
|
+
|
|
3
|
+
glass-easel 模板遵循 WXML 语法。
|
|
4
|
+
|
|
5
|
+
一些语法细节与 HTML 有一定差异。最明显的区别是标签都需要正确闭合,如 `<div></div>` 和 `<div />` 。
|
|
6
|
+
|
|
7
|
+
## 数据绑定
|
|
8
|
+
|
|
9
|
+
在模板中,可以用 `{{ ... }}` 的形式嵌入表达式,表达式中的数据来源于组件的 `data` ,例如:
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
export const addComponent = componentSpace.defineComponent({
|
|
13
|
+
template: compileTemplate(`
|
|
14
|
+
<div>{{ a }} + {{ b }} = {{ a + b }}</div>
|
|
15
|
+
`),
|
|
16
|
+
data: {
|
|
17
|
+
a: 1,
|
|
18
|
+
b: 2,
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
使用组件实例的 `setData` 方法可以更新数据绑定,例如:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
export const addComponent = componentSpace.defineComponent({
|
|
27
|
+
template: compileTemplate(`
|
|
28
|
+
<div>{{ a }} + {{ b }} = {{ a + b }}</div>
|
|
29
|
+
`),
|
|
30
|
+
data: {
|
|
31
|
+
a: 1,
|
|
32
|
+
b: 2,
|
|
33
|
+
},
|
|
34
|
+
lifetimes: {
|
|
35
|
+
attached() {
|
|
36
|
+
this.setData({
|
|
37
|
+
a: 3,
|
|
38
|
+
})
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 条件分支
|
|
45
|
+
|
|
46
|
+
借助 `wx:if` `wx:elif` `wx:else` 可以控制节点的存在与否,例如:
|
|
47
|
+
|
|
48
|
+
```xml
|
|
49
|
+
<div wx:if="{{ a > b }}"> a 大于 b </div>
|
|
50
|
+
<div wx:elif="{{ a < b }}"> a 小于 b </div>
|
|
51
|
+
<div wx:elif="{{ a === b }}"> a 等于 b </div>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
如果想要同时控制多个节点,可以借助 `<block>` 块,例如:
|
|
55
|
+
|
|
56
|
+
```xml
|
|
57
|
+
<block wx:if="{{ a > b }}">
|
|
58
|
+
<span>a</span>
|
|
59
|
+
<span>大于</span>
|
|
60
|
+
<span>b</span>
|
|
61
|
+
</block>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
注意, `<block>` 块不是一个真正的节点,其中不能包含其他属性。
|
|
65
|
+
|
|
66
|
+
## 列表
|
|
67
|
+
|
|
68
|
+
借助 `wx:for` 可以将一个数组展开成一组节点,例如:
|
|
69
|
+
|
|
70
|
+
```xml
|
|
71
|
+
<div wx:for="{{ arr }}">数组的第 {{ index }} 项是 {{ item }}</div>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
这个例子中,如果 `arr` 数组有 3 项,则会最终生成 3 个 `<div>` 。
|
|
75
|
+
|
|
76
|
+
这里也可以借助 `<block>` :
|
|
77
|
+
|
|
78
|
+
```xml
|
|
79
|
+
<block wx:for="{{ arr }}">
|
|
80
|
+
<div>数组的第 {{ index }} 项是 {{ item }}</div>
|
|
81
|
+
</block>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
其中, `index` 和 `item` 是自动生成的临时变量,变量名可以使用 `wx:for-index` 和 `wx:for-item` 来调整:
|
|
85
|
+
|
|
86
|
+
```xml
|
|
87
|
+
<block wx:for="{{ arr }}" wx:for-index="i" wx:for-item="t">
|
|
88
|
+
<div>数组的第 {{ i }} 项是 {{ t }}</div>
|
|
89
|
+
</block>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 带 key 列表
|
|
93
|
+
|
|
94
|
+
在列表数据更新时, glass-easel 会尝试对比新旧列表数据来推断哪些节点应该被增删或移动。
|
|
95
|
+
|
|
96
|
+
如果列表开头或者中间部分需要发生插入或删除, glass-easel 的推断可能不够准确或高效。此时可以提供一个 key 字段来辅助推断。
|
|
97
|
+
|
|
98
|
+
例如对于这样的数据:
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
data: {
|
|
102
|
+
students: [
|
|
103
|
+
{ id: 'A0001', name: '张三' },
|
|
104
|
+
{ id: 'A0002', name: '李四' },
|
|
105
|
+
{ id: 'A0003', name: '王五' },
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
列表中每一项的 `id` 是唯一的、有代表性的,就可以将它作为 key 使用:
|
|
111
|
+
|
|
112
|
+
```xml
|
|
113
|
+
<block wx:for="{{ arr }}" wx:key="id">
|
|
114
|
+
<div>姓名:{{ item.name }}</div>
|
|
115
|
+
</block>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
在复杂的列表中,使用 key 通常可以提升整体性能。但要注意:
|
|
119
|
+
|
|
120
|
+
* 如果每一项的 key 值不是唯一的,会降低使用 key 进行推断效果,不要将唯一性很差的字段作为 key ;
|
|
121
|
+
* 作为 key 的字段会被转换为字符串使用,所以只应使用数值或字符串类型的数据字段;
|
|
122
|
+
* 如果列表项目是固定的,或者只会在末尾增加、删除项目, key 不会有任何帮助(反而会增加少量开销),可以不用。
|
|
123
|
+
|
|
124
|
+
## 转义符
|
|
125
|
+
|
|
126
|
+
在数据绑定以外,应使用 XML Entities 来进行特殊字符的转义。
|
|
127
|
+
|
|
128
|
+
通常情况下只需要转义尖括号,例如 `<` 转义为 `<` :
|
|
129
|
+
|
|
130
|
+
```xml
|
|
131
|
+
<div wx:if="{{ a > b }}"> a > b </div>
|
|
132
|
+
<div wx:elif="{{ a < b }}"> a < b </div>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
数据绑定内部的转义方式与 JavaScript 一致。
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# 高级数据更新方法
|
|
2
|
+
|
|
3
|
+
## 使用 setData 更新模板数据绑定
|
|
4
|
+
|
|
5
|
+
一般情况下,可以使用组件实例的 `this.setData` 来更新数据绑定。
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
export const addComponent = componentSpace.defineComponent({
|
|
9
|
+
template: compileTemplate(`
|
|
10
|
+
<div>{{ a }} + {{ b }} = {{ a + b }}</div>
|
|
11
|
+
`),
|
|
12
|
+
data: {
|
|
13
|
+
a: 1,
|
|
14
|
+
b: 2,
|
|
15
|
+
},
|
|
16
|
+
lifetimes: {
|
|
17
|
+
attached() {
|
|
18
|
+
this.setData({
|
|
19
|
+
a: 3,
|
|
20
|
+
})
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
在使用 Chaning API 时,也可以利用 init 函数这样做:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
export const addComponent = componentSpace.define()
|
|
30
|
+
.template(compileTemplate(`
|
|
31
|
+
<div>{{ a }} + {{ b }} = {{ a + b }}</div>
|
|
32
|
+
`))
|
|
33
|
+
.data(() => ({
|
|
34
|
+
a: 1,
|
|
35
|
+
b: 2,
|
|
36
|
+
}))
|
|
37
|
+
.init(function ({ setData, lifetime }) {
|
|
38
|
+
lifetime('attached', () => {
|
|
39
|
+
// 这种做法可以省略掉 this
|
|
40
|
+
setData({
|
|
41
|
+
a: 3,
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
.registerComponent()
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
setData 支持一些复杂的数据路径,例如:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
export const addComponent = componentSpace.defineComponent({
|
|
52
|
+
data: {
|
|
53
|
+
obj: {
|
|
54
|
+
a: [1, 2],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
lifetimes: {
|
|
58
|
+
attached() {
|
|
59
|
+
this.setData({
|
|
60
|
+
'obj.a[0]': 3,
|
|
61
|
+
})
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 高级路径更新
|
|
68
|
+
|
|
69
|
+
如果想仅更新对象内的一个字段,可以使用高级路径更新的方式。这样虽然接口复杂一些,但可以拥有更好的性能。
|
|
70
|
+
|
|
71
|
+
例如,可以使用 `replaceDataOnPath` 来更新对象内的数据字段:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
export const addComponent = componentSpace.defineComponent({
|
|
75
|
+
data: {
|
|
76
|
+
obj: {
|
|
77
|
+
a: [1, 2],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
lifetimes: {
|
|
81
|
+
attached() {
|
|
82
|
+
// 更新 obj.a 字段
|
|
83
|
+
this.replaceDataOnPath(['obj', 'a', 0], 3)
|
|
84
|
+
// 将更新应用到模板上
|
|
85
|
+
this.applyDataUpdates()
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
如果字段是数组类型的,还可以使用 `spliceArrayDataOnPath` 来对数组项进行插入和删除:
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
export const addComponent = componentSpace.defineComponent({
|
|
95
|
+
data: {
|
|
96
|
+
obj: {
|
|
97
|
+
arr: [1, 2, 3, 4],
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
lifetimes: {
|
|
101
|
+
attached() {
|
|
102
|
+
// 更新 obj.arr 数组:
|
|
103
|
+
// 类似于数组的 splice 方法
|
|
104
|
+
// 可以在一个位置上移除若干项,再插入若干项
|
|
105
|
+
this.spliceArrayDataOnPath(['obj', 'arr'], 1, 2, [5, 6, 7])
|
|
106
|
+
// 得到的 obj.arr 是 [1, 5, 6, 7, 4]
|
|
107
|
+
// 将更新应用到模板上
|
|
108
|
+
this.applyDataUpdates()
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
})
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
调用 `replaceDataOnPath` 和 `spliceArrayDataOnPath` 后,并不会立即将更新内容应用到模板上,还需要调用 `applyDataUpdates` 。如果需要连续调用多个 `replaceDataOnPath` 或 `spliceArrayDataOnPath` ,在末尾调用一次 `applyDataUpdates` 即可。
|
|
115
|
+
|
|
116
|
+
## 组合更新
|
|
117
|
+
|
|
118
|
+
连续调用多个 `replaceDataOnPath` 或 `spliceArrayDataOnPath` 后,可能会遗忘调用 `applyDataUpdates` 。
|
|
119
|
+
|
|
120
|
+
可以考虑改用 `groupUpdates` 将它们组合起来,例如:
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
export const addComponent = componentSpace.defineComponent({
|
|
124
|
+
data: {
|
|
125
|
+
obj: {
|
|
126
|
+
a: 1,
|
|
127
|
+
b: 2,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
lifetimes: {
|
|
131
|
+
attached() {
|
|
132
|
+
// 进行组合更新
|
|
133
|
+
this.groupUpdates(() => {
|
|
134
|
+
this.replaceDataOnPath(['obj', 'a'], 3)
|
|
135
|
+
this.replaceDataOnPath(['obj', 'b'], 5)
|
|
136
|
+
})
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
})
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
在 `groupUpdates` 调用后,会自动将更新应用到模板上,不再需要调用 `applyDataUpdates` 。
|
|
143
|
+
|
|
144
|
+
另外,如果需要将多个 `setData` 调用组合起来,可以使用 `updateData` ,例如:
|
|
145
|
+
|
|
146
|
+
```js
|
|
147
|
+
export const addComponent = componentSpace.defineComponent({
|
|
148
|
+
template: compileTemplate(`
|
|
149
|
+
<div>{{ a }} + {{ b }} = {{ a + b }}</div>
|
|
150
|
+
`),
|
|
151
|
+
data: {
|
|
152
|
+
a: 1,
|
|
153
|
+
b: 2,
|
|
154
|
+
},
|
|
155
|
+
lifetimes: {
|
|
156
|
+
attached() {
|
|
157
|
+
this.groupUpdates(() => {
|
|
158
|
+
this.updateData({
|
|
159
|
+
a: 3,
|
|
160
|
+
})
|
|
161
|
+
this.updateData({
|
|
162
|
+
b: 5,
|
|
163
|
+
})
|
|
164
|
+
})
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
})
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
这种做法性能上优于连续多次 `setData` 。
|