@lightningjs/blits 0.8.1 → 0.9.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/CHANGELOG.md +20 -0
- package/boilerplate/js/default/src/index.js +2 -8
- package/docs/README.md +0 -21
- package/docs/_sidebar.md +25 -13
- package/docs/built-in/directives.md +44 -0
- package/docs/{component_state.md → components/component_state.md} +37 -5
- package/docs/components/computed_properties.md +48 -0
- package/docs/{lifecycle_events.md → components/lifecycle_events.md} +4 -2
- package/docs/components/methods.md +47 -0
- package/docs/components/props.md +58 -0
- package/docs/{user_input.md → components/user_input.md} +31 -26
- package/docs/components/utilities.md +4 -0
- package/docs/components/watchers.md +36 -0
- package/docs/essentials/application_root.md +21 -0
- package/docs/{components.md → essentials/components.md} +17 -5
- package/docs/{displaying_images.md → essentials/displaying_images.md} +7 -7
- package/docs/essentials/displaying_text.md +77 -0
- package/docs/{element_attributes.md → essentials/element_attributes.md} +17 -12
- package/docs/essentials/template_syntax.md +85 -0
- package/docs/getting_started/file_structure.md +61 -0
- package/docs/getting_started/getting_started.md +47 -0
- package/docs/{introduction.md → getting_started/intro.md} +2 -1
- package/docs/sidebar.json +70 -26
- package/docs/transitions_animations/transitions.md +132 -0
- package/package.json +2 -2
- package/src/component.js +12 -3
- package/src/element.js +8 -5
- package/src/fontLoader.js +20 -21
- package/src/launch.d.ts +22 -7
- package/src/launch.js +13 -2
- package/src/lib/codegenerator/generator.js +8 -7
- package/src/lib/codegenerator/generator.test.js +11 -16
- package/src/lib/hooks.js +7 -7
- package/src/lib/lifecycle.js +3 -2
- package/src/lib/reactivity/effect.js +23 -0
- package/src/lib/reactivity/reactive.js +59 -46
- package/src/lib/setup/base.js +18 -10
- package/src/lib/setup/state.js +1 -1
- package/src/lib/symbols.js +3 -0
- package/src/router/router.js +6 -6
- package/boilerplate/js/default/src/fontloader.js +0 -4
- package/docs/computed_properties.md +0 -18
- package/docs/getting_started.md +0 -40
- package/docs/props.md +0 -46
- package/docs/template_syntax.md +0 -65
- package/docs/watchers.md +0 -38
- /package/docs/{text-to-speech-announcer.md → plugins/text-to-speech-announcer.md} +0 -0
|
@@ -15,76 +15,89 @@
|
|
|
15
15
|
* SPDX-License-Identifier: Apache-2.0
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { track, trigger } from './effect.js'
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
'includes',
|
|
23
|
-
'indexOf',
|
|
24
|
-
'lastIndexOf',
|
|
25
|
-
'push',
|
|
26
|
-
'pop',
|
|
27
|
-
'shift',
|
|
28
|
-
'splice',
|
|
29
|
-
'unshift',
|
|
30
|
-
'sort',
|
|
31
|
-
'reverse',
|
|
32
|
-
]
|
|
33
|
-
|
|
34
|
-
const arrayPatchMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']
|
|
18
|
+
import { track, trigger, pauseTracking, resumeTracking } from './effect.js'
|
|
19
|
+
import symbols from '../symbols.js'
|
|
20
|
+
|
|
21
|
+
const arrayPatchMethods = ['push', 'pop', 'shift', 'unshift', 'splice']
|
|
35
22
|
|
|
36
23
|
const proxyMap = new WeakMap()
|
|
37
24
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
25
|
+
const getProxy = (obj) => {
|
|
26
|
+
return proxyMap.get(obj)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const getRaw = (value) => {
|
|
30
|
+
const raw = value && value[symbols.raw]
|
|
31
|
+
return raw ? getRaw(raw) : value
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const reactiveProxy = (original, _parent = null, _key) => {
|
|
35
|
+
// if original object is already a proxy, don't create a new one but return the existing one instead
|
|
36
|
+
const existingProxy = getProxy(original)
|
|
37
|
+
if (existingProxy) {
|
|
38
|
+
return existingProxy
|
|
42
39
|
}
|
|
43
40
|
|
|
44
41
|
const handler = {
|
|
45
42
|
get(target, key, receiver) {
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
// return the original object instead of the proxied
|
|
44
|
+
if (key === symbols.raw) {
|
|
45
|
+
return original
|
|
48
46
|
}
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
// handling arrays
|
|
49
|
+
if (Array.isArray(target)) {
|
|
50
|
+
// augment array path methods (that change the length of the array)
|
|
51
|
+
if (arrayPatchMethods.indexOf(key) > -1) {
|
|
52
|
+
return function (...args) {
|
|
53
|
+
pauseTracking()
|
|
54
|
+
const result = target[key].apply(this, args)
|
|
55
|
+
// trigger a change on the parent object and the key
|
|
56
|
+
// i.e. when pushing a new item to `obj.data`, _parent will equal `obj`
|
|
57
|
+
// and _key will equal `data`
|
|
58
|
+
trigger(_parent, _key)
|
|
59
|
+
resumeTracking()
|
|
60
|
+
return result
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
return Reflect.get(target, key, receiver)
|
|
64
|
+
}
|
|
52
65
|
}
|
|
53
66
|
|
|
67
|
+
// handling objects (but not null values, which have object type in JS)
|
|
68
|
+
if (typeof target[key] === 'object' && target[key] !== null) {
|
|
69
|
+
if (Array.isArray(target[key])) {
|
|
70
|
+
track(target, key)
|
|
71
|
+
}
|
|
72
|
+
// create a new reactive proxy
|
|
73
|
+
return reactiveProxy(target[key], target, key)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// handling all other types
|
|
77
|
+
// track the key on the target
|
|
54
78
|
track(target, key)
|
|
79
|
+
// return the reflected value
|
|
55
80
|
return Reflect.get(target, key, receiver)
|
|
56
81
|
},
|
|
57
82
|
set(target, key, value, receiver) {
|
|
58
|
-
|
|
83
|
+
// get the raw values (without proxy wrapper) so we can compare them
|
|
84
|
+
const oldRawValue = getRaw(target[key])
|
|
85
|
+
const rawValue = getRaw(value)
|
|
59
86
|
|
|
60
|
-
let result
|
|
61
|
-
if (
|
|
62
|
-
if (oldValue !== value) {
|
|
63
|
-
result = oldValue.splice(0, target[key].length, ...value)
|
|
64
|
-
} else {
|
|
65
|
-
result = true
|
|
66
|
-
}
|
|
67
|
-
} else {
|
|
87
|
+
let result = true
|
|
88
|
+
if (oldRawValue !== rawValue) {
|
|
68
89
|
result = Reflect.set(target, key, value, receiver)
|
|
69
90
|
}
|
|
70
91
|
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (key === 'length') {
|
|
76
|
-
trigger(target, key)
|
|
77
|
-
} else {
|
|
78
|
-
if (result && oldValue !== value) {
|
|
79
|
-
trigger(target, key)
|
|
80
|
-
}
|
|
92
|
+
if (result && oldRawValue !== value) {
|
|
93
|
+
trigger(target, key, true)
|
|
81
94
|
}
|
|
82
95
|
return result
|
|
83
96
|
},
|
|
84
97
|
}
|
|
85
98
|
|
|
86
|
-
const proxy = new Proxy(
|
|
87
|
-
proxyMap.set(
|
|
99
|
+
const proxy = new Proxy(original, handler)
|
|
100
|
+
proxyMap.set(original, proxy)
|
|
88
101
|
return proxy
|
|
89
102
|
}
|
|
90
103
|
|
package/src/lib/setup/base.js
CHANGED
|
@@ -35,7 +35,7 @@ const shaderAlias = {
|
|
|
35
35
|
rounded: 'radius',
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
export default (component, name) => {
|
|
38
|
+
export default (component, name, identifier) => {
|
|
39
39
|
Object.defineProperties(component.prototype, {
|
|
40
40
|
name: {
|
|
41
41
|
value: name,
|
|
@@ -43,8 +43,15 @@ export default (component, name) => {
|
|
|
43
43
|
enumerable: true,
|
|
44
44
|
configurable: false,
|
|
45
45
|
},
|
|
46
|
+
[symbols.identifier]: {
|
|
47
|
+
value: component[symbols.identifier],
|
|
48
|
+
writable: false,
|
|
49
|
+
enumerable: false,
|
|
50
|
+
configurable: false,
|
|
51
|
+
},
|
|
46
52
|
focus: {
|
|
47
53
|
value: function (e) {
|
|
54
|
+
this[symbols.state].hasFocus = true
|
|
48
55
|
Focus.set(this, e)
|
|
49
56
|
},
|
|
50
57
|
writable: false,
|
|
@@ -53,6 +60,7 @@ export default (component, name) => {
|
|
|
53
60
|
},
|
|
54
61
|
unfocus: {
|
|
55
62
|
value: function () {
|
|
63
|
+
this[symbols.state].hasFocus = false
|
|
56
64
|
this.lifecycle.state = 'unfocus'
|
|
57
65
|
},
|
|
58
66
|
writable: false,
|
|
@@ -262,15 +270,15 @@ export default (component, name) => {
|
|
|
262
270
|
}
|
|
263
271
|
|
|
264
272
|
const deleteChildren = function (children) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
273
|
+
for (let i = 0; i < children.length; i++) {
|
|
274
|
+
if (!children[i]) return
|
|
275
|
+
if (Array.isArray(children[i])) {
|
|
276
|
+
deleteChildren(children[i])
|
|
277
|
+
} else if (children[i].destroy) {
|
|
278
|
+
children[i].destroy()
|
|
279
|
+
}
|
|
280
|
+
children[i] = null
|
|
281
|
+
}
|
|
274
282
|
|
|
275
283
|
children.length = 0
|
|
276
284
|
}
|
package/src/lib/setup/state.js
CHANGED
|
@@ -22,7 +22,7 @@ import symbols from '../symbols.js'
|
|
|
22
22
|
export default (component, state) => {
|
|
23
23
|
component[symbols.stateKeys] = []
|
|
24
24
|
|
|
25
|
-
state = state.apply(component.prototype)
|
|
25
|
+
state = { ...state.apply(component.prototype), ...{ hasFocus: false } }
|
|
26
26
|
Object.keys(state).forEach((key) => {
|
|
27
27
|
if (component[symbols.propKeys] && component[symbols.propKeys].indexOf(key) > -1) {
|
|
28
28
|
Log.error(`State ${key} already exists as a prop`)
|
package/src/lib/symbols.js
CHANGED
|
@@ -3,6 +3,8 @@ export default {
|
|
|
3
3
|
cursorTagStart: Symbol('cursorTagStart'),
|
|
4
4
|
computedKeys: Symbol('computedKeys'),
|
|
5
5
|
destroy: Symbol('destroy'),
|
|
6
|
+
id: Symbol('id'),
|
|
7
|
+
identifier: Symbol('identifier'),
|
|
6
8
|
index: Symbol('index'),
|
|
7
9
|
init: Symbol('init'),
|
|
8
10
|
inputEvents: Symbol('inputEvents'),
|
|
@@ -11,6 +13,7 @@ export default {
|
|
|
11
13
|
methodKeys: Symbol('methodKeys'),
|
|
12
14
|
originalState: Symbol('originalState'),
|
|
13
15
|
propKeys: Symbol('propKeys'),
|
|
16
|
+
raw: Symbol('raw'),
|
|
14
17
|
ready: Symbol('ready'),
|
|
15
18
|
renderer: Symbol('renderer'),
|
|
16
19
|
routes: Symbol('routes'),
|
package/src/router/router.js
CHANGED
|
@@ -236,12 +236,12 @@ const removeView = async (route, view, transition) => {
|
|
|
236
236
|
cacheMap.set(route, { view: view, focus: previousFocus })
|
|
237
237
|
} else {
|
|
238
238
|
// remove and cleanup
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
239
|
+
for (let i = 0; i < view[symbols.children].length; i++) {
|
|
240
|
+
// if (view[symbols.children][i] && view[symbols.children][i].destroy) {
|
|
241
|
+
// view[symbols.children][i].destroy()
|
|
242
|
+
view[symbols.children][i] = null
|
|
243
|
+
// }
|
|
244
|
+
}
|
|
245
245
|
view.destroy()
|
|
246
246
|
view = null
|
|
247
247
|
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# Blits - Lightning 3 App Development Framework
|
|
2
|
-
|
|
3
|
-
## Computed properties
|
|
4
|
-
|
|
5
|
-
So far we've learned how to utilize internal state variables and props passed by a parent in (the template of) our component.
|
|
6
|
-
We can even perform simple operations like `Math.max()` or `str.toUpperCase()` directly within an argument of the template.
|
|
7
|
-
|
|
8
|
-
However, sometimes it's more clear and more maintainable to abstract these operations into what we call _computed properties_.
|
|
9
|
-
|
|
10
|
-
Within the computed key of the Component configuration object, you can specify a set of functions. Each function name you define (`offset()` for example) becomes accessible as a computed property.
|
|
11
|
-
|
|
12
|
-
In your template, you can reference these computed properties by prefixing them with a dollar sign (e.g., `$offset`). In the rest of your app's code, you can access these computed properties (but not modify them) using `this.offset`.
|
|
13
|
-
|
|
14
|
-
Within a computed property, you can reference one or more state variables or props and return a value based on calculations or logical operations.
|
|
15
|
-
|
|
16
|
-
Whenever the value of any referenced variable changes, the computed property will automatically recalculate. If a computed property is referenced reactively in the template (i.e., prefixed with colons `:`), it will also trigger an automatic rerender of that portion of the template.
|
|
17
|
-
|
|
18
|
-
Computed properties are a powerful tool for enhancing the readability of your component code. By abstracting complex or frequently used calculations into computed properties, you can make your code (and especially your template) more concise and easier to understand.
|
package/docs/getting_started.md
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# Blits - Lightning 3 App Development Framework
|
|
2
|
-
|
|
3
|
-
## Getting Started
|
|
4
|
-
|
|
5
|
-
To begin with Blits, follow these simple steps to set up your development environment and create your first Lightning 3 App.
|
|
6
|
-
|
|
7
|
-
### Installation
|
|
8
|
-
|
|
9
|
-
1. Open your terminal or command prompt.
|
|
10
|
-
|
|
11
|
-
2. Run the following command to start a new Blits Lightning 3 App project:
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
npx @lightningjs/blits@latest
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
You will be guide through a few short questions, to generate a new project with all the boilerplate code you need to start building your own Lightning 3 App.
|
|
18
|
-
|
|
19
|
-
3. Navigate to the newly created project directory and install the project dependencies:
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
cd my_blits_app
|
|
23
|
-
npm install
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### Running Your App
|
|
27
|
-
|
|
28
|
-
4. After installing the dependencies, you can start your development server by running:
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
npm run dev
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
This command will create an application bundle and launch a development server using Vite.
|
|
35
|
-
|
|
36
|
-
2. Once the server is up and running, open your web browser and navigate to the URL displayed in the console. Congratulations! You now have your brand new Blits Lightning 3 App up and running.
|
|
37
|
-
|
|
38
|
-
### Next steps
|
|
39
|
-
|
|
40
|
-
You are now ready to dive into the world of App development using Blits. In the following sections, we will explore the core concepts and guide you through building your TV applications step by step.
|
package/docs/props.md
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# Blits - Lightning 3 App Development Framework
|
|
2
|
-
|
|
3
|
-
## Props
|
|
4
|
-
|
|
5
|
-
Components in Blits have their own internal state and logic. However, as each component is part of the larger app's scope, they may need to display different behaviors or appearances based on the rest of the app. To achieve this, components can receive `props` from their parent component.
|
|
6
|
-
|
|
7
|
-
In the Component configuration object, you can specify exactly which props a component can accept. These props are passed to the child component via attributes in the parent component's template. Any attributes not explicitly defined as a prop will be ignored.
|
|
8
|
-
|
|
9
|
-
The `props` key in the Component configuration object should be an `Array`, where each item corresponds to a prop that the component can accept. The simplest way to define props is to list their names within the `props` array.
|
|
10
|
-
|
|
11
|
-
```javascript
|
|
12
|
-
{
|
|
13
|
-
props: ['x', 'color', 'index', 'alpha']
|
|
14
|
-
}
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Once specified, you can refer to these props inside the template of your component using the `$` sign, similar to how you would reference variables defined within your component's state (i.e. `<Element color="$color" />`). Likewise, you can access a prop inside a component's code (e.g., inside the `ready()` lifecycle hook) using `this.color` (note: without a dollar sign!).
|
|
18
|
-
|
|
19
|
-
Since props are used to pass information from a parent to a child, it's important not to attempt to modify props inside your child component. If changes based on the prop from the parent are needed, you can either reference the prop inside the component state (using `this.myprop`) or use the prop in a `computed` property.
|
|
20
|
-
|
|
21
|
-
For more advanced usage, you can define props using an array of objects for each prop. Within each prop object, you can:
|
|
22
|
-
|
|
23
|
-
- Specify a _default value_ for the prop if it's omitted.
|
|
24
|
-
- _Validate_ the value of the prop based on certain criteria.
|
|
25
|
-
- Mark the prop as _required_.
|
|
26
|
-
- Apply a `cast` function to modify the value passed as a prop.
|
|
27
|
-
|
|
28
|
-
```js
|
|
29
|
-
export default Blits.Component('MyComponent', {
|
|
30
|
-
// ...
|
|
31
|
-
props: [
|
|
32
|
-
'color',
|
|
33
|
-
{
|
|
34
|
-
key: 'alpha',
|
|
35
|
-
default: 0.5,
|
|
36
|
-
required: true,
|
|
37
|
-
validate(v) {
|
|
38
|
-
return v <= 1 && v >= 0;
|
|
39
|
-
},
|
|
40
|
-
cast: Number
|
|
41
|
-
}
|
|
42
|
-
]
|
|
43
|
-
})
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
You can mix and match the simple string notation with the more advanced object notation within the same `props` array.
|
package/docs/template_syntax.md
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# Blits - Lightning 3 App Development Framework
|
|
2
|
-
|
|
3
|
-
## Template structure
|
|
4
|
-
|
|
5
|
-
Blits uses an easy-to-read _XML-style_ template syntax. The syntax is inspired by frameworks like VueJS, so developers familiar with Vue will recognize certain concepts.
|
|
6
|
-
|
|
7
|
-
The _template_ key in the Componentn configuration object holds a string with an XML-like structure. Templates often span multiple lines, so it's advisable to use a JS template literal.
|
|
8
|
-
|
|
9
|
-
You can use different tags in your templates. And similar to HTML you can use arguments and nested tags. Self-closing tags and HTML-style comments are also supported.
|
|
10
|
-
|
|
11
|
-
The default tag within a template is the `<Element>` tag, which corresponds to a node in the Lightning 3 renderer. For each element, you can define a set of predefined render properties, such as `x`, `y`, `w`, `color`, and more. Detailed information regarding the attributes supported by the `<Element>` tag can be found [here](./element_attributes.md).
|
|
12
|
-
|
|
13
|
-
Consider the following template example:
|
|
14
|
-
|
|
15
|
-
```xml
|
|
16
|
-
<Element x="20" y="20">
|
|
17
|
-
<Element w="100" h="100" x="360" color="#0891b2" />
|
|
18
|
-
<Element w="$width" h="$height" color="$color" />
|
|
19
|
-
<Element :w="$changingWidth" :h="Math.floor($height / 5)" :color="$highlight" />
|
|
20
|
-
</Element>
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### Hardcoded arguments
|
|
24
|
-
|
|
25
|
-
In this template, you'll observe certain arguments with hardcoded values. You use these to configure the parts of your component that never change.
|
|
26
|
-
|
|
27
|
-
### Dynamic arguments
|
|
28
|
-
|
|
29
|
-
Additionally, some arguments contain a value prefixed with a dollar sign (`$`), representing _dynamic_ arguments. When the component renders, it automatically populates these dynamic values based on the component's state (or props or computed properties).
|
|
30
|
-
|
|
31
|
-
### Reactive arguments
|
|
32
|
-
|
|
33
|
-
Furthermore, certain arguments are prefixed with a colon sign (`:`), indicating _reactive_ arguments. These are not only dynamically set when your component renders, but also _rerender_ the corresponding part of the template whenever the referenced value in your component's internal state changes. This reactive data binding eliminates the need for manual template patching, as seen in Lightning 2.
|
|
34
|
-
|
|
35
|
-
Reactive arguments support _interpolation_, enabling the use of simple JavaScript instructions, such as ternary conditions or basic string and Math manipulations. For more complex logic, it's recommended to abstract this into a Component method or a Computed property.
|
|
36
|
-
|
|
37
|
-
## Custom components
|
|
38
|
-
|
|
39
|
-
As your component grows in complexity, you may want to reorganize your codebase with custom components, abstracting and reusing both templates and logic.
|
|
40
|
-
|
|
41
|
-
Inside a component template, you can utilize sub-components (i.e. a `Menu` component) and reference them with tags like `<Menu></Menu>`.
|
|
42
|
-
|
|
43
|
-
In order for the `<Menu />` tag to become available for use in a component's template, you first have to `import` the file that exports that component.
|
|
44
|
-
|
|
45
|
-
Next you have to _register_ this imported component using the `components`-key in the configuration object. The `components` key is an _object literal_, where the value is the reference to the Blits component. The key will correspond with the _tag_ that can be used to invoke the component.
|
|
46
|
-
|
|
47
|
-
```js
|
|
48
|
-
|
|
49
|
-
import Menu from './components/menu.js'
|
|
50
|
-
import Button from './components/button.js'
|
|
51
|
-
|
|
52
|
-
export default Blits.Component('MyComponent', {
|
|
53
|
-
components: {
|
|
54
|
-
Menu, // makes <Menu /> available for use in the template
|
|
55
|
-
MyButton: Button, // makes Button available as <MyButton /> in the template
|
|
56
|
-
},
|
|
57
|
-
template: `
|
|
58
|
-
<Element>
|
|
59
|
-
<Menu />
|
|
60
|
-
<MyButton />
|
|
61
|
-
</Element>
|
|
62
|
-
`
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
```
|
package/docs/watchers.md
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Blits - Lightning 3 App Development Framework
|
|
2
|
-
|
|
3
|
-
## Watching for Changes
|
|
4
|
-
|
|
5
|
-
In some cases, you may want to execute specific actions whenever the value of a state variable, a prop, or a computed property changes. These actions could involve dispatching an event or updating another state variable.
|
|
6
|
-
|
|
7
|
-
You might be tempted to handle this functionality inside a computed property, but this is not recommended. Computed properties should not have side effects, as side effects could potentially lead your app into an endless loop if not handled carefully.
|
|
8
|
-
|
|
9
|
-
Instead, Blits allows you to specify **watchers**.
|
|
10
|
-
|
|
11
|
-
### Using Watchers
|
|
12
|
-
|
|
13
|
-
Within the `watch` key of the Component configuration object, you can define an object of _watcher functions_.
|
|
14
|
-
|
|
15
|
-
The name of each function should correspond to the name of the internal state variable, prop, or computed property that you want to watch. Whenever the target value changes, the respective watcher function will be invoked.
|
|
16
|
-
|
|
17
|
-
The watcher function receives two arguments: the new value and the old value of the observed property. This allows you to perform specific actions based on the changes.
|
|
18
|
-
|
|
19
|
-
### Example:
|
|
20
|
-
|
|
21
|
-
```javascript
|
|
22
|
-
{
|
|
23
|
-
state() {
|
|
24
|
-
return {
|
|
25
|
-
alpha: 0.2
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
watch: {
|
|
29
|
-
alpha(value, oldValue) {
|
|
30
|
-
if(value > oldValue) {
|
|
31
|
-
// Execute some logic when the 'alpha' value increases
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
In this example, whenever the 'alpha' value changes, the watcher function associated with 'alpha' will be invoked. The function checks if the new value is greater than the old value and executes custom logic accordingly.
|
|
File without changes
|