README
Awesome Vue.TS
Why:
Awesome Vue.TS aims at getting type safety as much as possible, while still keeping TypeScript concise and idiomatic. To achieve this, av.ts exploits many techniques, tricks and hacks in TypeScript, which makes av.ts a good tour of TypeScript features.
Note: The target vue version is 2.0.
The canonical library does not
solve the problem that this.propertyInDataOption
is not checked by compiler.
Another popular library can provide more decorators for different usages and more type-safety.
None of the above two has taken extensibility into account. While av.ts pays attention how users can create their own decorators.
I believe av.ts have a good balance between safety, brevity, consistency and extensibility.
Usage:
component is declared via a decorated class.
extends
should work. (mixin
support is under consideration)data
,methods
andcomputed
can be declared by property initializer, member methods and property accessors in class body, respectively.props
are declared via@Prop
decorator and property initializer.render
and life cycle handler likecreated
is declared by decorated methods. They are declared in class body because these handlers usethis
. But you cannot invoke them on the instance itself. So they are decorated to remind users. When declaring custom methods, you should avoid these reserved names.watch
handlers are declared in@Watch
decorator, so user cannot watch the wrong property.All other options are considered as component's meta info. So users should declare them in the
@Componet
decorator function.
Example:
import {
Component, Prop, Watch, Lifecycle,
} from 'av.ts'
// meta info in `Component` decorator
@Component({
filters: {},
name: 'my-component',
delimiter: ['{{', '}}'],
})
export class MyComponent extends Vue { // extends Vue or your own component
// instance variable is in `data`
myData = '123'
// props declaration
@Prop myProp = p({
type: Object,
required: true,
default() {
return {a: 123, b: 456}
}
})
// method is `method`
myMethod() {
console.log('myMethod called!')
}
// accessor is `computed`
get myGetter() {
return this.myProp
}
// watch handler is declared by decorator
@Watch(function(){
console.log(this.myWatchee + 'changed!')
})
myWatchee = 'watch me!'
// lifecycle hook is speical so it is decorated
@Lifecycle beforeCreate() {}
}
which is equivalent to
let MyComponent = Vue.extend({
filters: {},
name: 'my-component',
delimiter: ['{{', '}}'],
data() {
return {
myData: '123',
myWatchee: 'watch me!'
}
},
props: {
myProp: {
type: Object,
required: true,
default() {
return {a: 123, b: 456}
}
}
},
methods: {
myMethod() {
console.log('my method called!')
}
},
computed: {
myGetter: {
get() {
return this.myProp
}
}
},
watch: {
myWatchee() {
console.log(this.myWatchee + 'changed!')
}
},
beforeCreate() {}
})
install
Via our old friend npm.
npm install av.ts --save
And don't forget installing vue. and then in your vue file.
import {Componet} from 'av.ts'
@Componet
class MyAwesomeComponent {
// ....
}
API
For full type signature, please refer to av.ts.d.ts
. They are most up-to-date.
Component
Type: ClassDecorator | (option) => ClassDecorator
It can be directly applied on component class as decorator, or take one option argument and return a decorator function.
@Component
class VueComp extends Vue {}
@Componet({
directive: {},
components: {},
functionals: {},
filters: {},
name: 'my-awesome-component',
delimiter: ['{{', '}}'],
})
class MyComponent extends Vue {}
Prop
Type: PropertyDecorator
Decorated properties should be the return value of utility function p
. p
is a function takes property option and return a fake type placeholder that will specify the property type. The fake type placeholder, at runtime, is just the config option object you feed to the argument.
@Prop
myProp = p({
type: Number,
default: 123
})
// p(option) returns a `number` type placeholder
// so the following code compiles
var num: number = p({
type: Number
})
// will print {type: Number}
console.log(num)
// you can also use a shorthand form of `p`
@Prop shortHand = p(String)
Watch
Contrary to vue-typescript, @Watch
is applied to a watched property.
Watch
takes handler as the first argument, and an optional config object as the second one.
// ....
@Watch(function(newVal, oldVal) {
console.log('the delta is ' + (newVal - oldVal))
}, {deep: true})
properyBeingWatched: number
// ....
is equivalent to
watch: {
properyBeingWatched: {
handler: function(newVal, oldVal) {
console.log('the delta is ' + (newVal - oldVal))
},
deep: true
}
}
and LifecycleRender
Type: TypedPropertyDecorator
mark decorated methods as special hooks in vue. You cannot call them in methods.
Transition
Type: TypedPropertyDecorator
mark method as a callback of transition component. method is still called in other instance methods. This decorator is solely for type checking.
common tricks
One can specify more specific class in vue special fields like $el
. This can be done by annotating types on a class property declaration without initializer.
class MyComponent extends Vue {
// instance property reification
$refs: {
mychild: Vue
}
// don't initialize `$el`
$el: HTMLDivElement
}
Difference
Added Feature:
functional component has its own assets slot.
new decorator
@Transition
for typechecking transition hooks!
Removed Feature:
- transitions is no longer needed given
<transition>
wrapper component.
Todo Features:
mixin
extends