因爲項目須要,須要使用Vue
的class語法配合TypeScript
來進行組件開發,我也簡單總結了一下Class語法與常規語法的對照,便於記憶和查閱。vue
項目中使用的是vue-class-component
、vue-property-decorator
配合TypeScript
來進行開發的,其中vue-class-component
提供了class語法,而vue-property-decorator
提供了一些裝飾器來方便代碼的組織和編寫。git
下面我將一一對照class語法與常規語法,但願可以方便各位讀者的使用和記憶,更多詳細信息,請參考下面的官方網站或者github文檔:github
注意:我將按照Vue
官方風格指南推薦的順序來進行一一對照,包含絕大多數經常使用寫法:vue-cli
Class語法:數組
import { Component, Vue } from 'vue-property-decorator'
import { CreateElement } from 'vue'
import Game from '../../components/game'
@Component({
components: {
game: Game
}
})
export default class Test extends Vue {
...
}
複製代碼
常規語法:promise
import Game from '../../components/game'
export default {
components: {
game: Game
}
...
}
複製代碼
注意:model屬性實際對應的是在Vue
中經常使用的指令v-model
,一般v-model
用於名爲value
的prop和名爲input
的事件,可是對於單選框、複選框等類型的輸入控件並不適用,經過model
能夠達到這個目的。因爲v-model
其實是經過事件監聽的方式實現的語法糖,使用model
屬性用於單選框、複選框等類型的控件,簡化了語法。bash
Class語法:babel
import { Vue, Component } from 'vue-property-decorator'
@Component
export default class Game extends Vue {
@Model('change', { type: Boolean }) readonly checked!: boolean
...
}
複製代碼
常規語法:ide
export default {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: {
type: Boolean
}
}
}
複製代碼
注意:下方的readonly
和: string | undefined
屬於TypeScript
語法,用於設置player屬性只讀,並設置player屬性的類型爲 string或者undefined。函數
Class語法:
import { Vue, Component, Prop } from 'vue-property-decorator'
@Component
export default class Game extends Vue {
@Prop(String) readonly player: string | undefined
...
}
複製代碼
常規語法:
export default {
props: {
player {
type: String
}
}
}
複製代碼
注意:data中的屬性在class語法中被定義爲了類的屬性,可是因爲在初始化的時候已經賦值,因此不須要再爲屬性設置類型,TypeScript
會推斷出屬性的類型(其中數組results設置了數組元素的類型)。
class語法:
import { Vue, Component } from 'vue-property-decorator'
@Component
export default class Game extends Vue {
// 定義data
private selectOptions = ['石頭', '剪刀', '布']
private results: string[] = []
private grade = 0
private round = 1
private playerSelected = ''
...
}
複製代碼
常規語法:
export default {
data(){
return {
selectOptions: ['石頭', '剪刀', '布'],
results: [],
grade: 0,
round: 1,
playerSelected: '',
}
}
}
複製代碼
class語法:
import { Vue, Component } from 'vue-property-decorator'
@Component
export default class HelloWorld extends Vue {
private firstName = 'Mark'
private lastName = 'Twain'
// 定義爲計算屬性的getter
get name() {
return this.firstName + ' ' + this.lastName
}
// 定義爲計算屬性的setter
set name(value) {
const splitted = value.split(' ')
this.firstName = splitted[0]
this.lastName = splitted[1] || ''
}
}
複製代碼
常規語法:
export default {
data () {
return {
firstName: 'Mark',
lastName: 'Twain',
}
},
computed: {
name: {
get: function() {
return this.firstName + ' ' + this.lastName
},
set: function(value) {
const splitted = value.split(' ')
this.firstName = splitted[0]
this.lastName = splitted[1] || ''
}
}
}
}
複製代碼
class語法:
import { Vue, Component, Watch } from 'vue-property-decorator'
@Component
export default class MyClass extends Vue {
@Watch('child')
onChildChanged(val: string, oldVal: string) {}
@Watch('person', { immediate: true, deep: true })
onPersonChanged1(val: Person, oldVal: Person) {}
@Watch('person')
onPersonChanged2(val: Person, oldVal: Person) {}
}
複製代碼
常規語法:
export default {
watch: {
child: [
{
handler: 'onChildChanged',
immediate: false,
deep: false
}
],
person: [
{
handler: 'onPersonChanged1',
immediate: true,
deep: true
},
{
handler: 'onPersonChanged2',
immediate: false,
deep: false
}
]
},
methods: {
onChildChanged(val, oldVal) {},
onPersonChanged1(val, oldVal) {},
onPersonChanged2(val, oldVal) {}
}
}
複製代碼
注意:生命週期鉤子函數包括:beforeCreate、created、beforeMounted、mounted、beforeUpdate、updated、activated、deactivated、beforeDestory、destoryed、errorCaptured;下面不會一一舉例,只會列出其中幾個,由於它們的class語法相似(用法不一樣)。
class語法:
class
語法中,生命週期鉤子函數被定義爲了類的方法。import { Vue, Component } from 'vue-property-decorator'
@Component
export default class MyClass extends Vue {
private mounted() {
console.log('mounted')
},
private updated() {
console.log('updated')
}
}
複製代碼
常規語法:
export default {
mounted() {
console.log('mounted')
},
updated() {
console.log('updated')
}
}
複製代碼
class語法:
class
語法中,methods中定義的方法被定義爲了類的方法。import { Vue, Component } from 'vue-property-decorator'
@Component
export default class MyClass extends Vue {
private clog(msg: string){
console.log(msg)
}
}
複製代碼
常規語法:
export default {
methods: {
clog(msg) {
console.log(msg)
}
}
}
複製代碼
注意:經過render函數,能夠代替字符串模板,該渲染函數接收一個 createElement 方法做爲第一個參數用來建立 VNode。
class語法:
class
語法中,render配合jsx
語法時須要配合相關插件使用@vue/babel-preset-jsx @vue/babel-
、helper-vue-jsx-merge-props
,可是若是項目是使用vue-cli建立的就不須要額外安裝這兩個插件,腳手架中已默認集成並配置。import { Vue, Component } from 'vue-property-decorator'
@Component
export default class MyClass extends Vue {
private render() {
const jsx = ...
return jsx
}
}
複製代碼
常規語法:
export default {
render: function (createElement, context) {
...
}
}
複製代碼
注意:這對選項須要一塊兒使用,以容許一個祖先組件向其全部子孫後代注入一個依賴,不論組件層次有多深;因此在通常的組件中並不適合使用,使用開發高階插件/組件庫。
class語法:
import { Component, Inject, Provide, Vue } from 'vue-property-decorator'
const symbol = Symbol('baz')
@Component
export class MyComponent extends Vue {
@Inject() readonly foo!: string
@Inject('bar') readonly bar!: string
@Inject({ from: 'optional', default: 'default' }) readonly optional!: string
@Inject(symbol) readonly baz!: string
@Provide() foo = 'foo'
@Provide('bar') baz = 'bar'
}
複製代碼
常規語法:
const symbol = Symbol('baz')
export const MyComponent = Vue.extend({
inject: {
foo: 'foo',
bar: 'bar',
optional: { from: 'optional', default: 'default' },
[symbol]: symbol
},
data() {
return {
foo: 'foo',
baz: 'bar'
}
},
provide() {
return {
foo: this.foo,
bar: this.baz
}
}
})
複製代碼
注意:這個其實是用來觸發當前實例上的事件的方法。 class語法:
import { Vue, Component, Emit } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
count = 0
@Emit()
addToCount(n: number) {
this.count += n
}
@Emit('reset')
resetCount() {
this.count = 0
}
@Emit()
returnValue() {
return 10
}
@Emit()
onInputChange(e) {
return e.target.value
}
@Emit()
promise() {
return new Promise(resolve => {
setTimeout(() => {
resolve(20)
}, 0)
})
}
}
複製代碼
常規語法:
export default {
data() {
return {
count: 0
}
},
methods: {
addToCount(n) {
this.count += n
this.$emit('add-to-count', n)
},
resetCount() {
this.count = 0
this.$emit('reset')
},
returnValue() {
this.$emit('return-value', 10)
},
onInputChange(e) {
this.$emit('on-input-change', e.target.value, e)
},
promise() {
const promise = new Promise(resolve => {
setTimeout(() => {
resolve(20)
}, 0)
})
promise.then(value => {
this.$emit('promise', value)
})
}
}
}
複製代碼
注意:mixins接收一個對象數組,其中的對象是包含vue選項(created、data、computed等)的對象,mixins中的對象會按照必定的規則與當前組件中的選項進行合併或者替換(同一類型相同名稱的選項中,原有的選項會覆蓋mixins中的選項)。
class語法:
聲明mixins Hello和的示例World:
// mixins.js
import Vue from 'vue'
import Component from 'vue-class-component'
// You can declare mixins as the same style as components.
@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'
// Use `mixins` helper function instead of `Vue`.
// `mixins` can receive any number of arguments.
@Component
export class HelloWorld extends mixins(Hello, World) {
created () {
console.log(this.hello + ' ' + this.world + '!') // -> Hello World!
}
}
複製代碼
常規語法:
聲明mixins Hello和的示例World:
// mixins.js
export default {
data() {
return {
hello: 'Hello',
world: 'World'
}
}
}
複製代碼
在類樣式組件中使用它們:
import { Hello, World } from './mixins'
export default {
created() {
console.log(this.hello + ' ' + this.world + '!') // -> Hello World!
},
mixins: [mixin]
}
複製代碼