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,157 @@
|
|
|
1
|
+
# 数据字段拷贝控制
|
|
2
|
+
|
|
3
|
+
## 数据深拷贝
|
|
4
|
+
|
|
5
|
+
默认情况下,数据字段应用到模板前,会经过一次深拷贝。这样,无意中对组件实例的 `this.data` 进行的修改,将不会应用到模板上。例如:
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
export const myComponent = componentSpace.defineComponent({
|
|
9
|
+
template: compileTemplate(`
|
|
10
|
+
<div>{{ a }}</div>
|
|
11
|
+
`),
|
|
12
|
+
data: {
|
|
13
|
+
a: 1,
|
|
14
|
+
},
|
|
15
|
+
lifetimes: {
|
|
16
|
+
attached() {
|
|
17
|
+
// 这样进行的更新不会应用到模板上
|
|
18
|
+
this.data.a = 2
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
这样虽然可以提供一些对错误逻辑的保护,但需要进行一次深拷贝。默认情况下,这次深拷贝不支持含有递归字段的数据,例如:
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
export const myComponent = componentSpace.defineComponent({
|
|
28
|
+
data: {
|
|
29
|
+
a: {},
|
|
30
|
+
},
|
|
31
|
+
lifetimes: {
|
|
32
|
+
attached() {
|
|
33
|
+
const a = {}
|
|
34
|
+
a.b = a
|
|
35
|
+
// a 是一个有递归字段的对象
|
|
36
|
+
// 不能用于 setData ,否则会出错!
|
|
37
|
+
this.setData({ a })
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
此时可以更改组件的 `dataDeepCopy` 选项,使其支持递归字段:
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
export const myComponent = componentSpace.defineComponent({
|
|
47
|
+
options: {
|
|
48
|
+
dataDeepCopy: glassEasel.DeepCopyKind.SimpleWithRecursion,
|
|
49
|
+
},
|
|
50
|
+
data: {
|
|
51
|
+
a: {},
|
|
52
|
+
},
|
|
53
|
+
lifetimes: {
|
|
54
|
+
attached() {
|
|
55
|
+
const a = {}
|
|
56
|
+
a.b = a
|
|
57
|
+
this.setData({ a })
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
或者也可以完全禁用拷贝(这需要保证不能直接修改 `this.data` ),这样可以完全避免额外开销、对象的原型链能够保留、性能最优:
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
export const myComponent = componentSpace.defineComponent({
|
|
67
|
+
options: {
|
|
68
|
+
dataDeepCopy: glassEasel.DeepCopyKind.None,
|
|
69
|
+
},
|
|
70
|
+
data: {
|
|
71
|
+
a: {},
|
|
72
|
+
},
|
|
73
|
+
lifetimes: {
|
|
74
|
+
attached() {
|
|
75
|
+
const a = {}
|
|
76
|
+
a.b = a
|
|
77
|
+
this.setData({ a })
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
如果需要改变所有组件的这个选项,考虑更改 [组件空间](../advanced/component_space.md) 中的默认组件选项。
|
|
84
|
+
|
|
85
|
+
## 属性传递深拷贝
|
|
86
|
+
|
|
87
|
+
默认情况下,传递组件属性时,也会经过一次深拷贝。这样可以使得两个组件之间不共享对象、对一个组件的数据变更不会影响另一个组件。
|
|
88
|
+
|
|
89
|
+
但这个行为也会使得含有递归字段的对象在传递时出错。可以通过更改子组件的 `propertyPassingDeepCopy` 选项,使其属性支持递归字段:
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
export const childComponent = componentSpace.defineComponent({
|
|
93
|
+
options: {
|
|
94
|
+
propertyPassingDeepCopy: glassEasel.DeepCopyKind.SimpleWithRecursion,
|
|
95
|
+
},
|
|
96
|
+
properties: {
|
|
97
|
+
a: Object,
|
|
98
|
+
},
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
export const myComponent = componentSpace.defineComponent({
|
|
102
|
+
options: {
|
|
103
|
+
dataDeepCopy: glassEasel.DeepCopyKind.SimpleWithRecursion,
|
|
104
|
+
},
|
|
105
|
+
using: {
|
|
106
|
+
child: childComponent,
|
|
107
|
+
},
|
|
108
|
+
template: compileTemplate(`
|
|
109
|
+
<child a="{{ a }}" />
|
|
110
|
+
`),
|
|
111
|
+
data: {
|
|
112
|
+
a: {},
|
|
113
|
+
},
|
|
114
|
+
lifetimes: {
|
|
115
|
+
attached() {
|
|
116
|
+
const a = {}
|
|
117
|
+
a.b = a
|
|
118
|
+
this.setData({ a })
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
})
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
或者也可以完全禁用拷贝(这需要子组件保证不修改传入的对象),这样可以完全避免额外开销、对象的原型链能够保留、性能最优:
|
|
125
|
+
|
|
126
|
+
```js
|
|
127
|
+
export const childComponent = componentSpace.defineComponent({
|
|
128
|
+
options: {
|
|
129
|
+
propertyPassingDeepCopy: glassEasel.DeepCopyKind.None,
|
|
130
|
+
},
|
|
131
|
+
properties: {
|
|
132
|
+
a: Object,
|
|
133
|
+
},
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
export const myComponent = componentSpace.defineComponent({
|
|
137
|
+
options: {
|
|
138
|
+
dataDeepCopy: glassEasel.DeepCopyKind.None,
|
|
139
|
+
},
|
|
140
|
+
using: {
|
|
141
|
+
child: childComponent,
|
|
142
|
+
},
|
|
143
|
+
template: compileTemplate(`
|
|
144
|
+
<child a="{{ a }}" />
|
|
145
|
+
`),
|
|
146
|
+
data: {
|
|
147
|
+
a: {},
|
|
148
|
+
},
|
|
149
|
+
lifetimes: {
|
|
150
|
+
attached() {
|
|
151
|
+
const a = {}
|
|
152
|
+
a.b = a
|
|
153
|
+
this.setData({ a })
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
})
|
|
157
|
+
```
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# 数据监听器
|
|
2
|
+
|
|
3
|
+
## 监听数据字段变化
|
|
4
|
+
|
|
5
|
+
通过数据监听器,可以在某些属性或数据字段被设置时触发一个函数。
|
|
6
|
+
|
|
7
|
+
例如,可以在 `a` 和 `b` 两个字段中任何一个被设置时,触发一个函数:
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
// 使用 Definition API 添加数据监听器
|
|
11
|
+
export const addComponent = componentSpace.defineComponent({
|
|
12
|
+
template: compileTemplate(`
|
|
13
|
+
<div>{{ a }} + {{ b }} = {{ sum }}</div>
|
|
14
|
+
`),
|
|
15
|
+
data: {
|
|
16
|
+
a: 1,
|
|
17
|
+
b: 2,
|
|
18
|
+
sum: 3,
|
|
19
|
+
},
|
|
20
|
+
// 添加一个数据监听器
|
|
21
|
+
observers: {
|
|
22
|
+
'a, b': function () {
|
|
23
|
+
// 数据监听器中,最好使用 updateData 而非 setData
|
|
24
|
+
// (事实上,使用 setData 将与 updateData 等效)
|
|
25
|
+
// 数据监听器执行完后,会自动将更新应用到模板上
|
|
26
|
+
this.updateData({
|
|
27
|
+
sum: this.data.a + this.data.b,
|
|
28
|
+
})
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
lifetimes: {
|
|
32
|
+
attached() {
|
|
33
|
+
// 执行这个 setData 时,数据监听器会被执行
|
|
34
|
+
this.setData({
|
|
35
|
+
a: 3,
|
|
36
|
+
})
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
// 或使用 Chaining API 添加数据监听器
|
|
41
|
+
export const addComponent = componentSpace.define()
|
|
42
|
+
.data(() => ({
|
|
43
|
+
a: 1,
|
|
44
|
+
b: 2,
|
|
45
|
+
sum: 3,
|
|
46
|
+
}))
|
|
47
|
+
// 在 Chaining API 中,应传入数组来监听多个数据字段
|
|
48
|
+
.observer(['a', 'b'], function () {
|
|
49
|
+
this.updateData({
|
|
50
|
+
sum: this.data.a + this.data.b,
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
.lifetime('attached', function () {
|
|
54
|
+
this.setData({
|
|
55
|
+
a: 3,
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
.registerComponent()
|
|
59
|
+
// 或在 init 函数中添加数据监听器
|
|
60
|
+
export const addComponent = componentSpace.define()
|
|
61
|
+
.data(() => ({
|
|
62
|
+
a: 1,
|
|
63
|
+
b: 2,
|
|
64
|
+
sum: 3,
|
|
65
|
+
}))
|
|
66
|
+
.init(function ({ lifetime, observer }) {
|
|
67
|
+
// 应传入数组来监听多个数据字段
|
|
68
|
+
observer(['a', 'b'], () => {
|
|
69
|
+
this.updateData({
|
|
70
|
+
sum: this.data.a + this.data.b,
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
lifetime('attached', function () {
|
|
74
|
+
this.setData({
|
|
75
|
+
a: 3,
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
.registerComponent()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
注意:数据监听器会在其所监听字段值被设置时触发,即使其值没有发生变化,监听器也会触发。
|
|
83
|
+
|
|
84
|
+
不要在数据监听器内设置被监听的数据字段本身,否则会无限循环:
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
export const addComponent = componentSpace.defineComponent({
|
|
88
|
+
data: {
|
|
89
|
+
a: 1,
|
|
90
|
+
},
|
|
91
|
+
observers: {
|
|
92
|
+
'a': function () {
|
|
93
|
+
// 会导致无限循环!
|
|
94
|
+
this.updateData({
|
|
95
|
+
a: 1,
|
|
96
|
+
})
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
})
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## 用数据监听器监听子字段
|
|
103
|
+
|
|
104
|
+
数据监听器也可以监听子字段,例如:
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
export const addComponent = componentSpace.defineComponent({
|
|
108
|
+
data: {
|
|
109
|
+
obj: { a: 1 },
|
|
110
|
+
arr: [1, 2, 3],
|
|
111
|
+
},
|
|
112
|
+
// 添加一个数据监听器
|
|
113
|
+
observers: {
|
|
114
|
+
'obj.a, arr[2]': function () {
|
|
115
|
+
// 当 obj.a 或 arr[2] 被设置时会执行
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
lifetimes: {
|
|
119
|
+
attached() {
|
|
120
|
+
// 执行这组更新时,数据监听器会被执行
|
|
121
|
+
this.groupUpdate(() => {
|
|
122
|
+
this.replaceDataOnPath(['obj', 'a'], 3)
|
|
123
|
+
})
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
})
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
若想监听所有子字段,可以使用通配符 `**` ,例如:
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
export const addComponent = componentSpace.defineComponent({
|
|
133
|
+
data: {
|
|
134
|
+
obj: { a: 1 },
|
|
135
|
+
},
|
|
136
|
+
observers: {
|
|
137
|
+
'obj.**': function () {
|
|
138
|
+
// 当 obj 的任何子字段被设置时都会执行
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
})
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
特别地,这样可以监听所有数据字段:
|
|
145
|
+
|
|
146
|
+
```js
|
|
147
|
+
export const addComponent = componentSpace.defineComponent({
|
|
148
|
+
observers: {
|
|
149
|
+
'**': function () {
|
|
150
|
+
// 当任何字段被设置时都会执行
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
})
|
|
154
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 组件初始化策略
|
|
2
|
+
|
|
3
|
+
组件实例初始化流程有两种:
|
|
4
|
+
|
|
5
|
+
1. 总是以自己定义的数据来初始化模板、触发 created 生命周期,然后如有必要,应用外部设置的组件属性、触发数据监听器、再更新一次模板;
|
|
6
|
+
2. 先在自己定义的数据的基础上,应用外部设置的组件属性、触发数据监听器,然后初始化模板、触发 created 生命周期。
|
|
7
|
+
|
|
8
|
+
前者的好处是数据监听器永远在 created 生命周期之后触发,逻辑时序比较稳定;坏处是常常需要一次额外的模板更新,性能相对较差。
|
|
9
|
+
|
|
10
|
+
glass-easel 目前以前者为默认的初始化方式,通过设置 `propertyEarlyInit` 选项可以改为后者:
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
export const childComponent = componentSpace.defineComponent({
|
|
14
|
+
options: {
|
|
15
|
+
propertyEarlyInit: true,
|
|
16
|
+
},
|
|
17
|
+
data: {
|
|
18
|
+
a: 1,
|
|
19
|
+
},
|
|
20
|
+
observers: {
|
|
21
|
+
a() {
|
|
22
|
+
// 可能早于 created 生命周期触发
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
lifetimes: {
|
|
26
|
+
created() {
|
|
27
|
+
// 可能晚于 observers 触发
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 纯数据字段
|
|
2
|
+
|
|
3
|
+
通过组件选项 `pureDataPattern` 可以使得一些数据字段不能用于模板上。这个选项接受一个正则表达式,符合这个正则表达式的字段名不能用于模板。
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
export const myComponent = componentSpace.defineComponent({
|
|
7
|
+
options: {
|
|
8
|
+
// 所有以 _ 开头的字段都不能用于模板
|
|
9
|
+
pureDataPattern: /^_/,
|
|
10
|
+
},
|
|
11
|
+
// 模板上的纯数据字段将视为 undefined
|
|
12
|
+
template: compileTemplate(`
|
|
13
|
+
<div>{{ _a }}</div>
|
|
14
|
+
`),
|
|
15
|
+
data: {
|
|
16
|
+
_a: 1,
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
使用 `pureDataPattern` 通常不会带来性能方面的影响。但如果通过 `dataDeepCopy` 禁用数据拷贝, `pureDataPattern` 可能仍然会带来部分数据拷贝开销。
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# glass-easel
|
|
2
|
+
|
|
3
|
+
多后端组件化界面框架
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
### 基础特性
|
|
8
|
+
|
|
9
|
+
[入门](basic/beginning.md)
|
|
10
|
+
|
|
11
|
+
[模板](basic/template.md)
|
|
12
|
+
|
|
13
|
+
[组件](basic/component.md)
|
|
14
|
+
|
|
15
|
+
[生命周期](basic/lifetime.md)
|
|
16
|
+
|
|
17
|
+
[方法](basic/method.md)
|
|
18
|
+
|
|
19
|
+
[事件](basic/event.md)
|
|
20
|
+
|
|
21
|
+
### 组件间交互
|
|
22
|
+
|
|
23
|
+
[slot 及 slot 类型](interaction/slot.md)
|
|
24
|
+
|
|
25
|
+
[普通 Behaviors](interaction/behavior.md)
|
|
26
|
+
|
|
27
|
+
[Trait Behaviors](interaction/trait_behavior.md)
|
|
28
|
+
|
|
29
|
+
[组件路径](interaction/component_path.md)
|
|
30
|
+
|
|
31
|
+
[组件间关系](interaction/relation.md)
|
|
32
|
+
|
|
33
|
+
[占位组件](interaction/placeholder.md)
|
|
34
|
+
|
|
35
|
+
[抽象节点](interaction/generic.md)
|
|
36
|
+
|
|
37
|
+
[多文件模板](interaction/template_import.md)
|
|
38
|
+
|
|
39
|
+
### 数据控制
|
|
40
|
+
|
|
41
|
+
[高级数据更新方法](data_management/advanced_update.md)
|
|
42
|
+
|
|
43
|
+
[数据监听器](data_management/data_observer.md)
|
|
44
|
+
|
|
45
|
+
[数据字段拷贝控制](data_management/data_deep_copy.md)
|
|
46
|
+
|
|
47
|
+
[组件初始化策略](data_management/property_early_init.md)
|
|
48
|
+
|
|
49
|
+
[纯数据字段](data_management/pure_data_pattern.md)
|
|
50
|
+
|
|
51
|
+
### 样式控制
|
|
52
|
+
|
|
53
|
+
[样式隔离](styling/style_isolation.md)
|
|
54
|
+
|
|
55
|
+
[外部样式类](styling/external_class.md)
|
|
56
|
+
|
|
57
|
+
[虚拟组件节点](styling/virtual_host.md)
|
|
58
|
+
|
|
59
|
+
### 节点树访问
|
|
60
|
+
|
|
61
|
+
[节点树与节点类型](tree/node_tree.md)
|
|
62
|
+
|
|
63
|
+
[节点树遍历](tree/element_iterator.md)
|
|
64
|
+
|
|
65
|
+
[选择器查询](tree/selector.md)
|
|
66
|
+
|
|
67
|
+
[节点树变化监听](tree/mutation_observer.md)
|
|
68
|
+
|
|
69
|
+
[节点树变更](tree/node_tree_modification.md)
|
|
70
|
+
|
|
71
|
+
### 高级特性
|
|
72
|
+
|
|
73
|
+
[组件空间](advanced/component_space.md)
|
|
74
|
+
|
|
75
|
+
[组件构造器中间件](advanced/component_filter.md)
|
|
76
|
+
|
|
77
|
+
[绑定映射表更新](advanced/binding_map_update.md)
|
|
78
|
+
|
|
79
|
+
[自定义后端](advanced/custom_backend.md)
|
|
80
|
+
|
|
81
|
+
[自定义模板引擎](advanced/template_engine.md)
|
|
82
|
+
|
|
83
|
+
[外部组件](advanced/external_component.md)
|
|
84
|
+
|
|
85
|
+
[警告与错误](advanced/error_listener.md)
|
|
86
|
+
|
|
87
|
+
[构建参数](advanced/build_args.md)
|
|
88
|
+
|
|
89
|
+
### 附录
|
|
90
|
+
|
|
91
|
+
[自定义后端协议](appendix/backend_protocol.md)
|
|
92
|
+
|
|
93
|
+
[list-diff 算法介绍](appendix/list_diff_algorithm.md)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# 普通 Behaviors
|
|
2
|
+
|
|
3
|
+
behaviors 是一种简单的组件间代码共享机制。通过 behaviors ,可以将几个组件间共享的部分逻辑抽离出来。
|
|
4
|
+
|
|
5
|
+
对于 Definition API ,可以用 behaviors 定义一部分属性、方法等,然后在组件中可以引用 behaviors ,例如:
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
export const sharedBehavior = componentSpace.defineComponent({
|
|
9
|
+
// 属性列表会被合并到引用它的组件中
|
|
10
|
+
properties: {
|
|
11
|
+
a: Number,
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export const myComponent = componentSpace.defineComponent({
|
|
16
|
+
// 引入 behavior
|
|
17
|
+
behaviors: [sharedBehavior],
|
|
18
|
+
properties: {
|
|
19
|
+
b: String,
|
|
20
|
+
},
|
|
21
|
+
// 属性会与 behavior 中的属性列表合并,因而模板中可以引用模板中的字段
|
|
22
|
+
template: compileTemplate(`
|
|
23
|
+
<div>{{a}}</div>
|
|
24
|
+
<div>{{b}}</div>
|
|
25
|
+
`),
|
|
26
|
+
})
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
注意,有些字段不能写在 behaviors 中(会被忽略)。
|
|
30
|
+
|
|
31
|
+
* `template` 模板因为无法很好合并,所以不能写在 behaviors 中。
|
|
32
|
+
* `using` `generics` `placeholder` 由于涉及了模板中节点信息,也不能写在 behaviors 中。
|
|
33
|
+
* `options` 是针对组件的配置,不能写在 hehaviors 中。
|
|
34
|
+
|
|
35
|
+
对于 Chaining API , behaviors 相当于链式调用中的一部分。 Chaining API 的 behaviors 也有上述字段限制。
|
|
36
|
+
|
|
37
|
+
上面的例子可以用 Chaining API 表达为:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
export const sharedBehavior = componentSpace.define()
|
|
41
|
+
.property('a', Number)
|
|
42
|
+
.registerBehavior()
|
|
43
|
+
|
|
44
|
+
export const myComponent = componentSpace.define()
|
|
45
|
+
.behavior(sharedBehavior)
|
|
46
|
+
.property('b', String)
|
|
47
|
+
.template(compileTemplate(`
|
|
48
|
+
<div>{{a}}</div>
|
|
49
|
+
<div>{{b}}</div>
|
|
50
|
+
`))
|
|
51
|
+
.registerComponent()
|
|
52
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# 组件路径
|
|
2
|
+
|
|
3
|
+
可以给组件起一个路径名称,用于给组件归类。
|
|
4
|
+
|
|
5
|
+
使用 Definition API 给组件命名的示例:
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
export const myComponent = componentSpace.defineComponent({
|
|
9
|
+
is: 'path/to/my/component',
|
|
10
|
+
})
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
使用 Chaining API 给组件命名的示例:
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
export const myComponent = componentSpace.define('path/to/my/component')
|
|
17
|
+
.registerComponent()
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
在引用其他组件时,可以使用组件路径来指定,这对于含有递归引用的组件很实用:
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
componentSpace.defineComponent({
|
|
24
|
+
is: 'path/to/one/component',
|
|
25
|
+
using: {
|
|
26
|
+
// 使用相对路径来指定另一个组件
|
|
27
|
+
another: '../another/component',
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
componentSpace.defineComponent({
|
|
31
|
+
is: 'path/to/another/component',
|
|
32
|
+
using: {
|
|
33
|
+
// 使用绝对路径来指定另一个组件
|
|
34
|
+
one: '/path/to/one/component',
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# 抽象节点
|
|
2
|
+
|
|
3
|
+
有时,由于代码解耦等需要,一些节点对应的组件是不确定的。此时可以将它设置为一个 **抽象节点** ,它对应的组件可以由父组件来指定。例如:
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
// 使用 Definition API 设置抽象节点
|
|
7
|
+
export const childComponent = componentSpace.defineComponent({
|
|
8
|
+
generics: {
|
|
9
|
+
// 设置一个抽象节点
|
|
10
|
+
item: true,
|
|
11
|
+
},
|
|
12
|
+
// 在模板中可以使用抽象节点
|
|
13
|
+
template: compileTemplate(`
|
|
14
|
+
<item />
|
|
15
|
+
`),
|
|
16
|
+
})
|
|
17
|
+
// 或使用 Chaining API 设置抽象节点
|
|
18
|
+
export const childComponent = componentSpace.define()
|
|
19
|
+
.generics({
|
|
20
|
+
item: true,
|
|
21
|
+
})
|
|
22
|
+
.template(compileTemplate(`
|
|
23
|
+
<item />
|
|
24
|
+
`))
|
|
25
|
+
.registerComponent()
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
在使用含有抽象节点的组件时,需要指定抽象节点对应的实际组件,例如:
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
// 先定义一个抽象节点的实现组件
|
|
32
|
+
export const implItemComponent = componentSpace.defineComponent({})
|
|
33
|
+
|
|
34
|
+
// 使用组件时,传入 itemComponent
|
|
35
|
+
export const myComponent = componentSpace.defineComponent({
|
|
36
|
+
using: {
|
|
37
|
+
child: childComponent,
|
|
38
|
+
impl: implItemComponent,
|
|
39
|
+
},
|
|
40
|
+
template: compileTemplate(`
|
|
41
|
+
<child generic:item="impl" />
|
|
42
|
+
`),
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
注意:使用 `generic:` 传入实现组件时,不能使用数据绑定。
|
|
47
|
+
|
|
48
|
+
定义抽象节点时,可以提供一个默认组件,如果父组件没有传入实现组件,则会转而使用这个默认组件,例如:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
const defaultComponent = componentSpace.defineComponent({})
|
|
52
|
+
|
|
53
|
+
export const childComponent = componentSpace.defineComponent({
|
|
54
|
+
generics: {
|
|
55
|
+
item: {
|
|
56
|
+
default: defaultComponent,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
template: compileTemplate(`
|
|
60
|
+
<item />
|
|
61
|
+
`),
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
export const myComponent = componentSpace.defineComponent({
|
|
65
|
+
using: {
|
|
66
|
+
child: childComponent,
|
|
67
|
+
},
|
|
68
|
+
// 未指定 generic:item 时,默认组件将被使用
|
|
69
|
+
template: compileTemplate(`
|
|
70
|
+
<child />
|
|
71
|
+
`),
|
|
72
|
+
})
|
|
73
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# 占位组件
|
|
2
|
+
|
|
3
|
+
有时,出于性能考虑,一些组件需要被延迟加载。此时,可以设置一个占位组件,当一个组件缺失时,可以用占位组件来暂时代替。等到组件被注册之后,占位组件会被自动替换成它。例如:
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
export const placeholderComponent = componentSpace.defineComponent({
|
|
7
|
+
template: compileTemplate(`
|
|
8
|
+
<div>Loading...</div>
|
|
9
|
+
`),
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
// 使用 Definition API 设置占位组件
|
|
13
|
+
export const myComponent = componentSpace.defineComponent({
|
|
14
|
+
using: {
|
|
15
|
+
child: 'lazy-components/child',
|
|
16
|
+
placeholder: placeholderComponent,
|
|
17
|
+
},
|
|
18
|
+
placeholders: {
|
|
19
|
+
child: 'placeholder',
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
// 或使用 Chaining API 设置占位组件
|
|
23
|
+
export const myComponent = componentSpace.define()
|
|
24
|
+
.usingComponents({
|
|
25
|
+
child: 'lazy-components/child',
|
|
26
|
+
placeholder: placeholderComponent,
|
|
27
|
+
})
|
|
28
|
+
.placeholders({
|
|
29
|
+
child: 'placeholder',
|
|
30
|
+
})
|
|
31
|
+
.registerComponent()
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
等到对应的被注册时,占位组件会被自动替换:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
componentSpace.defineComponent({
|
|
38
|
+
is: 'lazy-components/child',
|
|
39
|
+
})
|
|
40
|
+
```
|