-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathcontext.go
80 lines (69 loc) · 2.21 KB
/
context.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package vue
import (
"fmt"
"reflect"
)
// Context is received by functions to interact with the component.
type Context interface {
Data() interface{}
Get(field string) interface{}
Set(field string, value interface{})
Go(method string, args ...interface{})
Emit(event string, args ...interface{})
}
// Data returns the data for the component.
// Props and computed are excluded from data.
func (vm *ViewModel) Data() interface{} {
return vm.data.Interface()
}
// Get returns the data field value.
// Props and computed are included to get.
// Computed may be calculated as needed.
func (vm *ViewModel) Get(field string) interface{} {
if value, ok := vm.state[field]; ok {
return value
}
function, ok := vm.comp.computed[field]
if !ok {
must(fmt.Errorf("unknown data field: %s", field))
}
value := vm.compute(function)
vm.mapField(field, value)
return value
}
// Set assigns the data field to the given value.
// Props and computed are excluded to set.
func (vm *ViewModel) Set(field string, value interface{}) {
data := reflect.Indirect(vm.data)
oldVal := reflect.Indirect(data.FieldByName(field))
newVal := reflect.Indirect(reflect.ValueOf(value))
oldVal.Set(newVal)
vm.mapField(field, value)
}
// Go asynchronously calls the given method with optional arguments.
// Blocking functions must be called asynchronously.
func (vm *ViewModel) Go(method string, args ...interface{}) {
values := make([]reflect.Value, 0, len(args))
for _, arg := range args {
values = append(values, reflect.ValueOf(arg))
}
go vm.call(method, values)
}
// Emit dispatches the given event with optional arguments.
func (vm *ViewModel) Emit(event string, args ...interface{}) {
vm.bus.pub(event, "", args)
}
// call calls the given method with optional values then calls render.
func (vm *ViewModel) call(method string, values []reflect.Value) {
if function, ok := vm.comp.methods[method]; ok {
values = append([]reflect.Value{reflect.ValueOf(vm)}, values...)
function.Call(values)
vm.render()
}
}
// compute calls the given function and returns the first element.
func (vm *ViewModel) compute(function reflect.Value) interface{} {
values := []reflect.Value{reflect.ValueOf(vm)}
rets := function.Call(values)
return rets[0].Interface()
}