vasille 2.0.0 → 2.0.1
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 +153 -119
- package/flow-typed/vasille.js +14 -13
- package/lib/node/interceptor.js +2 -2
- package/lib/node/node.js +19 -2
- package/lib/node/watch.js +3 -3
- package/lib/views/array-view.js +2 -3
- package/lib/views/base-view.js +4 -4
- package/lib/views/map-view.js +2 -2
- package/lib/views/object-view.js +2 -2
- package/lib/views/set-view.js +2 -2
- package/package.json +1 -1
- package/types/node/interceptor.d.ts +2 -2
- package/types/node/node.d.ts +3 -1
- package/types/node/watch.d.ts +3 -3
- package/types/views/base-view.d.ts +2 -3
- package/img/favicon.svg +0 -254
- package/img/getLocus.svg +0 -18
- package/img/logo.png +0 -0
- package/img/logo.svg +0 -550
- package/img/scores-o-log.png +0 -0
- package/img/scores-o.png +0 -0
- package/img/scores-wo-log.png +0 -0
- package/img/scores-wo.png +0 -0
- package/img/x1-x32.png +0 -0
package/README.md
CHANGED
|
@@ -1,132 +1,166 @@
|
|
|
1
|
-
# Vasille
|
|
1
|
+
# Vasille
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|:---:|
|
|
5
|
-
||
|
|
6
|
-
|Vasille.js is **very fast** javascript frontend framework, it is not using virtual DOM, it updates DOM directly using an own reactive mechanism.|
|
|
3
|
+

|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
the maintainer: Lelițac Vasile (lixcode@vivaldi.net).
|
|
5
|
+
`Vasille` core library is frontend solution for `safe`, `fast` & `powerful` applications.
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
## Table of content
|
|
12
8
|
[[_TOC_]]
|
|
13
9
|
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
<hr>
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|---------------------------------------------|--------------|------------|
|
|
19
|
-
| Initial Version | 01.07.2021 | Ready |
|
|
20
|
-
| Patch to 1.1 | 02.12.2021 | Ready |
|
|
21
|
-
| Describe API | 02.14.2021 | Ready |
|
|
22
|
-
| Describe JS API | 02.15.2021 | Ready |
|
|
23
|
-
| Describe VCC architecture | 02.22.2021 | Waiting |
|
|
24
|
-
| Code and debug VCC | 03.xx.2021 | |
|
|
25
|
-
| First enterprise ready version | xx.xx.2021 | |
|
|
26
|
-
| Boost by HTML templates | xx.xx.2021 | |
|
|
13
|
+
## Installation
|
|
27
14
|
|
|
28
|
-
|
|
15
|
+
```
|
|
16
|
+
npm install vasille --save
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Getting ready be example
|
|
20
|
+
* JavaScript Example
|
|
21
|
+
* TypeScript Example
|
|
22
|
+
* Flow.js Example
|
|
23
|
+
|
|
24
|
+
### Flow.js typedef
|
|
25
|
+
Add the next line to `[libs]` section in your `.flowconfig` file
|
|
26
|
+
```
|
|
27
|
+
node_modules/vasille/flow-typed
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
<hr>
|
|
31
|
+
|
|
32
|
+
## How SAFE is Vasille
|
|
33
|
+
|
|
34
|
+
The safe of your application is ensured by
|
|
35
|
+
* `100%` coverage of `vasille` code by unit tests.
|
|
36
|
+
Each function, each branch are working as designed.
|
|
37
|
+
* `strong typing` makes your javascript/typescript code safe as C++ code.
|
|
38
|
+
All entities of `vasille` core library are strong typed, including:
|
|
39
|
+
* data fields & properties.
|
|
40
|
+
* computed properties (function parameters & result).
|
|
41
|
+
* methods.
|
|
42
|
+
* events (defined handlers & event emit).
|
|
43
|
+
* DOM events & DOM operation (attributing, styling, etc.).
|
|
44
|
+
* slots of component.
|
|
45
|
+
* references to children.
|
|
46
|
+
* What you write is what you get - there is no hidden operations, you can control everything.
|
|
47
|
+
* No asynchronous code, when the line of code is executed, the DOM and reactive things are already synced.
|
|
48
|
+
|
|
49
|
+
## How FAST is Vasille
|
|
50
|
+
|
|
51
|
+
The test project was coded using the next frameworks:
|
|
52
|
+
* Angular /
|
|
53
|
+
[Try Initial](https://vasille-js.gitlab.io/project-x32/angular/) /
|
|
54
|
+
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/angular/).
|
|
55
|
+
* React /
|
|
56
|
+
[Try Initial](https://vasille-js.gitlab.io/project-x32/react/) /
|
|
57
|
+
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/react/).
|
|
58
|
+
* Vue 2 /
|
|
59
|
+
[Try Initial](https://vasille-js.gitlab.io/project-x32/vue-2/) /
|
|
60
|
+
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/vue-2/).
|
|
61
|
+
* Vue 3 /
|
|
62
|
+
[Try Initial](https://vasille-js.gitlab.io/project-x32/vue-3/) /
|
|
63
|
+
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/vue-3/).
|
|
64
|
+
* Svelte /
|
|
65
|
+
[Try Initial](https://vasille-js.gitlab.io/project-x32/svelte/) /
|
|
66
|
+
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/svelte/).
|
|
67
|
+
* Vasille /
|
|
68
|
+
[Try Initial](https://vasille-js.gitlab.io/project-x32/vasille-js/) /
|
|
69
|
+
[Try Optimized](https://vasille-js.gitlab.io/project-x32-if/vasille-js/).
|
|
70
|
+
|
|
71
|
+
The result of test are demonstrated in figures 1 & 2.
|
|
72
|
+
The test result are measured in FPS (frames per second), which is calculated as `1000 / ft`,
|
|
73
|
+
where `ft` is an average frame time in ms of 20 frames. All values are absolute. Higher is better.
|
|
74
|
+
|
|
75
|
+
The initial version is updating all the page content in each frame.
|
|
76
|
+
The page reactivity connections are very complex, and we get poor results in Angular, React, Vue & Svelte.
|
|
77
|
+
|
|
78
|
+
The optimized version disables the offscreen & non-actual content, which simplifies the
|
|
79
|
+
reactivity complexity in time. Angular & Svelte give result similar to Vasille.
|
|
80
|
+
React & Vue continue to be slow in the beginning of test.
|
|
81
|
+
|
|
82
|
+
**Conclusion:** The reactivity system of Vasille is very fast
|
|
83
|
+
and its complexity is not slowing down the application.
|
|
84
|
+
|
|
85
|
+
<hr>
|
|
29
86
|
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
Figure 1: Initial version
|
|
90
|
+
|
|
91
|
+

|
|
92
|
+
|
|
93
|
+
<hr>
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
Figure 2: Optimized version
|
|
98
|
+
|
|
99
|
+

|
|
100
|
+
|
|
101
|
+
<hr>
|
|
102
|
+
|
|
103
|
+
## How POWERFUL is Vasille
|
|
104
|
+
|
|
105
|
+
The secret of `Vasille` is a good task decomposition. The core library is composed of
|
|
106
|
+
an effective reactive module and a DOM generation engine based on it.
|
|
107
|
+
|
|
108
|
+
<hr>
|
|
109
|
+
|
|
110
|
+
### Reactivity Module
|
|
111
|
+
|
|
112
|
+
Reactivity module is used to create a model of data. It can contain self-updating values,
|
|
113
|
+
forward-only shared data. Reactivity of objects/fields can be disabled/enabled manually.
|
|
114
|
+
|
|
115
|
+

|
|
116
|
+
|
|
117
|
+
* `Destroyable` is an entity which has a custom destructor.
|
|
118
|
+
* `IValue<T>` is a common interface for any value container, with next members:
|
|
119
|
+
* `get $` gets the encapsulated value.
|
|
120
|
+
* `set $` manually update the encapsulated value, if enabled triggers updating of all linked data.
|
|
121
|
+
* `disable` disables the reactivity.
|
|
122
|
+
* `enable` enables the reactivity and triggers updating of all linked data.
|
|
123
|
+
* `Reference<T>` contains a value of type `T`.
|
|
124
|
+
* `Mirror<T>` syncs self value with another `IValue` container, can be used to share a value forward-only.
|
|
125
|
+
* `Pointer<T>` same as `Mirror`, but it can switch between `IValue` target anytime.
|
|
126
|
+
* `Expression<ReturnType, Args...>` is a self-updating value.
|
|
127
|
+
* `Reactive` is a reactive object which can have multiple reactive fields, emit/receive events/signals.
|
|
128
|
+
|
|
129
|
+
<hr>
|
|
130
|
+
|
|
131
|
+
### DOM Generation Engine
|
|
132
|
+
|
|
133
|
+
DOM Generation Engine is used to describe a virtual DOM of reactive fragments,
|
|
134
|
+
which will be reflected into a browser DOM and keep up to date it.
|
|
135
|
+
|
|
136
|
+

|
|
137
|
+
|
|
138
|
+
* `Fragment` describes a virtual DOM node, which has siblings, children, parent & slots.
|
|
139
|
+
* `TextNode` reflects a `Text` node.
|
|
140
|
+
* `INode` reflects a `Element` node.
|
|
141
|
+
* `Tag` reflect a self created `Element` node.
|
|
142
|
+
* `Extension` reflects an existing `Element` node.
|
|
143
|
+
* `Component` reflects a `Element` node created by a `Tag` child.
|
|
144
|
+
* `AppNode` is root of a `Vasille` application, can be used to create applications in application.
|
|
145
|
+
* `App` is root of a definitive `Vasille` application.
|
|
146
|
+
* `DebugNode` reflects a `Comment` node, useful for debug.
|
|
147
|
+
* `Watch` recompose children nodes on model value change.
|
|
148
|
+
* `RepeatNode` creates multiples children nodes using the same code multiple time.
|
|
149
|
+
* `Repeater` repeat slot content `n` times.
|
|
150
|
+
* `BaseView` represent a view in context of MVC (Model-View-Controller).
|
|
151
|
+
* `ObjectView` repeats slot content for each value of `ObjectModel`.
|
|
152
|
+
* `MapView` repeats slot content for each `MapModel` value.
|
|
153
|
+
* `SetView` repeats slot content for each `SetModel` value.
|
|
154
|
+
* `ArrayView` repeats slot content for each `ArrayModel` value respecting its order.
|
|
155
|
+
* `InterceptorNode` is used to send an event/signal from one child to other
|
|
156
|
+
without manually creating of interceptors.
|
|
157
|
+
|
|
158
|
+
## API documentation
|
|
30
159
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
* [API Documentation](https://gitlab.com/vasille-js/vasille-js/-/blob/master/pages/API.md)
|
|
36
|
-
* [JS API Documentation](https://gitlab.com/vasille-js/vasille-js/-/blob/master/pages/JavaScriptAPI.md)
|
|
37
|
-
|
|
38
|
-
## Tools in development
|
|
39
|
-
|
|
40
|
-
* **Vasille.js** is a component based framework without any dependencies
|
|
41
|
-
* **Reactive Reference** is a build in reactivity library of Vasille.js
|
|
42
|
-
* **Vasille Language** is a user-friendy language to describe Vasille.js
|
|
43
|
-
components
|
|
44
|
-
* **VCC** (*Vasille Component Compiler*) translate code from Vasille
|
|
45
|
-
language to high-effective Vasille.js components performing a
|
|
46
|
-
lot of performance improvements.
|
|
47
|
-
|
|
48
|
-
## How it works
|
|
49
|
-
|
|
50
|
-
To test the speed of frameworks (inclusive Vasille JS) I had created a map,
|
|
51
|
-
which can be zoomed up to 32x, this project was called "Project x32".
|
|
52
|
-
|
|
53
|
-
On the next image is demonstrated the difference between 1x zoom (on the
|
|
54
|
-
left side) and x32 zoom (on the right side):
|
|
55
|
-

|
|
56
|
-
|
|
57
|
-
There are 100 random squares over each brick, on small zoom the squares
|
|
58
|
-
are hidden to optimize browser performance, because the page is composed
|
|
59
|
-
of over than 23 000 nodes. The random squares added one by one to not
|
|
60
|
-
freeze zoom animation. The zoom animation duration is 300ms, and it
|
|
61
|
-
must consist of 20 frames on 60Hz screen.
|
|
62
|
-
|
|
63
|
-
The project x32 was coded using the next frameworks:
|
|
64
|
-
* Angular.
|
|
65
|
-
* React.
|
|
66
|
-
* Vue 2.
|
|
67
|
-
* Vue 3.
|
|
68
|
-
* Svelte.
|
|
69
|
-
* Vasille JS.
|
|
70
|
-
|
|
71
|
-
### Measuring zoom performance
|
|
72
|
-
|
|
73
|
-
After zooming in each production build and measuring performance
|
|
74
|
-
I had got the next results:
|
|
75
|
-

|
|
76
|
-
|
|
77
|
-
The Vue & React builds are the slowest: the average frame time of:
|
|
78
|
-
* React build is 1263.48ms.
|
|
79
|
-
* Vue 3 build is 971.80ms.
|
|
80
|
-
* Vue 2 build is 823.56ms.
|
|
81
|
-
|
|
82
|
-
There is the same graphic in logarithmic scale:
|
|
83
|
-

|
|
84
|
-
|
|
85
|
-
Let's analyze the Angular, Svelte & Vasille JS results:
|
|
86
|
-
* Angular & Svelte has a similar result, the average time of frame
|
|
87
|
-
is 53.94ms for Angular & 53.98 for Svelte.
|
|
88
|
-
* The Vasille JS is the unique framework which support the zoom
|
|
89
|
-
animation at 60fps without any additional optimization.
|
|
90
|
-
Average time of frame is 3.22ms.
|
|
91
|
-
|
|
92
|
-
#### Try it:
|
|
93
|
-
* [Project x32 powered by Angular](https://vasille-js.gitlab.io/project-x32/angular/)
|
|
94
|
-
* [Project x32 powered by React](https://vasille-js.gitlab.io/project-x32/react/)
|
|
95
|
-
* [Project x32 powered by Vue 2](https://vasille-js.gitlab.io/project-x32/vue-2/)
|
|
96
|
-
* [Project x32 powered by Vue 3](https://vasille-js.gitlab.io/project-x32/vue-3/)
|
|
97
|
-
* [Project x32 powered by Svelte](https://vasille-js.gitlab.io/project-x32/svelte/)
|
|
98
|
-
* [Project x32 powered by Vasille JS](https://vasille-js.gitlab.io/project-x32/vasille-js/)
|
|
99
|
-
|
|
100
|
-
### Let's optimize Project x32
|
|
101
|
-
|
|
102
|
-
To optimize the Project x32 realizations, the optimization consist
|
|
103
|
-
of removing the off-screen components, that change will decrease
|
|
104
|
-
the number of components. So let's zoom each optimized build
|
|
105
|
-
from x1 to x32.
|
|
106
|
-
|
|
107
|
-
Tests results:
|
|
108
|
-

|
|
109
|
-
|
|
110
|
-
After X8 the number of onscreen components is very small, the optimization has a good result.
|
|
111
|
-
The Reactive frameworks are the slowest before and after optimization.
|
|
112
|
-
|
|
113
|
-
There is the same graphic in logarithmic scale:
|
|
114
|
-

|
|
115
|
-
|
|
116
|
-
After optimization Angular, Svelte & Vasille JS has very good
|
|
117
|
-
results close to Vasille JS before optimization.
|
|
118
|
-
|
|
119
|
-
#### Try it:
|
|
120
|
-
* [Optimized Project x32 powered by Angular](https://vasille-js.gitlab.io/project-x32-if/angular/)
|
|
121
|
-
* [Optimized Project x32 powered by React](https://vasille-js.gitlab.io/project-x32-if/react/)
|
|
122
|
-
* [Optimized Project x32 powered by Vue 2](https://vasille-js.gitlab.io/project-x32-if/vue-2/)
|
|
123
|
-
* [Optimized Project x32 powered by Vue 3](https://vasille-js.gitlab.io/project-x32-if/vue-3/)
|
|
124
|
-
* [Optimized Project x32 powered by Svelte](https://vasille-js.gitlab.io/project-x32-if/svelte/)
|
|
125
|
-
* [Optimized Project x32 powered by Vasille JS](https://vasille-js.gitlab.io/project-x32-if/vasille-js/)
|
|
126
|
-
|
|
127
|
-
## Conclusions
|
|
128
|
-
The main goal of Vasille JS is not to be the fastest JavaScript framework,
|
|
129
|
-
but to ensure excellent performance without any optimizations.
|
|
160
|
+
There are several API, and most of it are WIP (Work In Progress):
|
|
161
|
+
* [OOP API - Ready](https://gitlab.com/vasille-js/vasille-js/-/blob/v2/pages/OOP-API.md)
|
|
162
|
+
* [Procedural API - WIP](https://gitlab.com/vasille-js/vasille-js/-/blob/v2/pages/Procedural-API.md)
|
|
163
|
+
* [Final API - WIP](https://gitlab.com/vasille-js/vasille-js/-/blob/v2/pages/API.md)
|
|
130
164
|
|
|
131
165
|
## Questions
|
|
132
166
|
|
package/flow-typed/vasille.js
CHANGED
|
@@ -87,48 +87,48 @@ declare module "vasille" {
|
|
|
87
87
|
$bind<T, T1> (
|
|
88
88
|
func : (a1 : T1) => T,
|
|
89
89
|
v1: IValue<T1>,
|
|
90
|
-
) :
|
|
90
|
+
) : IValue<T>;
|
|
91
91
|
$bind<T, T1, T2> (
|
|
92
92
|
func : (a1 : T1, a2 : T2) => T,
|
|
93
93
|
v1: IValue<T1>, v2: IValue<T2>,
|
|
94
|
-
) :
|
|
94
|
+
) : IValue<T>;
|
|
95
95
|
$bind<T, T1, T2, T3> (
|
|
96
96
|
func : (a1 : T1, a2 : T2, a3 : T3) => T,
|
|
97
97
|
v1: IValue<T1>, v2: IValue<T2>, v3: IValue<T3>,
|
|
98
|
-
) :
|
|
98
|
+
) : IValue<T>;
|
|
99
99
|
$bind<T, T1, T2, T3, T4> (
|
|
100
100
|
func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4) => T,
|
|
101
101
|
v1: IValue<T1>, v2: IValue<T2>, v3: IValue<T3>,
|
|
102
102
|
v4: IValue<T4>,
|
|
103
|
-
) :
|
|
103
|
+
) : IValue<T>;
|
|
104
104
|
$bind<T, T1, T2, T3, T4, T5> (
|
|
105
105
|
func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4, a5 : T5) => T,
|
|
106
106
|
v1: IValue<T1>, v2: IValue<T2>, v3: IValue<T3>,
|
|
107
107
|
v4: IValue<T4>, v5: IValue<T5>,
|
|
108
|
-
) :
|
|
108
|
+
) : IValue<T>;
|
|
109
109
|
$bind<T, T1, T2, T3, T4, T5, T6> (
|
|
110
110
|
func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4, a5 : T5, a6 : T6) => T,
|
|
111
111
|
v1: IValue<T1>, v2: IValue<T2>, v3: IValue<T3>,
|
|
112
112
|
v4: IValue<T4>, v5: IValue<T5>, v6: IValue<T6>,
|
|
113
|
-
) :
|
|
113
|
+
) : IValue<T>;
|
|
114
114
|
$bind<T, T1, T2, T3, T4, T5, T6, T7> (
|
|
115
115
|
func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4, a5 : T5, a6 : T6, a7 : T7) => T,
|
|
116
116
|
v1: IValue<T1>, v2: IValue<T2>, v3: IValue<T3>,
|
|
117
117
|
v4: IValue<T4>, v5: IValue<T5>, v6: IValue<T6>,
|
|
118
118
|
v7: IValue<T7>,
|
|
119
|
-
) :
|
|
119
|
+
) : IValue<T>;
|
|
120
120
|
$bind<T, T1, T2, T3, T4, T5, T6, T7, T8> (
|
|
121
121
|
func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4, a5 : T5, a6 : T6, a7 : T7, a8 : T8) => T,
|
|
122
122
|
v1: IValue<T1>, v2: IValue<T2>, v3: IValue<T3>,
|
|
123
123
|
v4: IValue<T4>, v5: IValue<T5>, v6: IValue<T6>,
|
|
124
124
|
v7: IValue<T7>, v8: IValue<T8>,
|
|
125
|
-
) :
|
|
125
|
+
) : IValue<T>;
|
|
126
126
|
$bind<T, T1, T2, T3, T4, T5, T6, T7, T8, T9> (
|
|
127
127
|
func : (a1 : T1, a2 : T2, a3 : T3, a4 : T4, a5 : T5, a6 : T6, a7 : T7, a8 : T8, a9 : T9) => T,
|
|
128
128
|
v1: IValue<T1>, v2: IValue<T2>, v3: IValue<T3>,
|
|
129
129
|
v4: IValue<T4>, v5: IValue<T5>, v6: IValue<T6>,
|
|
130
130
|
v7: IValue<T7>, v8: IValue<T8>, v9: IValue<T9>,
|
|
131
|
-
) :
|
|
131
|
+
) : IValue<T>;
|
|
132
132
|
|
|
133
133
|
$enable () : void;
|
|
134
134
|
$disable () : void;
|
|
@@ -324,7 +324,8 @@ declare module "vasille" {
|
|
|
324
324
|
) : this;
|
|
325
325
|
$create<T> (
|
|
326
326
|
node : T,
|
|
327
|
-
callback : ($ : T) => void
|
|
327
|
+
callback : ($ : T) => void,
|
|
328
|
+
callback1 : ($ : T) => void
|
|
328
329
|
) : this;
|
|
329
330
|
$if (
|
|
330
331
|
cond : IValue<boolean>,
|
|
@@ -598,9 +599,9 @@ declare module "vasille" {
|
|
|
598
599
|
|
|
599
600
|
$preinit (app : AppNode, parent : Fragment, text : ?IValue<string>) : void;
|
|
600
601
|
}
|
|
601
|
-
declare export class Watch extends Fragment {
|
|
602
|
-
slot : Slot
|
|
603
|
-
model : IValue<
|
|
602
|
+
declare export class Watch<T> extends Fragment {
|
|
603
|
+
slot : Slot<T>;
|
|
604
|
+
model : IValue<T>;
|
|
604
605
|
|
|
605
606
|
constructor () : void;
|
|
606
607
|
|
package/lib/node/interceptor.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment } from "./node";
|
|
2
2
|
import { Destroyable } from "../core/destroyable";
|
|
3
3
|
import { Signal } from "../core/signal";
|
|
4
4
|
import { Slot } from "../core/slot";
|
|
@@ -63,7 +63,7 @@ export class Interceptor extends Destroyable {
|
|
|
63
63
|
* @class InterceptorNode
|
|
64
64
|
* @extends Extension
|
|
65
65
|
*/
|
|
66
|
-
export class InterceptorNode extends
|
|
66
|
+
export class InterceptorNode extends Fragment {
|
|
67
67
|
constructor() {
|
|
68
68
|
super(...arguments);
|
|
69
69
|
/**
|
package/lib/node/node.js
CHANGED
|
@@ -204,14 +204,18 @@ export class Fragment extends Reactive {
|
|
|
204
204
|
* Defines a custom element
|
|
205
205
|
* @param node {Fragment} vasille element to insert
|
|
206
206
|
* @param callback {function($ : *)}
|
|
207
|
+
* @param callback1 {function($ : *)}
|
|
207
208
|
*/
|
|
208
|
-
$create(node, callback) {
|
|
209
|
+
$create(node, callback, callback1) {
|
|
209
210
|
const $ = this.$;
|
|
210
211
|
node.$.parent = this;
|
|
211
212
|
node.$preinit($.app, this);
|
|
212
213
|
if (callback) {
|
|
213
214
|
callback(node);
|
|
214
215
|
}
|
|
216
|
+
if (callback1) {
|
|
217
|
+
callback1(node);
|
|
218
|
+
}
|
|
215
219
|
this.$$pushNode(node);
|
|
216
220
|
node.$init().$ready();
|
|
217
221
|
return this;
|
|
@@ -947,6 +951,19 @@ export class Tag extends INode {
|
|
|
947
951
|
$$findFirstChild() {
|
|
948
952
|
return this.$.unmounted ? null : this.$.node;
|
|
949
953
|
}
|
|
954
|
+
$$insertAdjacent(node) {
|
|
955
|
+
if (this.$.unmounted) {
|
|
956
|
+
if (this.$.next) {
|
|
957
|
+
this.$.next.$$insertAdjacent(node);
|
|
958
|
+
}
|
|
959
|
+
else {
|
|
960
|
+
this.$.parent.$$appendNode(node);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
else {
|
|
964
|
+
super.$$insertAdjacent(node);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
950
967
|
$$appendNode(node) {
|
|
951
968
|
const $ = this.$;
|
|
952
969
|
$.app.$run.appendChild($.node, node);
|
|
@@ -1054,7 +1071,7 @@ export class SwitchedNodePrivate extends INodePrivate {
|
|
|
1054
1071
|
/**
|
|
1055
1072
|
* Defines a node witch can switch its children conditionally
|
|
1056
1073
|
*/
|
|
1057
|
-
class SwitchedNode extends
|
|
1074
|
+
class SwitchedNode extends Fragment {
|
|
1058
1075
|
/**
|
|
1059
1076
|
* Constructs a switch node and define a sync function
|
|
1060
1077
|
*/
|
package/lib/node/watch.js
CHANGED
|
@@ -13,15 +13,15 @@ export class Watch extends Fragment {
|
|
|
13
13
|
this.$seal();
|
|
14
14
|
}
|
|
15
15
|
$createWatchers() {
|
|
16
|
-
this.$watch(() => {
|
|
16
|
+
this.$watch((value) => {
|
|
17
17
|
this.$children.forEach(child => {
|
|
18
18
|
child.$destroy();
|
|
19
19
|
});
|
|
20
20
|
this.$children.splice(0);
|
|
21
|
-
this.slot.release(this);
|
|
21
|
+
this.slot.release(this, value);
|
|
22
22
|
}, this.model);
|
|
23
23
|
}
|
|
24
24
|
$compose() {
|
|
25
|
-
this.slot.release(this);
|
|
25
|
+
this.slot.release(this, this.model.$);
|
|
26
26
|
}
|
|
27
27
|
}
|
package/lib/views/array-view.js
CHANGED
|
@@ -8,15 +8,14 @@ import { ArrayModel } from "../models/array-model";
|
|
|
8
8
|
export class ArrayView extends BaseView {
|
|
9
9
|
constructor() {
|
|
10
10
|
super();
|
|
11
|
-
this.model =
|
|
11
|
+
this.model = new ArrayModel;
|
|
12
12
|
this.$seal();
|
|
13
13
|
}
|
|
14
14
|
createChild(id, item, before) {
|
|
15
15
|
super.createChild(item, item, before || this.$.nodes.get(id));
|
|
16
16
|
}
|
|
17
17
|
$ready() {
|
|
18
|
-
|
|
19
|
-
arr.forEach(item => {
|
|
18
|
+
this.model.forEach(item => {
|
|
20
19
|
this.createChild(item, item);
|
|
21
20
|
});
|
|
22
21
|
super.$ready();
|
package/lib/views/base-view.js
CHANGED
|
@@ -33,8 +33,8 @@ export class BaseView extends RepeatNode {
|
|
|
33
33
|
*/
|
|
34
34
|
$ready() {
|
|
35
35
|
const $ = this.$;
|
|
36
|
-
this.model
|
|
37
|
-
this.model
|
|
36
|
+
this.model.listener.onAdd($.addHandler);
|
|
37
|
+
this.model.listener.onRemove($.removeHandler);
|
|
38
38
|
super.$ready();
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
@@ -42,8 +42,8 @@ export class BaseView extends RepeatNode {
|
|
|
42
42
|
*/
|
|
43
43
|
$destroy() {
|
|
44
44
|
const $ = this.$;
|
|
45
|
-
this.model
|
|
46
|
-
this.model
|
|
45
|
+
this.model.listener.offAdd($.addHandler);
|
|
46
|
+
this.model.listener.offRemove($.removeHandler);
|
|
47
47
|
super.$destroy();
|
|
48
48
|
}
|
|
49
49
|
}
|
package/lib/views/map-view.js
CHANGED
|
@@ -8,10 +8,10 @@ import { MapModel } from "../models/map-model";
|
|
|
8
8
|
export class MapView extends BaseView {
|
|
9
9
|
constructor() {
|
|
10
10
|
super();
|
|
11
|
-
this.model =
|
|
11
|
+
this.model = new MapModel;
|
|
12
12
|
}
|
|
13
13
|
$ready() {
|
|
14
|
-
const map = this.model
|
|
14
|
+
const map = this.model;
|
|
15
15
|
map.forEach((value, key) => {
|
|
16
16
|
this.createChild(key, value);
|
|
17
17
|
});
|
package/lib/views/object-view.js
CHANGED
|
@@ -8,10 +8,10 @@ import { ObjectModel } from "../models/object-model";
|
|
|
8
8
|
export class ObjectView extends BaseView {
|
|
9
9
|
constructor() {
|
|
10
10
|
super();
|
|
11
|
-
this.model =
|
|
11
|
+
this.model = new ObjectModel;
|
|
12
12
|
}
|
|
13
13
|
$ready() {
|
|
14
|
-
const obj = this.model
|
|
14
|
+
const obj = this.model;
|
|
15
15
|
for (const key in obj) {
|
|
16
16
|
this.createChild(key, obj[key]);
|
|
17
17
|
}
|
package/lib/views/set-view.js
CHANGED
|
@@ -8,11 +8,11 @@ import { SetModel } from "../models/set-model";
|
|
|
8
8
|
export class SetView extends BaseView {
|
|
9
9
|
constructor() {
|
|
10
10
|
super();
|
|
11
|
-
this.model =
|
|
11
|
+
this.model = new SetModel();
|
|
12
12
|
}
|
|
13
13
|
$ready() {
|
|
14
14
|
const $ = this.$;
|
|
15
|
-
const set = this.model
|
|
15
|
+
const set = this.model;
|
|
16
16
|
set.forEach(item => {
|
|
17
17
|
$.app.$run.callCallback(() => {
|
|
18
18
|
this.createChild(item, item);
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment } from "./node";
|
|
2
2
|
import { Destroyable } from "../core/destroyable";
|
|
3
3
|
import { Signal } from "../core/signal";
|
|
4
4
|
import { Slot } from "../core/slot";
|
|
@@ -35,7 +35,7 @@ export declare class Interceptor<t1 = void, t2 = void, t3 = void, t4 = void, t5
|
|
|
35
35
|
* @class InterceptorNode
|
|
36
36
|
* @extends Extension
|
|
37
37
|
*/
|
|
38
|
-
export declare class InterceptorNode<t1 = void, t2 = void, t3 = void, t4 = void, t5 = void, t6 = void, t7 = void, t8 = void, t9 = void> extends
|
|
38
|
+
export declare class InterceptorNode<t1 = void, t2 = void, t3 = void, t4 = void, t5 = void, t6 = void, t7 = void, t8 = void, t9 = void> extends Fragment {
|
|
39
39
|
/**
|
|
40
40
|
* Internal interceptor
|
|
41
41
|
* @type Interceptor
|
package/types/node/node.d.ts
CHANGED
|
@@ -127,8 +127,9 @@ export declare class Fragment extends Reactive {
|
|
|
127
127
|
* Defines a custom element
|
|
128
128
|
* @param node {Fragment} vasille element to insert
|
|
129
129
|
* @param callback {function($ : *)}
|
|
130
|
+
* @param callback1 {function($ : *)}
|
|
130
131
|
*/
|
|
131
|
-
$create<T extends Fragment>(node: T, callback?: ($: T) => void): this;
|
|
132
|
+
$create<T extends Fragment>(node: T, callback?: ($: T) => void, callback1?: ($: T) => void): this;
|
|
132
133
|
/**
|
|
133
134
|
* Defines an if node
|
|
134
135
|
* @param cond {IValue} condition
|
|
@@ -636,6 +637,7 @@ export declare class Tag extends INode {
|
|
|
636
637
|
constructor();
|
|
637
638
|
$preinit(app: AppNode, parent: Fragment, tagName?: string): void;
|
|
638
639
|
protected $$findFirstChild(): Node;
|
|
640
|
+
$$insertAdjacent(node: Node): void;
|
|
639
641
|
$$appendNode(node: Node): void;
|
|
640
642
|
/**
|
|
641
643
|
* Mount/Unmount a node
|
package/types/node/watch.d.ts
CHANGED
|
@@ -6,17 +6,17 @@ import { IValue } from "../core/ivalue";
|
|
|
6
6
|
* @class Watch
|
|
7
7
|
* @extends Fragment
|
|
8
8
|
*/
|
|
9
|
-
export declare class Watch extends Fragment {
|
|
9
|
+
export declare class Watch<T> extends Fragment {
|
|
10
10
|
/**
|
|
11
11
|
* Default slot
|
|
12
12
|
* @type Slot
|
|
13
13
|
*/
|
|
14
|
-
slot: Slot
|
|
14
|
+
slot: Slot<T>;
|
|
15
15
|
/**
|
|
16
16
|
* iValue to watch
|
|
17
17
|
* @type IValue
|
|
18
18
|
*/
|
|
19
|
-
model: IValue<
|
|
19
|
+
model: IValue<T>;
|
|
20
20
|
constructor();
|
|
21
21
|
$createWatchers(): void;
|
|
22
22
|
$compose(): void;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { RepeatNode, RepeatNodePrivate } from "./repeat-node";
|
|
2
|
-
import { IValue } from "../core/ivalue";
|
|
3
2
|
import { IModel } from "../models/model";
|
|
4
3
|
/**
|
|
5
4
|
* Private part of BaseView
|
|
@@ -29,9 +28,9 @@ export declare class BaseView<K, T, Model extends IModel<K, T>> extends RepeatNo
|
|
|
29
28
|
protected $: BaseViewPrivate<K, T>;
|
|
30
29
|
/**
|
|
31
30
|
* Property which will contain a model
|
|
32
|
-
* @type {
|
|
31
|
+
* @type {IModel}
|
|
33
32
|
*/
|
|
34
|
-
model:
|
|
33
|
+
model: Model;
|
|
35
34
|
constructor($1?: BaseViewPrivate<K, T>);
|
|
36
35
|
/**
|
|
37
36
|
* Handle ready event
|