前言
vue官网推荐了一个叫vue-class-component的包,可以以class的模式写vue组件。
类组件
@Component 装饰器使您的类成为Vue组件
import Vue from 'vue'
import Component from 'vue-class-component'
// HelloWorld class will be a Vue component
@Component
export default class HelloWorld extends Vue {}
data
@Component
export default class HelloWorld extends Vue {
// data可以直接声明为类属性
message = 'Hello World!'
}
methods
@Component
export default class HelloWorld extends Vue {
// methods可以直接声明为类方法
hello() {
console.log('Hello World!')
}
}
computed
@Component
export default class HelloWorld extends Vue {
name = 'John'
// computed声明为类属性getter / setter
get name() {
return this.name
}
set name(value) {
this.name= value
}
}
hooks
@Component
export default class HelloWorld extends Vue {
// 所有Vue生命周期挂钩也可以直接声明为类原型方法,但是您不能在实例本身上调用它们。
// 声明自定义方法时,应避免使用这些保留名称。
mounted() {
console.log('mounted')
}
}
其他配置项
import Vue from 'vue'
import Component from 'vue-class-component'
import OtherComponent from './OtherComponent.vue'
@Component({
// 对于所有其他选项,将它们传递给装饰器函数
// See Vue.js docs for all available options:
// https://vuejs.org/v2/api/#Options-Data
components: {
OtherComponent
}
})
export default class HelloWorld extends Vue {}
注册钩子
使用Vue Router等Vue插件,可能希望类组件解析它们提供的钩子
在这种情况下,Component.registerHooks允许注册钩子
注册钩子后,类组件将它们实现为类原型方法
注意:必须在组件定义之前对其进行注册
import Component from 'vue-class-component'
Component.registerHooks([
'beforeRouteEnter',
'beforeRouteLeave',
'beforeRouteUpdate'
])
extend
Vue类组件支持继承
@Component
export default class Super extends Vue { // 父组件
superValue = 'Hello'
}
@Component
export default class HelloWorld extends Super { // 继承
created() {
console.log(this.superValue) // -> Hello
}
}
mixins
Vue类组件提供了mixins辅助功能,以类样式方式使用mixins。通过使用mixins帮助程序,TypeScript可以推断混合类型并在组件类型上继承它们。
注意:所有mixin必须声明为类组件
// mixins.js
import Vue from 'vue'
import Component from 'vue-class-component'
@Component
export class Hello extends Vue {
hello = 'Hello'
}
@Component
export class World extends Vue {
world = 'World'
}
import Component, { mixins } from 'vue-class-component'
import { Hello, World } from './mixins'
@Component
export class HelloWorld extends mixins(Hello, World) {
created () {
console.log(this.hello + ' ' + this.world + '!')
}
}
props
Vue类组件没有提供用于props定义的专用API。但是,可以通过Vue.extend来实现
const GreetingProps = Vue.extend({
props: {
name: String
}
})
@Component
export default class Greeting extends GreetingProps {
get message(): string {
// this.name will be typed
return 'Hello, ' + this.name
}
}
extends 被占用了,如果想继承类组件或者混入时,可以使用mixins来实现
import Vue from 'vue'
import Component, { mixins } from 'vue-class-component'
import Super from './super'
const GreetingProps = Vue.extend({
props: {
name: String
}
})
@Component
export default class Greeting extends mixins(GreetingProps, Super) {
get message(): string {
return 'Hello, ' + this.name
}
}
vuex
import Vue from 'vue'
import Component from 'vue-class-component'
import { mapGetters, mapActions } from 'vuex'
import { Post } from './post'
@Component({
computed: mapGetters([
'posts'
]),
methods: mapActions([
'fetchPosts'
])
})
export default class Posts extends Vue {
posts!: Post[]
fetchPosts!: () => Promise<void>
mounted() {
this.fetchPosts().then(() => {
console.log(this.posts)
})
}
}
$refs
$refs组件的类型声明为处理所有可能的ref类型的最广泛的类型。虽然理论上是正确的,但在大多数情况下,每个ref在实践中仅具有特定的元素或组件。
可以通过覆盖$refs类组件中的类型来指定特定的引用类型
<template>
<input ref="input">
</template>
@Component
export default class InputFocus extends Vue {
// `!` (显式赋值断言,就是由用户自己保证,这个属性在使用前会初始化,类型检查不管这个属性了)
// 这样就可以消除编译错误
$refs!: {
input: HTMLInputElement
}
mounted() {
this.$refs.input.focus()
}
}