Skip to content

Commit 13158de

Browse files
committed
init
0 parents  commit 13158de

File tree

8 files changed

+244
-0
lines changed

8 files changed

+244
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
example/build.js

README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# vue-classy
2+
3+
> Experimental ES7 / TypeScript decorator for class-style Vue components.
4+
5+
### Example Usage with Babel stage=0:
6+
7+
``` js
8+
import Vue from 'vue'
9+
import VueClassy from 'vue-classy'
10+
11+
Vue.use(VueClassy)
12+
13+
@Vue.componentClass
14+
export default class Component extends Vue {
15+
16+
// template
17+
static template = `
18+
<div>
19+
<input v-model="msg">
20+
<p>msg: {{msg}}</p>
21+
<p>computed msg: {{computedMsg}}</p>
22+
<button v-on="click:greet">Greet</button>
23+
</div>
24+
`
25+
26+
// data
27+
msg = 'hello'
28+
29+
// computed
30+
get computedMsg() {
31+
return 'computed ' + this.msg
32+
}
33+
34+
// method
35+
greet() {
36+
alert('greeting: ' + this.msg)
37+
}
38+
39+
// lifecycle hook
40+
ready() {
41+
this.greet()
42+
}
43+
}
44+
45+
// mount
46+
new Component({
47+
el: '#el'
48+
})
49+
```
50+
51+
### Build the Example
52+
53+
``` bash
54+
$ npm install && npm run build
55+
```
56+
57+
Theoretically, this should also work properly as a TypeScript 1.5+ decorator. If you'd like to make it work properly with TypeScript, feel free to contribute!

example/example.es

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import Vue from 'vue'
2+
import VueClassy from '../'
3+
4+
Vue.use(VueClassy)
5+
6+
@Vue.componentClass
7+
export default class Component extends Vue {
8+
9+
// template
10+
static template = `
11+
<div>
12+
<input v-model="msg">
13+
<p>msg: {{msg}}</p>
14+
<p>computed msg: {{computedMsg}}</p>
15+
<button v-on="click:greet">Greet</button>
16+
</div>
17+
`
18+
19+
// data
20+
msg = 'hello'
21+
22+
// computed
23+
get computedMsg() {
24+
return 'computed ' + this.msg
25+
}
26+
27+
// method
28+
greet() {
29+
alert('greeting: ' + this.msg)
30+
}
31+
32+
// lifecycle hook
33+
ready() {
34+
this.greet()
35+
}
36+
}
37+
38+
// mount
39+
new Component({
40+
el: '#el'
41+
})

example/example.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title></title>
6+
</head>
7+
<body>
8+
<div id="el"></div>
9+
<script src="build.js"></script>
10+
</body>
11+
</html>

example/webpack.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module.exports = {
2+
entry: './example/example.es',
3+
output: {
4+
path: './example',
5+
filename: 'build.js'
6+
},
7+
module: {
8+
loaders: [
9+
{ test: /\.es$/, loader: 'babel?stage=0' }
10+
]
11+
}
12+
}

index.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
var Vue
2+
3+
var internalHooks = [
4+
'created',
5+
'ready',
6+
'beforeCompile',
7+
'compiled',
8+
'beforeDestroy',
9+
'destroyed',
10+
'attached',
11+
'detached'
12+
]
13+
14+
function decorate (Component) {
15+
var capture = new Component(false)
16+
var options = {}
17+
// instance properties are data
18+
var fields = Object.keys(capture)
19+
if (fields.length) {
20+
options.data = function () {
21+
return clone(capture)
22+
}
23+
}
24+
// prototype props.
25+
// only need to identify hooks and methods.
26+
// computed properties just work!
27+
var proto = Component.prototype
28+
Object.getOwnPropertyNames(proto).forEach(function (key) {
29+
if (key === 'constructor') {
30+
return
31+
}
32+
// hooks
33+
if (internalHooks.indexOf(key) > -1) {
34+
options[key] = proto[key]
35+
return
36+
}
37+
// methods
38+
var descriptor = Object.getOwnPropertyDescriptor(proto, key)
39+
if (typeof descriptor.value === 'function') {
40+
(options.methods || (options.methods = {}))[key] = descriptor.value
41+
}
42+
})
43+
// copy static options
44+
Object.keys(Component).forEach(function (key) {
45+
options[key] = Component[key]
46+
})
47+
// set options
48+
var Super = proto.__proto__.constructor
49+
Component.options = Vue.util.mergeOptions(Super.options, options)
50+
Component['super'] = Super
51+
Component.extend = Super.extend
52+
// asset registers
53+
Vue.config._assetTypes.forEach(function (type) {
54+
Component[type] = Super[type]
55+
})
56+
}
57+
58+
function clone (val) {
59+
if (typeof val !== 'object') {
60+
return val
61+
} else if (Array.isArray(val)) {
62+
return val.map(clone)
63+
} else {
64+
var res = {}
65+
Object.keys(val).forEach(function (key) {
66+
res[key] = clone(val[key])
67+
})
68+
return res
69+
}
70+
}
71+
72+
function install (externalVue) {
73+
Vue = externalVue
74+
Vue.componentClass = decorate
75+
}
76+
77+
module.exports = install

package.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"name": "vue-classy",
3+
"version": "1.0.0",
4+
"description": "ES7/TypeScript class decorator for Vue components",
5+
"main": "index.js",
6+
"scripts": {
7+
"build": "webpack --config example/webpack.config.js"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/vuejs/vue-classy.git"
12+
},
13+
"keywords": [
14+
"vue",
15+
"class",
16+
"babel",
17+
"typescript"
18+
],
19+
"author": "Evan You",
20+
"license": "MIT",
21+
"bugs": {
22+
"url": "https://github.com/vuejs/vue-classy/issues"
23+
},
24+
"homepage": "https://github.com/vuejs/vue-classy#readme",
25+
"devDependencies": {
26+
"babel-core": "^5.6.7",
27+
"babel-loader": "^5.2.0",
28+
"node-libs-browser": "^0.5.2",
29+
"vue": "^0.12.3",
30+
"webpack": "^1.9.12"
31+
}
32+
}

webpack.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module.exports = {
2+
entry: './test/test.js',
3+
output: {
4+
path: './test',
5+
filename: 'build.js'
6+
},
7+
module: {
8+
loaders: [
9+
{ test: /\.es$/, loader: 'babel?stage=0' }
10+
]
11+
}
12+
}

0 commit comments

Comments
 (0)