2020-07-02 初稿 2021-04-29 补充

公司用 ts 写 vue 项目,经过初步的了解记录在此。

重新开始

我们先通过一个全新项目来尝试 ts,通过 vue create ts-vue-demo 再创建过程中选择 ts

初始化之后,看到新增两个依赖:

  • vue-class-component
  • vue-property-decorator

几个开发依赖:

  • @vue/cli-plugin-typescript
  • @vue/eslint-config-typescript
  • typescript
  • vue-template-combiler

其中 vue-class-componentvuejs 官方推出的。

vue-class-component

这里摘录官方的代码,看看怎么用

  1. // 固定写法,分别引入 Vue Component
  2. import Vue from 'vue'
  3. import Component from 'vue-class-component'
  4. // 装饰器,本质上是一个函数
  5. @Component({
  6. props: {
  7. propMessage: String
  8. }
  9. })
  10. // class Name 是 App
  11. export default class App extends Vue {
  12. // initial data
  13. msg = 123
  14. // use prop values for initial data
  15. helloMsg = 'Hello, ' + this.propMessage
  16. // lifecycle hook
  17. mounted () {
  18. this.greet()
  19. }
  20. // computed 变成了 get
  21. get computedMsg () {
  22. return 'computed ' + this.msg
  23. }
  24. // method
  25. greet () {
  26. alert('greeting: ' + this.msg)
  27. }
  28. }

看完官方的demo感觉并不复杂,后续有通过基类继承

  1. import Component,{mixins} from 'vue-class-component'
  2. @Component
  3. export class MyComp extends minxins(MyMixin){}

看到这里,github used27.8k star4.2k

从短暂的考察成都来看,官方维护 vue-class-component 还不够强大,实际中使用 vue-property-decorator 更多,作为替代品。

vue-property-decorator

这个是民间维护的,官方推荐的插件。它完全依赖 vue-class-compnent

这个插件提供了几个装饰器和 mixin 函数

  • @Prop
  • @PropSync
  • @Model
  • @Watch
  • @Provide
  • @Inject
  • @ProvideReactive
  • @InjectReactive
  • @Emit
  • @Ref

后两者继承自 vue-class-compnent:

  • @Component
  • Mixins

先看代码 Prop

  1. // 这里一行代码引入 Vue Componet 和 Prop
  2. impornt { Vue, Component, Prop } from 'vue-property-decorator'
  3. @Component
  4. export defalut class _name_ extends Vue {
  5. @Prop(Number) readonly propA: string
  6. @Prop({ defalut: '' }) readonly propB!:string
  7. }

有一种情况是,通过 prop 获得数据,在页面里 computed 部分使用。

https://github.com/kaorun343/vue-property-decorator

vue2 vue3中的 provide/injdect

provide/inject 的使用不必多说。options/class-component/composition 三种用法。

  • 优点显而易见:祖先组件一旦注入,下游的子代孙代随时能获取到数据,也能修改数据,操作数据更直观。
  • 缺点,数据耦合,组件难复用。
  • 如何避免?双刃剑,组件库、插件、整体的一个业务组件可以使用,更能体现数据“高内聚”。

无论在 vue2 还是 vue3 里,对于 provide/indect ,官方的表述是一致的:绑定的值不是响应式的

vue2 里的表述

提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。 https://cn.vuejs.org/v2/api/#provide-inject

vue3 里的表述

默认情况下,provide/inject 绑定并不是响应式的。我们可以通过传递一个 ref property 或 reactive 对象给 provide 来改变这种行为。 https://v3.cn.vuejs.org/guide/component-provide-inject.html#%E5%A4%84%E7%90%86%E5%93%8D%E5%BA%94%E6%80%A7

vue3 中单独把 reactive 功能单独拆分成api,这让 reactive-provide 变得更为容易。官方案例独立成章节来讨论

vue2 里如何操作?如何理解“如果你传入一个可监听的对象”?

翻看一些帮助连接能够看到答案:

  1. // 祖先组件
  2. @Component({
  3. components: {
  4. HelloWorld,
  5. },
  6. })
  7. export default class App extends Vue {
  8. public data1 = { a: 1 };
  9. @Provide()
  10. public provideData = this.data1;
  11. }
  12. // 子组件
  13. @Component
  14. export default class HelloWorld extends Vue {
  15. @Prop() private msg!: string;
  16. @Inject()
  17. public provideData!: any;
  18. public changeInject(): void {
  19. this.provideData.a = 2;
  20. }
  21. }

做了demo,效果是ok的。

包括 vue-property-decorator 中的 ReactiveProvide 源码 https://github.com/kaorun343/vue-property-decorator/blob/master/src/helpers/provideInject.ts#L28

思路都是 data中设定数据,provide引用 data

Vue.utils.defineReactive

战未来:composition-api

忘了他吧,使用 @vue/composition-api