vue-property-decorator 使用

lxf2023-12-17 19:30:01

vue-property-decorator 使用指南

使用背景

vue2 对 TS 的支持相对较少,项目又使用了 TS,vue-property-decorator是在vue-class-component的基础上做了进一步的封装,在TypeScript官方文档 中,官方推荐了vue-class-component,提供了Vue,Component等,而vue-property-decorator是社区出品,深度依赖于vue-class-component,提供了更多操作符:@Component,@Prop,@Watch,@Emit等

npm vue-property-decorator 文档地址

如何使用vue-property-decorator

基本写法

    <script lang='ts'>
       import {Component, Vue} from vue-property-decorator;
       @Component
       export default class App extends Vue {

       };
   </script>

data中定义数据

data中的数据由原来的data()方法改成直接在对象中定义,data内的属性直接作为实例属性书写,默认都是public公有属性

    export default class App extends Vue {
      private msg1 : string = '123';
      private msg2 : number = 1;
    }

生命周期

    export default class App extends Vue {
      private created(){
        this.init();
      }
    }

 方法

    export default class App extends Vue {
      private init(){
        console.log('init');
      }
    }

@Component()

<script lang="ts">
    @Component({
      components: {
        HelloWorld, // 声明子组件的引用
      }
    })
    export default class App extends Vue {}
    </script>

@Prop()

  • PropOptions
    • type 类型不对会报错 Invalid prop: type check failed for prop “xxx”. Expected Function, got String with value “xxx”.
    • default 如果父组件没有传的话为该值, 注意只能用这一种形式来表示默认值, 不能@Prop() name = 1来表示默认值 1, 虽然看起来一样, 但是会在 console 里报错, 不允许修改 props 中的值
    • required 没有会报错 [Vue warn]: Missing required prop: “xxx”
    • validator 为一个函数, 参数为传入的值
@Prop()
propA: string

@Prop()
propB: number

@Prop({
  type: Number,
  validator: (value) => {
    return value > 100;
  },
  required: true
}) private propC!: string // !表示有值, 否则 ts 会告警未初始化


@Prop({ 
  default: 'this is title'required: true
}) propD!: string; // !表示有值, 否则 ts 会告警未初始化

@Prop({ 
  default: truerequired: true
}) propE: boolean | undefined;

@PropSync()

与 Prop 的区别是子组件可以对 props 进行更改, 并同步给父组件

子组件

<template>
  <div>
    <p>{{count}}</p>
    <button @click="innerCount += 1">increment</button>
  </div>
</template>

<script lang="ts">
    @Component
    export default class PropSyncComponent extends Vue {
      @PropSync('count') private innerCount!: number // 注意@PropSync 里的参数不能与定义的实例属性同名, 因为还是那个原理, props 是只读的.
    }
</script>

父组件:注意父组件里绑定 props 时需要加修饰符 .sync

<template>
    <PropSyncComponent :count.sync="count"/>
</template>
<script lang="ts">
@Component({
  components: PropSyncComponent
})
export default class PropSyncComponent extends Vue {
  @PropSync('count') private innerCount!: number // 注意@PropSync 里的参数不能与定义的实例属性同名, 因为还是那个原理, props 是只读的.
}

@Emit()

定义emit事件,参数字符串表示分发的事件名,如果没有,则使用方法名作为分发事件名,会自动转连字符写法:

  1. @Emit()不传参数,那么它触发的事件名就是它所修饰的函数名.
  2. @Emit(name: string),里面传递一个字符串,该字符串为要触发的事件名.

js写法

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)
    },
    promise() {
      const promise = new Promise(resolve => {
        setTimeout(() => {
          resolve(20)
        }, 0)
      })

      promise.then(value => {
        this.$emit('promise', value)
      })
    }
  }
}

ts写法

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()
  promise() {
    return new Promise(resolve => {
      setTimeout(() => {
        resolve(20)
      }, 0)
    })
  }
}

计算属性

对于Vue中的计算属性,我们只需要将该计算属性名定义为一个函数,,在函数前加上get关键字即可,原本Vue中的computed里的每个计算属性都变成了在前缀添加get的函数。

public get computedMsg(){
   return '这里是计算属性' + this.message;
}
public set computedMsg(message: string){
}

@Watch()

监听属性发生更改时被触发. 可接受配置参数 options

  1. immediate: boolean 是否在侦听开始之后立即调用该函数
  2. deep: boolean 是否深度监听.
import { Vue, Component, Watch } from vue-property-decorator;

export default class App extends Vue {
  @Watch('child')
  onChangeChildValue(newValue: string, oldValue: string){
    //todo
  }

  @Watch('parent', {immediate: true, deep: false})
  private onChangeParentValue(newValue: string, oldValue: string){
    //todo
  }
} 

@Ref()

@Ref 装饰器接收一个可选参数,用来指向元素或子组件的引用。没有提供参数,会使用装饰器后面的属性名充当参数。

<template>
  <div class="PropSync">
    <button @click="getRef()" ref="aButton">获取ref</button>
    <RefComponent name="names" ref="RefComponent"></RefComponent>
  </div>
</template>
 
<script lang="ts">
import { Vue, Component, Ref } from 'vue-property-decorator';
import RefComponent from '@/components/RefComponent.vue';
 
@Component({
  components: { RefComponent },
})
export default class RefPage extends Vue {
  @Ref('RefComponent') readonly RefC!: RefComponent;
  @Ref('aButton') readonly ref!: HTMLButtonElement;
  getRef() {
    console.log(this.RefC);
    console.log(this.ref);
  }
}
</script>

Mixins

Mixins.ts

import { Vue, Component } from 'vue-property-decorator'; @Component 
export default class TestMixins extends Vue { 
    valueFromMixins: string = "来自mixins的value" 
}

使用 Mixins 的文件

<template>
  <div class="home">
    vue+ts项目vue-property-decorator用法
    <hr>
    来自mixins中的变量--{{valueFromMixins}}
  </div>
</template>

<script lang="ts">
import { Component, Vue, Model, Emit, Prop } from 'vue-property-decorator';
import TestMixins from './mixins';

@Component({
  mixins: [TestMixins]
})
export default class Home extends Vue {}
</script>

本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!