Skip to content

Commit 9f7a09a

Browse files
committed
add package directive
1 parent d05e57e commit 9f7a09a

File tree

1 file changed

+218
-0
lines changed

1 file changed

+218
-0
lines changed

directive/derective.go

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
package directive
2+
3+
import (
4+
"github.com/gopherjs/gopherjs/js"
5+
"github.com/oskca/gopherjs-vue"
6+
)
7+
8+
type Context struct {
9+
*js.Object
10+
// el: the element the directive is bound to.
11+
El *js.Object `js:"el"`
12+
// vm: the context ViewModel that owns this directive.
13+
Vm *vue.Vue `js:"vm"`
14+
// expression: the expression of the binding, excluding arguments and filters.
15+
Expression string `js:"expression"`
16+
// arg: the argument, if present.
17+
Arg string `js:"arg"`
18+
// name: the name of the directive, without the prefix.
19+
Name string `js:"name"`
20+
// modifiers: an object containing modifiers, if any.
21+
Modifiers *js.Object `js:"modifiers"`
22+
// descriptor: an object that contains the parsing result of the entire directive.
23+
Descriptor *js.Object `js:"descriptor"`
24+
// params: an object containing param attributes. Explained below.
25+
Params *js.Object `js:"params"`
26+
}
27+
28+
func makeUpdater(fn func(ctx *Context, newValue, oldValue *js.Object)) *js.Object {
29+
return js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} {
30+
ctx := &Context{
31+
Object: this,
32+
}
33+
fn(ctx, args[0], args[1])
34+
return nil
35+
})
36+
}
37+
38+
func makeBinder(fn func(*Context)) *js.Object {
39+
return js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} {
40+
ctx := &Context{
41+
Object: this,
42+
}
43+
fn(ctx)
44+
return nil
45+
})
46+
}
47+
48+
// func Directive(
49+
// name string,
50+
// update func(ctx *Context, newValue, oldValue *js.Object),
51+
// ) {
52+
// fn := js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} {
53+
// ctx := &Context{
54+
// Object: this,
55+
// }
56+
// update(ctx, args[0], args[1])
57+
// return nil
58+
// })
59+
// vue.Call("directive", name, fn)
60+
// }
61+
62+
// func DirectiveEx(
63+
// name string,
64+
// bind func(ctx *Context),
65+
// update func(ctx *Context, newValue, oldValue *js.Object),
66+
// unbind func(ctx *Context),
67+
// ) {
68+
// fnInit := js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} {
69+
// ctx := &Context{
70+
// Object: this,
71+
// }
72+
// bind(ctx)
73+
// return nil
74+
// })
75+
// fnUpdate := js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} {
76+
// ctx := &Context{
77+
// Object: this,
78+
// }
79+
// update(ctx, args[0], args[1])
80+
// return nil
81+
// })
82+
// fnUnbind := js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} {
83+
// ctx := &Context{
84+
// Object: this,
85+
// }
86+
// unbind(ctx)
87+
// return nil
88+
// })
89+
// vue.Call("directive", name, js.M{
90+
// "bind": fnInit,
91+
// "update": fnUpdate,
92+
// "unbind": fnUnbind,
93+
// })
94+
// }
95+
96+
// func Directive(
97+
// name string,
98+
// update func(ctx *Context, newValue, oldValue *js.Object),
99+
// ) {
100+
// vue.Call("directive", name, makeUpdater(update))
101+
// }
102+
103+
// func DirectiveEx(
104+
// name string,
105+
// bind func(ctx *Context),
106+
// update func(ctx *Context, newValue, oldValue *js.Object),
107+
// unbind func(ctx *Context),
108+
// ) {
109+
// vue.Call("directive", name, js.M{
110+
// "bind": makeBinder(bind),
111+
// "update": makeUpdater(update),
112+
// "unbind": makeBinder(unbind),
113+
// })
114+
// }
115+
116+
// In some cases, we may want our directive to be used in the form of
117+
// a custom element rather than as an attribute.
118+
// This is very similar to Angular’s notion of “E” mode directives.
119+
// Element directives provide a lighter-weight alternative to
120+
// full-blown components (which are explained later in the guide).
121+
//
122+
// Element directives cannot accept arguments or
123+
// expressions, but it can read the element’s attributes to
124+
// determine its behavior.
125+
//
126+
// A big difference from normal directives is that
127+
// element directives are terminal, which means once Vue encounters
128+
// an element directive, it will completely skip that element
129+
// - only the element directive itself will be
130+
// able to manipulate that element and its children.
131+
// func ElementDirective(
132+
// name string,
133+
// update func(ctx *Context, newValue, oldValue *js.Object),
134+
// ) {
135+
// vue.Call("elementDirective", name, makeUpdater(update))
136+
// }
137+
138+
// func ElementDirectiveEx(
139+
// name string,
140+
// bind func(ctx *Context),
141+
// update func(ctx *Context, newValue, oldValue *js.Object),
142+
// unbind func(ctx *Context),
143+
// ) {
144+
// vue.Call("elementDirective", name, js.M{
145+
// "bind": makeBinder(bind),
146+
// "update": makeUpdater(update),
147+
// "unbind": makeBinder(unbind),
148+
// })
149+
// }
150+
151+
type Directive struct {
152+
*js.Object
153+
Name string
154+
// advanced options
155+
// Custom directive can provide a params array,
156+
// and the Vue compiler will automatically extract
157+
// these attributes on the element that the directive is bound to.
158+
Params []string `js:"params"`
159+
// If your custom directive is expected to be used on an Object,
160+
// and it needs to trigger update when a nested property inside
161+
// the object changes, you need to pass in deep: true in your directive definition.
162+
Deep bool `js:"deep"`
163+
// If your directive expects to write data back to
164+
// the Vue instance, you need to pass in twoWay: true.
165+
// This option allows the use of this.set(value) inside
166+
// the directive:If your directive expects to write data back to
167+
// the Vue instance, you need to pass in twoWay: true.
168+
// This option allows the use of this.set(value) inside the directive
169+
TwoWay bool `js:"twoWay"`
170+
// Passing in acceptStatement:true enables
171+
// your custom directive to accept inline statements like v-on does
172+
AcceptStatement bool `js:"acceptStatement"`
173+
// Vue compiles templates by recursively walking the DOM tree.
174+
// However when it encounters a terminal directive,
175+
// it will stop walking that element’s children.
176+
// The terminal directive takes over the job of compiling the element and
177+
// its children. For example, v-if and v-for are both terminal directives.
178+
Terminal bool `js:"terminal"`
179+
// You can optionally provide a priority number for your directive.
180+
// If no priority is specified, a default priority will be used
181+
// - 1000 for normal directives and 2000 for terminal directives.
182+
// A directive with a higher priority will be processed earlier than
183+
// other directives on the same element. Directives with
184+
// the same priority will be processed in the order they appear in
185+
// the element’s attribute list, although that order is not
186+
// guaranteed to be consistent in different browsers.
187+
Priority int `js:"priority"`
188+
}
189+
190+
func New(name string, updater ...func(ctx *Context, newValue, oldValue *js.Object)) *Directive {
191+
d := &Directive{
192+
Name: name,
193+
Object: js.Global.Get("Object").New(),
194+
}
195+
if len(updater) > 0 {
196+
d.SetUpdater(updater[0])
197+
}
198+
return d
199+
}
200+
201+
func (d *Directive) SetBinder(fn func(ctx *Context)) *Directive {
202+
d.Set("bind", makeBinder(fn))
203+
return d
204+
}
205+
206+
func (d *Directive) SetUnBinder(fn func(ctx *Context)) *Directive {
207+
d.Set("unbind", makeBinder(fn))
208+
return d
209+
}
210+
211+
func (d *Directive) SetUpdater(fn func(ctx *Context, newValue, oldValue *js.Object)) *Directive {
212+
d.Set("update", makeUpdater(fn))
213+
return d
214+
}
215+
216+
func (d *Directive) Register() {
217+
js.Global.Get("Vue").Call("directive", d.Name, d.Object)
218+
}

0 commit comments

Comments
 (0)