一、前言
装饰器是ES2016
提出来的一个提案,当前处于Stage 2
阶段,通过本文学习,你将学到以下内容:
- 了解什么是装饰器
- 在
class
中使用装饰器 - 在方法使用装饰器
- 在
Vue
中使用装饰器 - 装饰器与注释的区别
二、什么是装饰器
装饰器是一种与类相关的语法糖,用来包装或者修改类或者类的方法的行为,其实装饰器就是设计模式中装饰者模式的一种实现方式。
三、装饰器分类
按照装饰器被装饰的特性来分,一共可以分为以下五种类:类装饰器、方法装饰器、属性装饰器、方法装饰器、访问符装饰器
3.1 类装饰器 Class Decorato
类装饰器在类声明之前被声明(紧靠着类声明),类装饰器可以拦截类的构造函数 constructor,这使得我们可以通过结合传入的 metadata,以此确定类在运行时是如何被处理、实例化以及使用的。
- 类的装饰器有一个参数,为类的构造函数,通过这个参数可以改变类上的属性方法等
- 类的装饰器会在类定义后执行,不需要类实例化
3.2 属性装饰器 Property Decorator
属性装饰器声明在一个属性声明之前(紧靠着属性声明),我们可以使用它来劫持属性的 getter 和 setter。
3.3 方法装饰器 Method Decorator
方法装饰器声明在一个方法的声明之前(紧靠着方法声明)。它会被应用到方法的属性描述符上,可以用来监视,修改或者替换方法定义。
3.4 参数装饰器 Parameter Decorator
参数装饰器声明在一个参数声明之前(紧靠着参数声明)。 参数装饰器应用于类构造函数或方法声明,但参数装饰器的返回值会被忽略。
3.5 访问符装饰器 Accessor Decorator
访问器装饰器声明在一个访问器的声明之前(紧靠着访问器声明)。访问器装饰器应用于访问器的 属性描述符并且可以用来监视,修改或替换一个访问器的定义。访问器装饰器不能用在声明文件中(.d.ts),或者任何外部上下文(比如 declare 的类)里。
四、 Vue中使用装饰器
vue-class-component是vue
作者尤大推出的一个支持使用class方式来开发vue
单文件组件的库。在Vue2.0中使用TypeScript
语法时,需要引用 vue-property-decorator
,且完全依赖于vue-class-component,有几个装饰器和 1 个函数 (Mixin)
@Prop
@PropSync
@Model
@ModelSync
@Watch
@Provide
@Inject
@ProvideReactive
@InjectReactive
@Emit
@Ref
@VModel
@Component
(由vue-class-component 提供)Mixins
(mixins
由vue-class-component提供的名为 helper 函数)
4.1 @Prop
我们在使用Vue
时有时会遇到子组件接收父组件传递来的参数.我们需要定义Prop
属性.
ES6写法
export default { props: { propA: { type: Number }, propB: { default: 'default value' }, propC: { type: [String, Boolean] }, } }
当我们在
vue
单文件中使用TypeScript
时,引入vue-property-decorator
之后,使用@Prop
<script lang="ts"> import {Vue, Component, Prop} from 'vue-property-decorator'; @Component({}) export default class "组件名" extends Vue{ @Prop(Number) propA!: number; @Prop({default: 'default value'}) propB!: string; @propC([String, Boolean]) propC: string | boolean; } </script>
总结:
@Prop
接受一个参数可以是类型变量或者对象或者数组.@Prop
接受的类型比如Number
是JavaScript
的类型,之后定义的属性类型则是TypeScript
的类型
4.2 @PropSync
4.3 @Model
4.4 @ModelSync
4.5 @Watch
4.6 @Provide
4.7 @Inject
4.8 @ProvideReactive
4.9 @InjectReactive
4.10 @Emit
4.11 @Ref
4.12 @VModel
4.13 @Component
4.14 Mixins
在使用Vue
进行开发时我们经常要用到混合
ES6写法
// 定义要混合的类pagination.js export default { data() { return { pagination: { page: 1, pageSize: 10, total: 0, showTotal: (total, range) => `共 ${total} 条` }, // requestData: { // page: this.pagination.page, // pageSize: this.pagination.pageSize, // }, } }, computed:{ requestData(){ return { page: this.pagination.page, pageSize: this.pagination.pageSize, }; } }, methods: { init() { }, search() { }, pageChange(page) { this.pagination.page = page; this.requestData.page = page.current; this.search(); } } }
// 引入 <script> import pagination from "@/mixins/pagination"; export default { components: {}, mixins: [pagination], data() { return { columns }, created() { this.init(); }, methods: { init(){ let app = this; app.loading = true; list(app.requestData).then(res=>{ app.dataSource = res.data.list; app.pagination.total = res.data.total; app.authList = []; res.data.authList.forEach(function (v) { const obj = { label: v.title, value: v.id }; app.authList.push(obj); }); app.loading = false; }) }, } } </script>
当我们在
vue
单文件中使用TypeScript
时,引入vue-property-decorator
之后,使用mixins
之后我们有两种mixins
的方法
vue-class-component
// 定义要混合的类 mixins.ts import Vue from 'vue'; import Component from 'vue-class-component'; @Component // 一定要用Component修饰 export default class myMixins extends Vue { value: string = "Hello" }
// 引入 import Component {mixins} from 'vue-class-component'; import myMixins from 'mixins.ts'; @Component export class myComponent extends mixins(myMixins) { // 直接extends myMinxins 也可以正常运行 created(){ console.log(this.value) // => Hello } }