vue-property-decorator分享

vue-property-decorator分享

关于vue-property-decorator的疑问

vue-property-decorator是什么

  • 'vue-property-decorator' 是vue社区推出的用于拓展 'vue-class-component' 的 装饰器集合库

vue-class-component是什么

  • 'vue-class-component' 是vue官方推出的一个库,可让您使用类样式的语法来制作Vue组件,使vue组件可以使用继承(Extend)、混入(Mixins)等高级特性

装饰器是什么

  • 装饰器(Decorator)是一种与类(class)相关的语法,用来注释或修改类和类方法,许多面向对象的语言都有这项功能。
  • 装饰器是一种函数,写成@ + 函数名。它可以放在类和类方法的定义前面。

vue-property-decorator的用法

vue-property-decorator有哪些内容

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

@Component

  • 继承自vue-class-component
  • 其中可以声明props,watch,components,template
  • 采用vue-property-decorator后尽量将components,template以外的内容用装饰器声明
  • 例:
@Component({
  template: '<button @click="onClick">Click!</button>',
  components: {
    helloworld,
  }
})

@Prop

  • 组件的props值之一
  • 例:
@Prop([String, Boolean]) readonly propA: string | boolean | undefined
@Prop() title?: string;

相当于
props: {
  propC: {
    type: [String, Boolean],
  },
  title: {

  }
}

@PropSync

  • 组件的props值之一,并给此prop添加一个<kbd>.sync</kbd>修饰符
  • 例:
@PropSync('name', { type: String }) syncedName!: string

相当于
props: {
  name: {
    type: String
  }
},
computed: {
  syncedName: {
    get() {
      return this.name
    },
    set(value) {
      this.$emit('update:name', value)
    }
  }
}

@Model

  • 组件的v-model, 用于给自定义组件添加v-model
  • 例:
@Model('change', { type: Boolean }) readonly checked!: boolean

相当于
model: {
  prop: 'checked',
  event: 'change'
},
props: {
  checked: {
    type: Boolean
  }
}

@Watch

  • vue的侦听属性
  • 例:
@Watch('child', {immediate: true, deep: true})
onChildChanged(val: string, oldVal: string) {}

相当于
watch: {
  child: [{
    handler: 'onChildChanged',
    immediate: true,
    deep: true
  }]
},
methods: {
  onChildChanged(val, oldVal) {}
}

@Emit

  • 在函数的最后使用emit将返回值传给父组件, 第一个参数是emit事件名
  • 例:
count = 0
@Emit()
addToCount(n: number) {
  this.count += n
},
@Emit('reset')
resetCount() {
  this.count = 0
}

相当于
data() {
  return {
    count: 0
  }
},
methods: {
  addToCount(n) {
    this.count += n
    this.$emit('add-to-count', n)
  },
  resetCount() {
    this.count = 0
    this.$emit('reset')
  },
}

@Ref

  • refs值之一,第一个参数是ref值,此装饰器会将ref映射到计算属性中
  • 例:
@Ref() readonly anotherComponent!: AnotherComponent
@Ref('aButton') readonly button!: HTMLButtonElement

相当于
computed() {
  anotherComponent: {
    cache: false,
    get() {
      return this.$refs.anotherComponent as AnotherComponent
    }
  },
  button: {
    cache: false,
    get() {
      return this.$refs.aButton as HTMLButtonElement
    }
  }
}

@Provide

  • 等同于provide,用于祖孙组件的传输值,需要与inject配合使用
  • 例:
@Provide() foo = 'foo'
@Provide('bar') baz = 'bar'

相当于
provide() { // 当前组件传入子孙组件的值
  return {
    foo: this.foo,
    bar: this.baz
  }
}

@Inject

  • 等同于inject,用于祖孙组件的接收值,需要与provide配合使用
  • 例:
@Inject('bar') readonly bar!: string
@Inject({ from: 'optional', default: 'default' }) readonly optional!: string


相当于
inject: { // 接收父、祖组件的 provide
  bar: 'bar',
  optional: { from: 'optional', default: 'default' },
},

@ProvideReactive 与 @InjectReactive

  • 等同于provide/inject,用于祖孙组件的传输接收
  • 与@Provide/inject不同的是,@ProvideReactive/@InjectReactive是响应式的, 使用后者的情况下,祖父组件进行修改时孙子组件会相应的变更
  • 例:
@Component
class ParentComponent extends Vue {
  @ProvideReactive() one = 'value'
}

@Component
class ChildComponent extends Vue {
  @InjectReactive() one!: string
}

相当于
inject: { // 接收父、祖组件的 provide
  one: 'foo',
},
data() {
  return {
    one: 'foo',
  }
},
provide() { // 当前组件传入子孙组件的值
  return {
    one: this.one,
  }
}


vue-property-decorator的其他用法

Component.registerHooks

  • 此方法可用于vue生态下的其他钩子,例如vue-router
  • 这些钩子不会被视为vue methods下的方法
  • 用法:
Component.registerHooks([
  'beforeRouteEnter',
  'beforeRouteLeave',
  'beforeRouteUpdate'
])

@Component
export default class HelloWorld extends Vue {
  beforeRouteEnter(to, from, next) {...}
}

createDecorator

  • 用此方法可以创建自定义的装饰器, 自定义装饰器的用法与es6中规定的装饰器一致。
  • 用法:
import Vue from 'vue'
import Component,{ createDecorator } from 'vue-class-component'

const Log = createDecorator((options, key) => {
  const originalMethod = options.methods[key]
  options.methods[key] = function wrapperMethod(...args) {
    console.log(`Invoked: ${key}(`, ...args, ')')
    originalMethod.apply(this, args)
  }
})

@Component
class MyComp extends Vue {
  @Log
  hello(value) {
    // ...
  }
}

与vue-property-decorator相关的一些内容

vuex-class

import { Component, Inject, Provide, Vue } from 'vue-property-decorator'
import {
  State,
  Getter,
  Action,
  Mutation,
  namespace
} from 'vuex-class'

const someModule = namespace('path/to/module')

@Component
export class MyComp extends Vue {
  @State('foo') stateFoo
  @State(state => state.bar) stateBar
  @Getter('foo') getterFoo
  @Action('foo') actionFoo
  @Mutation('foo') mutationFoo
  @someModule.Getter('foo') moduleGetterFoo

  // If the argument is omitted, use the property name 如果省略了参数,则使用属性名
  // for each state/getter/action/mutation type
  @State foo
  @Getter bar
  @Action baz
  @Mutation qux

  created () {
    this.stateFoo // -> store.state.foo
    this.stateBar // -> store.state.bar
    this.getterFoo // -> store.getters.foo
    this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true })
    this.mutationFoo({ value: true }) // -> store.commit('foo', { value: true })
    this.moduleGetterFoo // -> store.getters['path/to/module/foo']
  }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容