Vue的class语法与常规语法对照表

2,861 阅读5分钟

由于项目需要,需要使用Vueclass语法配合TypeScript 来进行组件开发,我也简单总结了一下Class语法与常规语法的对照,便于记忆和查阅。

项目中使用的是vue-class-componentvue-property-decorator配合TypeScript来进行开发的,其中vue-class-component提供了class语法,而vue-property-decorator提供了一些装饰器来方便代码的组织和编写。

下面我将一一对照class语法与常规语法,希望能够方便各位读者的使用和记忆,更多详细信息,请参考下面的官方网站或者github文档:

注意:我将按照Vue官方风格指南推荐的顺序来进行一一对照,包含绝大多数常用写法:

components

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 {
	...
}

常规语法:

import Game from '../../components/game'
export default {
	components: {
		game: Game
	}
	...
}

model

注意:model属性实际对应的是在Vue中常用的指令v-model,通常v-model用于名为value的prop和名为input的事件,但是对于单选框、复选框等类型的输入控件并不适用,通过model可以达到这个目的。由于v-model实际上是通过事件监听的方式实现的语法糖,使用model属性用于单选框、复选框等类型的控件,简化了语法。

Class语法:

import { Vue, Component } from 'vue-property-decorator'
@Component
export default class Game extends Vue {
	@Model('change', { type: Boolean }) readonly checked!: boolean
	...
}

常规语法:

export default {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: {
      type: Boolean
    }
  }
}

props

注意:下方的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

注意: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: '',
		}
	}
}

computed

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] || ''
			}
		}
	}
}

watch

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')
	}
}

methods

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

注意:通过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) {
		...
	}
}

provide / inject

注意:这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深;所以在一般的组件中并不适合使用,使用开发高阶插件/组件库。

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
    }
  }
})

Emit

注意:这个实际上是用来触发当前实例上的事件的方法。 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

注意: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]
}