├── .gitignore
├── LICENSE
├── README.md
├── component.go
├── directive.go
├── examples
├── basic
│ ├── basic.go
│ └── index.html
├── component
│ ├── index.html
│ └── main.go
├── computed
│ ├── computed.go
│ └── index.html
├── directive
│ ├── index.html
│ └── main.go
├── features
│ ├── features.go
│ └── index.html
└── unwritableTime
│ ├── index.html
│ └── main.go
├── extra.go
├── filter.go
├── inc_debug.go
├── inc_minified.go
├── jscode
├── debug
│ ├── inc.go
│ └── vue-2.1.10.inc.js
└── minified
│ ├── inc.go
│ └── vue-2.1.10.min.inc.js
├── mapping.go
├── option.go
└── vue.go
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | *.o
3 | *.a
4 | *.so
5 |
6 | # Folders
7 | _obj
8 | _test
9 |
10 | # Architecture specific extensions/prefixes
11 | *.[568vq]
12 | [568vq].out
13 |
14 | *.cgo1.go
15 | *.cgo2.c
16 | _cgo_defun.c
17 | _cgo_gotypes.go
18 | _cgo_export.*
19 |
20 | _testmain.go
21 |
22 | *.exe
23 | *.test
24 | *.prof
25 | examples/basic/basic.js.map
26 | examples/basic/basic.js
27 | examples/unwritableTime/unwritableTime.js
28 | examples/unwritableTime/unwritableTime.js.map
29 | examples/component/component.js
30 | examples/component/component.js.map
31 |
32 | node_modules/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 oskca
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gopherjs-vue
2 | VueJS bindings for gopherjs
3 |
4 | # Usage
5 |
6 | Combined the power of [Gopherjs][gopherjs] and [VueJS][vuejs], you can use
7 | `golang struct` to provide the two-way data-binding context for [VueJS][vuejs],
8 | and easily implements the popular browser `MVVM` models in Go.
9 |
10 | Currently `ViewModel/Component/Directive/Filter` are supported and wrapped in
11 | a gopherjs friendly way.
12 |
13 | These are the basic rules to use this package:
14 |
15 | * all `exported fields` of the `golang struct` would become VueJS Instance's
16 | data which can be used in the html to do data binding: v-bind, etc
17 |
18 | * all `exported funcs` of the `golang struct` would become VueJS Instance's
19 | methods which can be called as html event handler: v-on, etc
20 |
21 | * the `golang struct` talked above is actually of pointer type and
22 | should have an anonymous embeded `*js.Object` field and the `exported fields`
23 | should have proper `js struct tag` for bidirectionaly data bindings
24 |
25 | # Using the debug|dev version of VueJS
26 |
27 | This package includes the `minified|product version` of VueJS code by default,
28 | if you want to include the `debug|dev version` of of VueJS code, please specify
29 | buidling tags `debug` to the `gopherjs build` cmd as this:
30 |
31 | gopherjs build --tags debug main.go
32 |
33 | for more details please see the examples.
34 |
35 | # Basic example
36 |
37 | gopherjs code:
38 |
39 | ```go
40 | package main
41 |
42 | import (
43 | "github.com/gopherjs/gopherjs/js"
44 | "github.com/oskca/gopherjs-vue"
45 | )
46 |
47 | type Model struct {
48 | *js.Object // this is needed for bidirectional data bindings
49 | IntValue int `js:"integer"`
50 | Str string `js:"str"`
51 | }
52 |
53 | // this would be recognized as Inc in html
54 | func (m *Model) Inc() {
55 | m.IntValue += 1
56 | println("inc called")
57 | }
58 |
59 | // this would be recognized as Repeat in html
60 | func (m *Model) Repeat() {
61 | m.Str = m.Str + m.Str
62 | }
63 |
64 | // this would be recognized as Reset in html
65 | func (m *Model) Reset() {
66 | m.Str = "a string "
67 | }
68 |
69 | func main() {
70 | m := &Model{
71 | Object: js.Global.Get("Object").New(),
72 | }
73 | // field assignment is required in this way to make data passing works
74 | m.IntValue = 100
75 | m.Str = "a string"
76 | // create the VueJS viewModel using a struct pointer
77 | vue.New("#app", m)
78 | }
79 | ```
80 |
81 |
82 | html markup:
83 |
84 | ```html
85 |
86 |
87 |
88 |
89 |
90 |
integer: {{ integer }}
91 |
92 |
93 |
str: {{ str }}
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | ```
103 |
104 | compile and run, then there you are :)
105 |
106 | [gopherjs]: https://github.com/gopherjs/gopherjs
107 | [vuejs]: http://vuejs.org/
108 |
--------------------------------------------------------------------------------
/component.go:
--------------------------------------------------------------------------------
1 | package vue
2 |
3 | import (
4 | "github.com/gopherjs/gopherjs/js"
5 | )
6 |
7 | var (
8 | creatorPool = make([]*pool, 0)
9 | )
10 |
11 | type pool struct {
12 | creator func() (structPtr interface{})
13 | structPtr interface{}
14 | counter int
15 | }
16 |
17 | // Component is actually an Extended Vue SubClass,
18 | // which acts as a Component constructor in VueJS world
19 | // thus you can use Component.New to create a
20 | // preConfigured VueJS instance(*ViewModel).
21 | type Component struct {
22 | *ViewModel
23 | }
24 |
25 | // New create the component instance
26 | func (c *Component) New() *ViewModel {
27 | return newViewModel(c.Object.New())
28 | }
29 |
30 | func newComponent(o *js.Object) *Component {
31 | return &Component{
32 | ViewModel: newViewModel(o),
33 | }
34 | }
35 |
36 | // Register register Component:c in the global namespace
37 | func (c *Component) Register(name string) *Component {
38 | vue.Call("component", name, c)
39 | return c
40 | }
41 |
42 | func GetComponent(name string) *Component {
43 | return newComponent(vue.Call("component", name))
44 | }
45 |
46 | // NewComponent creates and registers a named global Component
47 | //
48 | // vmCreator should return a gopherjs struct pointer. see New for more details
49 | func NewComponent(
50 | vmCreator func() (structPtr interface{}),
51 | templateStr string,
52 | replaceMountPoint ...bool,
53 | ) *Component {
54 | // args
55 | idx := len(creatorPool)
56 | creatorPool = append(creatorPool, new(pool))
57 | creatorPool[idx].creator = vmCreator
58 | vmfn := func() interface{} {
59 | p := creatorPool[idx]
60 | if p.counter%3 == 0 {
61 | p.structPtr = p.creator()
62 | }
63 | p.counter += 1
64 | return p.structPtr
65 | }
66 | // opts
67 | opt := NewOption()
68 | opt.Data = vmfn
69 | opt.Template = templateStr
70 | opt.OnLifeCycleEvent(EvtBeforeCreate, func(vm *ViewModel) {
71 | vm.Options.Set("methods", js.MakeWrapper(vmfn()))
72 | vMap[vmfn()] = vm
73 | })
74 | return opt.NewComponent()
75 | }
76 |
--------------------------------------------------------------------------------
/directive.go:
--------------------------------------------------------------------------------
1 | package vue
2 |
3 | import "github.com/gopherjs/gopherjs/js"
4 | import "github.com/oskca/gopherjs-dom"
5 |
6 | type DirectiveBinding struct {
7 | *js.Object
8 | // name: the name of the directive, without the prefix.
9 | Name string `js:"name"`
10 | // value: The value passed to the directive. For example in v-my-directive="1 + 1", the value would be 2.
11 | Value string `js:"value"`
12 | // oldValue: The previous value, only available in update and componentUpdated. It is available whether or not the value has changed.
13 | OldValue string `js:"oldValue"`
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 | // modifiers: an object containing modifiers, if any.
19 | Modifiers *js.Object `js:"modifiers"`
20 | }
21 |
22 | // DirectiveCallback can be used in every directive callback functions
23 | type DirectiveCallback func(el *dom.Element, b *DirectiveBinding, vNode, oldVnode *js.Object)
24 |
25 | type Directive struct {
26 | *js.Object
27 | // // Name string
28 | // // advanced options
29 | // // Custom directive can provide a params array,
30 | // // and the Vue compiler will automatically extract
31 | // // these attributes on the element that the directive is bound to.
32 | // Params []string `js:"params"`
33 | // // If your custom directive is expected to be used on an Object,
34 | // // and it needs to trigger update when a nested property inside
35 | // // the object changes, you need to pass in deep: true in your directive definition.
36 | // Deep bool `js:"deep"`
37 | // // If your directive expects to write data back to
38 | // // the Vue instance, you need to pass in twoWay: true.
39 | // // This option allows the use of this.set(value) inside
40 | // // the directive:If your directive expects to write data back to
41 | // // the Vue instance, you need to pass in twoWay: true.
42 | // // This option allows the use of this.set(value) inside the directive
43 | // TwoWay bool `js:"twoWay"`
44 | // // Passing in acceptStatement:true enables
45 | // // your custom directive to accept inline statements like v-on does
46 | // AcceptStatement bool `js:"acceptStatement"`
47 | // // Vue compiles templates by recursively walking the DOM tree.
48 | // // However when it encounters a terminal directive,
49 | // // it will stop walking that element’s children.
50 | // // The terminal directive takes over the job of compiling the element and
51 | // // its children. For example, v-if and v-for are both terminal directives.
52 | // Terminal bool `js:"terminal"`
53 | // // You can optionally provide a priority number for your directive.
54 | // // If no priority is specified, a default priority will be used
55 | // // - 1000 for normal directives and 2000 for terminal directives.
56 | // // A directive with a higher priority will be processed earlier than
57 | // // other directives on the same element. Directives with
58 | // // the same priority will be processed in the order they appear in
59 | // // the element’s attribute list, although that order is not
60 | // // guaranteed to be consistent in different browsers.
61 | // Priority int `js:"priority"`
62 | }
63 |
64 | func NewDirective(updaterCallBack ...interface{}) *Directive {
65 | d := &Directive{
66 | Object: js.Global.Get("Object").New(),
67 | }
68 | if len(updaterCallBack) > 0 {
69 | d.SetUpdater(updaterCallBack[0])
70 | }
71 | return d
72 | }
73 |
74 | func (d *Directive) SetBinder(fnCallback interface{}) *Directive {
75 | d.Set("bind", fnCallback)
76 | return d
77 | }
78 |
79 | func (d *Directive) SetUnBinder(fnCallback interface{}) *Directive {
80 | d.Set("unbind", fnCallback)
81 | return d
82 | }
83 |
84 | func (d *Directive) SetUpdater(fnCallback interface{}) *Directive {
85 | d.Set("update", fnCallback)
86 | return d
87 | }
88 |
89 | func (d *Directive) Register(name string) {
90 | js.Global.Get("Vue").Call("directive", name, d.Object)
91 | }
92 |
--------------------------------------------------------------------------------
/examples/basic/basic.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/gopherjs/gopherjs/js"
5 | "github.com/oskca/gopherjs-vue"
6 | )
7 |
8 | type Model struct {
9 | *js.Object // this is needed for bidirectional data bindings
10 | IntValue int `js:"integer"`
11 | Str string `js:"str"`
12 | }
13 |
14 | // this would be recognized as Inc in html
15 | func (m *Model) Inc() {
16 | m.IntValue += 1
17 | println("inc called")
18 | }
19 |
20 | // this would be recognized as Repeat in html
21 | func (m *Model) Repeat() {
22 | m.Str = m.Str + m.Str
23 | }
24 |
25 | // this would be recognized as Reset in html
26 | func (m *Model) Reset() {
27 | m.Str = "a string "
28 | }
29 |
30 | func main() {
31 | m := &Model{
32 | Object: js.Global.Get("Object").New(),
33 | }
34 | // field assignment is required in this way to make data passing works
35 | m.IntValue = 100
36 | m.Str = "a string"
37 | // create the VueJS viewModel using a struct pointer
38 | vue.New("#app", m)
39 | }
40 |
--------------------------------------------------------------------------------
/examples/basic/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |