This commit is contained in:
aaron 2023-08-04 15:38:16 +01:00
parent 13965868ce
commit c0c3d598b0
4 changed files with 82 additions and 53 deletions

View file

@ -44,7 +44,6 @@ To connect to an event, just set the event property name to a function.
All event arguments are passed into the function.
```lua
create "TextButton" {
Activated = function()
@ -53,8 +52,6 @@ create "TextButton" {
}
```
## Summary
In short:
- String keys = properties

View file

@ -1,6 +1,9 @@
# [State](./index.md)
State in Vide are special objects that store data.
State in Vide are the core of reactivity in Vide.
State contain values that can change, and when they do change, automatically
update anything that is using it.
A state object in Vide can be created using
[`source()`](../../api/reactivity-core.md#source).
@ -10,14 +13,14 @@ local source = vide.source
```
```lua
-- create a new source
local count = source(0)
```
-- set source value
count(10)
The value of a state can be set by calling it with an argument, and can be read
by calling it with no arguments.
-- get source value
print(count()) -- "10"
```lua
count(count() + 1) -- increment count state by 1
```
Below is an example of a counter component that has state.
@ -27,11 +30,11 @@ local function Counter()
local count = source(0)
return create "TextButton" {
Text = count
Text = count,
Activated = function()
count(count() + 1)
end,
end
}
end
```

View file

@ -3,6 +3,10 @@
You can create new state from existing states. This is known as *deriving
state*.
A function that wraps a state effectively becomes a state. If a state used
inside a function is updated, the whole function can be re-ran to recompute
its value.
```lua
local count = source(0)
@ -15,12 +19,14 @@ create "TextLabel" {
}
```
Assigning a non-event property a function will bind that property to that
function, anytime a state being read from inside that function is changed, the
function will be re-ran and the property value updated.
Sometimes when using expensive computations to derive state, you only want to
recalculate it when a source state has changed.
recalculate it once when a source state has changed
If you wrap a source state with a regular function, its value will be recomputed
every time you call that function.
[`derive()`](../../api/reactivity-core.md#derive) accepts a functions whose
return value will be cached, so that subsequent calls of this derived state
will return the same cached value until one of its source states have changed.
```lua
local derive = vide.derive
@ -38,18 +44,17 @@ local factorial = derive(function()
end)
```
`derive()` will cache and return the same value until a source state has
changed, where it will recompute and cache a new value.
This can improve performance for expensive calculations.
```lua
create "TextLabel" {
Text = function()
return "factorial: " .. factorial()
return "factorial squared: " .. factorial() * factorial()
end
}
count(3) -- displays "factorial: 6"
count(4) -- displays "factorial: 24"
count(3) -- displays "factorial squared: 36"
count(4) -- displays "factorial squared: 576"
```
--------------------------------------------------------------------------------

View file

@ -1,8 +1,43 @@
# [Property Groups](./index.md)
When a key is assigned a table, Vide does not attempt to assign it to a
property, instead, the table is iterated and processed just like the nesting
table.
Often when creating components from existing components, you can find yourself
repetitively passing through properties such as size or position.
```lua
function Background(props: {
Color: Color3,
AnchorPoint: UDim2,
Position: UDim2,
Size: UDim2
})
return create "Frame" {
Color = props.Color
AnchorPoint = props.AnchorPoint,
Position = props.Position,
Size = props.Size
}
end
function Menu(props: {
Color = props.Color
AnchorPoint: UDim2,
Position: UDim2,
Size: UDim2
})
return Background {
Color = props.COlor,
AnchorPoint = props.AnchorPoint,
Position = props.Position,
Size = props.Size
}
end
```
One way this can be avoided is by using *property nesting*. In Vide, passign a
table value inside `props` has special semantics. Any key with a table value is
not assigned like a property, instead the table is iterated and processed just
like the outer table is. Any properties in the nested table will be assigned
to the instance just the same.
Below is an example of how you can use this to pass groups of similar properties
together such as position and size, while also using typechecking.
@ -16,48 +51,36 @@ type Layout = {
}
}
local function Button(args: Layout & {
Text: string,
Callback: () -> ()
})
local count = source(0)
return create "TextButton" {
Text = args.Text
Activated = args.Callback,
Layout = args.Layout
function Background(props: Layout & { Color: Color3 })
return create "Frame" {
Color = props.Color,
props.Layout
}
end
Button {
Text = "Click me!",
Callback = function()
print "clicked me!"
end,
Layout = {
Position = UDim2.new(),
Size = UDim2.new()
}
function Menu(props: Layout & { Color: Color3 })
return Background {
Color = props.Color,
Layout = props.Layout
}
end
```
Here the button component is assigned a position and size as if you passed those
properties directly.
Here we created a nested group with the key `Layout` that can accept
layout-related properties. Any name could be chosen for the key.
This allows us to write much more concise syntax that is also typecheckable.
The same can be done for properties such as children.
The same can be done for properties such as children to pass table of instances.
```lua
type Children = {
Children = Array<Instance>
}
local function List(args: Children & Layout)
local function List(props: Children & Layout)
return create "Frame" {
Layout = args.Layout,
Children = args.Children,
props.Layout,
props.Children,
create "UIListLayout" {}
}
end
@ -68,7 +91,8 @@ List {
},
Children = {
create "TextLabel" { Text = "1" }
create "TextLabel" { Text = "1" },
create "TextLabel" { Text = "2" }
}
}
```