-
Notifications
You must be signed in to change notification settings - Fork 0
3. Signals (Reactivity) and Dynamic Render
NotElementImport edited this page Nov 10, 2024
·
6 revisions
There are mechanisms in the framework that allow you to achieve application reactivity.
First, we need to understand how reactivity works:
The Signal is responsible for the reactivity. Signal returns a structure with the value property. Which, when changed, sends an event for changes in the Signal object. That allows to work with small details in the framework in a rather optimized way.
Practice:
import { comp } from "horizon-core/component";
import { useSignal } from "horizon-core/state";
export default comp((_, { text, $ }) => {
// Creating Signal
const counter = useSignal(0)
// Creating button with click event and text like `Counter: ${counter.value}`
$('button', { '@click': () => counter.value++ }, () => {
text('Counter: ')
text(counter)
})
})To display your information in the DOM element. You can use the asRaw method in the configuration
import { comp } from "horizon-core/component";
import { useSignal } from "horizon-core/state";
export default comp((_, { text, $ }) => {
const name = useSignal('jonh doe', {
asRaw: value => `Hello ${value}!`
})
text(name)
})And the output will be
<span>Hello jonh doe!</span>Or another example:
import { comp } from "horizon-core/component";
import { useSignal } from "horizon-core/state";
export default comp((_, { text, $ }) => {
const blockConfig = useSignal({}, {
asRaw: value => `display: ${value.display}; width: ${display.width}em;`
})
blockConfig.display = 'flex'
blockConfig.width = 10
$('div', { style: blockConfig }, () => {
// ...Block content...
})
})And the output will be
<div style="display: flex; width: 10em;">
<!--...Block content...-->
</div>And all of the examples have reactivity
To keep track of Signal changes, you need to use the global method watch()
import { comp } from "horizon-core/component";
import { useSignal, watch } from "horizon-core/state";
export default comp((_, { text, $ }) => {
const counter = useSignal(0)
const unwatch = watch(counter, value => {
console.log(`Counter: ${value}`)
})
counter.value++
// Counter: 1
unwatch()
counter.value++
})Work with object/arrays
import { comp } from "horizon-core/component";
import { useSignal, watch } from "horizon-core/state";
export default comp((_, { text, $ }) => {
const data = useSignal({
first: 'test 1',
second: {
value: 'test 2'
}
})
watch(data, value => {
console.log(`Without deep: ${value}`)
})
watch(data, value => {
console.log(`With deep: ${value}`)
}, { deep: true })
data.value.first = 'New value test'
// Without deep: { "first": "New value test", "second": { value: "test 2" } }
// With deep: { "first": "New value test", "second": { value: "test 2" } }
data.value.second.value = 'Deep value test'
// With deep: { "first": "New value test", "second": { value: "Deep value test" } }
})Local property observe:
import { comp } from "horizon-core/component";
import { useSignal, watch } from "horizon-core/state";
export default comp((_, { text, $ }) => {
const person = useSignal({
lastName: 'Doe',
firstName: 'Jonh'
})
watch(person.value.firstName, value => {
console.log(`New name: ${value}`)
})
person.value.firstName = 'Mike'
// New name: Mike
})