# 类风格的组件

# 综述(对比 JS)

# JS 语法

对外暴露了一个处理后的 options 对象。

<script>
import Child from "path/to/Child";

export default {
  name: "component-name",
  components: {
    Child,
  },
  props: {
    msg: { type: String, default: "" },
  },
  data() {
    return {
      count: 10,
      price: 99,
    };
  },
  computed: {
    money() {
      return this.count * this.price;
    },
  },
  watch: {
    count(newValue, oldValue) {},
  },
  methods: {
    handleCountChange() {},
  },
  filters: {
    prefix(value) {
      return "$" + value;
    },
  },
  created() {},
  beforeRouteEnter(to, from, next) {
    console.log("beforeRouteEnter");
    next();
  },
  beforeRouteLeave(to, from, next) {
    // 可以通过 this 访问组件实例
    console.log("beforeRouteLeave");
    next();
  },
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# TS 语法

对外暴露了一个 Vue 子类,下面会详细介绍。

<script lang="ts">
import { Component, Vue, Prop, Watch } from "vue-property-decorator";
import Child from "path/to/Child.vue";

@Component({
  components: {
    Child,
  },

  /* router hooks */
  beforeRouteEnter(to, from, next) {
    console.log("beforeRouteEnter");
    next();
  },
  beforeRouteLeave(to, from, next) {
    // 可以通过 this 访问组件实例
    console.log("beforeRouteLeave");
    next();
  },
})
export default class ComponentName extends Vue {
  /* props */
  @Prop({ type: String, default: "" }) private msg!: string;

  /* data */
  private count: number = 10;
  private price = 99;

  /* computed */
  private get money(): number {
    return this.count * this.price;
  }

  /* watch */
  @Watch("count")
  private onCountChanged(newValue: number, oldValue: number): void {}

  /* methods */
  private handleCountChange() {}

  /* instance lifecycle hooks */
  private created() {}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# 组件

JS 语法

export default {};
1

TS 语法

import { Component, Vue } from "vue-property-decorator";

@Component
export default class Home extends Vue {}
1
2
3
4

深入理解 Component 装饰器

# props

JS 语法

export default {
  props: {
    msg: { type: String, default: "" },
  },
};
1
2
3
4
5

TS 语法

import { Component, Vue, Prop } from "vue-property-decorator";

@Component
export default class Home extends Vue {
  @Prop({ type: String, default: "" }) private msg!: string;
}
1
2
3
4
5
6

详细教程 (opens new window)

TIP

props name 后添加 ! 修饰符 是为了防止 Strict Class Initialization (opens new window) 警告。

# data

JS 语法

export default {
  data() {
    return {
      count: 10,
      price: 99,
    };
  },
};
1
2
3
4
5
6
7
8

TS 语法

import { Component, Vue } from "vue-property-decorator";

@Component
export default class Home extends Vue {
  private count: number = 10;
  private price = 99;
}
1
2
3
4
5
6
7

# computed

JS 语法

export default {
  computed: {
    money() {
      return this.count * this.price;
    },
  },
};
1
2
3
4
5
6
7

TS 语法

import { Component, Vue } from "vue-property-decorator";

@Component
export default class Home extends Vue {
  private get money(): number {
    return this.count * this.price;
  }
}
1
2
3
4
5
6
7
8

# methods

JS 语法

export default {
  methods: {
    handleCountChange() {},
  },
};
1
2
3
4
5

TS 语法

import { Component, Vue } from "vue-property-decorator";

@Component
export default class Home extends Vue {
  private handleCountChange() {}
}
1
2
3
4
5
6

# watch

JS 语法

export default {
  watch: {
    count(newValue, oldValue) {},
  },
};
1
2
3
4
5

TS 语法

import { Component, Vue, Watch } from "vue-property-decorator";

@Component
export default class Home extends Vue {
  private count: number = 10;

  @Watch("count")
  private onCountChanged(newValue: number, oldValue: number): void {}
}
1
2
3
4
5
6
7
8
9

# lifecycle hooks

JS 语法

export default {
  beforeCreate() {},
  created() {},
  beforeDestroy() {},
};
1
2
3
4
5

TS 语法

import { Component, Vue } from "vue-property-decorator";

@Component
export default class Home extends Vue {
  private beforeCreate() {}
  private created() {}
  private beforeDestroy() {}
}
1
2
3
4
5
6
7
8

# components

JS 语法

import Child from "path/to/Child";

export default {
  components: {
    Child,
  },
};
1
2
3
4
5
6
7

TS 语法

import { Component, Vue } from "vue-property-decorator";
import Child from "path/to/Child.vue";

@Component({
  components: {
    Child,
  },
})
export default class Home extends Vue {}
1
2
3
4
5
6
7
8
9

# router hooks

JS 语法

import Child from "path/to/Child";

export default {
  beforeRouteEnter(to, from, next) {
    console.log("beforeRouteEnter");
    next();
  },
  beforeRouteLeave(to, from, next) {
    // 可以通过 this 访问组件实例
    console.log("beforeRouteLeave");
    next();
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13

TS 语法

import { Component, Vue } from "vue-property-decorator";

@Component({
  /* router hooks */
  beforeRouteEnter(to, from, next) {
    console.log("beforeRouteEnter");
    next();
  },
  beforeRouteLeave(to, from, next) {
    // 可以通过 this 访问组件实例
    console.log("beforeRouteLeave");
    next();
  },
})
export default class Home extends Vue {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 总结

语法变更可以分成 3 类:

  • 直接写在类下
    • data, methods, render, errorCaptured
    • computed,类访问器写法 get
    • lifecycle hooks: beforeCreate, created, beforeMount, mounted, beforeDestroy, destroyed, beforeUpdate, updated, activated, 参见 (opens new window)
  • 需要装饰器:props, watch
  • 除了上述指明的属性外其余均需要放到 Component 装饰器的 options 内,如:
    • name, components, filters, directives
    • router hooks: beforeRouteEnter,beforeRouteUpdate, beforeRouteLeave

# 参考