Vue装饰器中的vue-property-decorator 和 vux-class使用详解,vuex-class的使用方法 ts+vuex

这篇文章主要介绍了Vue装饰器中的vue-property-decorator 和 vux-class使用详解,通过示例代码给大家介绍的非常详细,对vue-property-decorator 和 vux-class的使用感兴趣的朋友一起看看吧

目录
  • 1. 安装
  • 2. vue-property-decorator
  • 3. vuex-class

目前在用vue开发的项目中,都会配合使用TypeScript进行一些约束。为了提高开发效率,往往会使用装饰器来简化我们的代码。

本文主要介绍装饰器vue-property-decorator 和 vux-class的使用。

1. 安装

1

2

npm i -S vue-property-decorator

npm i -S vuex-class

2. vue-property-decorator

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

@Component

1

2

3

4

5

6

7

8

9

10

11

import { Vue, Component } from 'vue-property-decorator'

@Component({

 components:{

      componentA,

      componentB,

  }

})

export default class MyComponent extends Vue{

    

}

相当于:

1

2

3

4

5

6

7

export default{

  name: 'MyComponent',

  components:{

    componentA,

    componentB,

  }

}

@Prop

1

@Prop(options: (PropOptions | Constructor[] | Constructor) = {}) decorator

表示:@Prop装饰器接收一个参数,这个参数可以有三种写法:

  • PropOptions:可以使用以下选项:type,required,default,validator
  • Constructor:例如String,Number,Boolean等,指定 prop 的类型
  • Constructor[]:指定 prop 的可选类型

例如:

1

2

3

4

5

6

7

8

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

  

@Component

export default class MyComponent extends Vue {

  @Prop(Number) readonly propA: number | undefined

  @Prop({ default: 'default value' }) readonly propB!: string

  @Prop([String, Boolean]) readonly propC: string | boolean | undefined

}

相当于:

1

2

3

4

5

6

7

8

9

10

11

12

13

export default {

  name: 'MyComponent',

  props: {

    propA: {

      type: Number,

    },

    propB: {

      default: 'default value',

    },

    propC: {

      type: [String, Boolean],

    },

  },

@PropSync

1

@PropSync(propName: string, options: (PropOptions | Constructor[] | Constructor) = {}) decorator

  • propName 表示父组件传递过来的属性名
  • 父组件要结合.sync来使用

例如:

1

2

3

4

5

6

// child.vue

import { Vue, Component, PropSync } from 'vue-property-decorator'

  

@Component

export default class MyComponent extends Vue {

  @PropSync('name', { type: String }) syncedName!: string

1

2

3

4

5

6

相当于:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

export default {

  name: 'MyComponent',

  props: {

    name: {

      type: String,

    },

  },

  computed: {

    syncedName: {

      get() {

        return this.name

      },

      set(value) {

        this.$emit('update:name', value)

      },

    },

  },

}

@PropSync的工作原理与@Prop类似,除了接受propName作为装饰器的参数之外,它还在幕后创建了一个计算的getter和setter。通过这种方式,您可以像使用常规数据属性一样使用该属性,同时像在父组件中添加.sync修饰符一样简单。

@Model

@Model装饰器允许我们在一个组件上自定义v-model。

1

@Model(event?: string, options: (PropOptions | Constructor[] | Constructor) = {}) decorator

例如:

1

2

3

4

5

6

import { Vue, Component, Model } from 'vue-property-decorator'

  

@Component

export default class MyComponent extends Vue {

  @Model('change', { type: Boolean }) readonly checked!: boolean

}

相当于:

1

2

3

4

5

6

7

8

9

10

11

export default {

  model: {

    prop: 'checked',

    event: 'change',

  },

  props: {

    checked: {

      type: Boolean,

    },

  },

}

@ModelSync

1

@ModelSync(propName: string, event?: string, options: (PropOptions | Constructor[] | Constructor) = {}) decorator

例如:

1

2

3

4

5

6

import { Vue, Component, ModelSync } from 'vue-property-decorator'

  

@Component

export default class MyComponent extends Vue {

  @ModelSync('checked', 'change', { type: Boolean }) readonly checkedValue!: boolean

}

相当于:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

export default {

  model: {

    prop: 'checked',

    event: 'change',

  },

  props: {

    checked: {

      type: Boolean,

    },

  },

  computed: {

    checkedValue: {

      get() {

        return this.checked

      },

      set(value) {

        this.$emit('change', value)

      },

    },

  },

}

@Watch

1

@Watch(path: string, options: WatchOptions = {}) decorator

例如:

1

2

3

4

5

6

7

8

9

10

11

12

13

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

  

@Component

export default class MyComponent extends Vue {

  @Watch('child')

  onChildChanged(val: string, oldVal: string) {}

  

  @Watch('person', { immediate: true, deep: true })

  onPersonChanged1(val: Person, oldVal: Person) {}

  

  @Watch('person')

  onPersonChanged2(val: Person, oldVal: Person) {}

}

相当于:

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

export default {

  watch: {

    child: [

      {

        handler: 'onChildChanged',

        immediate: false,

        deep: false,

      },

    ],

    person: [

      {

        handler: 'onPersonChanged1',

        immediate: true,

        deep: true,

      },

      {

        handler: 'onPersonChanged2',

        immediate: false,

        deep: false,

      },

    ],

  },

  methods: {

    onChildChanged(val, oldVal) {},

    onPersonChanged1(val, oldVal) {},

    onPersonChanged2(val, oldVal) {},

  },

}

@Provide | @Inject

1

2

@Provide(key?: string | symbol) decorator

@Inject(options?: { from?: InjectKey, default?: any } | InjectKey) decorator

例如:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

import { Component, Inject, Provide, Vue } from 'vue-property-decorator'

  

const symbol = Symbol('baz')

  

@Component

export class MyComponent extends Vue {

  @Inject() readonly foo!: string

  @Inject('bar') readonly bar!: string

  @Inject({ from: 'optional', default: 'default' }) readonly optional!: string

  @Inject(symbol) readonly baz!: string

  

  @Provide() foo = 'foo'

  @Provide('bar') baz = 'bar'

}

相当于:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

const symbol = Symbol('baz')

  

export const MyComponent = Vue.extend({

  inject: {

    foo: 'foo',

    bar: 'bar',

    optional: { from: 'optional', default: 'default' },

    baz: symbol,

  },

  data() {

    return {

      foo: 'foo',

      baz: 'bar',

    }

  },

  provide() {

    return {

      foo: this.foo,

      bar: this.baz,

    }

  },

})

@ProvideReactive | @InjectReactive

它们是@provider@Inject的响应式版本。如果父组件修改了提供的值,那么子组件可以捕捉到这种修改。

1

2

@ProvideReactive(key?: string | symbol)  decorato

@InjectReactive(options?: { from?: InjectKey, default?: any } | InjectKey) decorator

例如:

1

2

3

4

5

6

7

8

9

10

11

12

const key = Symbol()

@Component

class ParentComponent extends Vue {

  @ProvideReactive() one = 'value'

  @ProvideReactive(key) two = 'value'

}

  

@Component

class ChildComponent extends Vue {

  @InjectReactive() one!: string

  @InjectReactive(key) two!: string

}

@Emit

1

@Emit(event?: string) decorator

例如:

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

import { Vue, Component, Emit } from 'vue-property-decorator'

  

@Component

export default class MyComponent extends Vue {

  count = 0

  

  @Emit()

  addToCount(n: number) {

    this.count += n

  }

  

  @Emit('reset')

  resetCount() {

    this.count = 0

  }

  

  @Emit()

  returnValue() {

    return 10

  }

  

  @Emit()

  onInputChange(e) {

    return e.target.value

  }

  

  @Emit()

  promise() {

    return new Promise((resolve) => {

      setTimeout(() => {

        resolve(20)

      }, 0)

    })

  }

}

相当于:

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

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)

    },

    onInputChange(e) {

      this.$emit('on-input-change', e.target.value, e)

    },

    promise() {

      const promise = new Promise((resolve) => {

        setTimeout(() => {

          resolve(20)

        }, 0)

      })

  

      promise.then((value) => {

        this.$emit('promise', value)

      })

    },

  },

}

@Ref

1

Ref(refKey?: string) decorator

例如:

1

2

3

4

5

6

7

8

9

import { Vue, Component, Ref } from 'vue-property-decorator'

  

import AnotherComponent from '@/path/to/another-component.vue'

  

@Component

export default class MyComponent extends Vue {

  @Ref() readonly anotherComponent!: AnotherComponent

  @Ref('aButton') readonly button!: HTMLButtonElement

}

相当于:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

export default {

  computed() {

    anotherComponent: {

      cache: false,

      get() {

        return this.$refs.anotherComponent as AnotherComponent

      }

    },

    button: {

      cache: false,

      get() {

        return this.$refs.aButton as HTMLButtonElement

      }

    }

  }

}

@VModel

1

@VModel(propsArgs?: PropOptions) decorator

例如:

1

2

3

4

5

6

import { Vue, Component, VModel } from 'vue-property-decorator'

  

@Component

export default class MyComponent extends Vue {

  @VModel({ type: String }) name!: string

}

相当于:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

export default {

  props: {

    value: {

      type: String,

    },

  },

  computed: {

    name: {

      get() {

        return this.value

      },

      set(value) {

        this.$emit('input', value)

      },

    },

  },

}

3. vuex-class

@State@Getter@Action@Mutationnamespace

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

import Vue from 'vue'

import Component from 'vue-class-component'

import {

  State,

  Getter,

  Action,

  Mutation,

  namespace

} from 'vuex-class'

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

@Component

export class MyComponent extends Vue {

  @State('foo') stateFoo

  @State(state => state.bar) stateBar

  @Getter('foo') getterFoo

  @Action('foo') actionFoo

  @Mutation('foo') mutationFoo

  @someModule.Getter('foo') moduleGetterFoo

  // 如果省略参数, 直接使用每一个 state/getter/action/mutation 类型的属性名称

  @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']

  }

}

到此这篇关于Vue装饰器中的vue-property-decorator 和 vux-class使用详解的文章就介绍到这了,更多相关vue-property-decorator 和 vux-class内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

=========================

vuex-class的使用方法 ts+vuex

简介:vuex-class是vuex和vue-class-component的绑定助手,包装了vuex, 简化了代码。

本人是个菜鸟,由于项目中是这种用法。研究了半天才使用明白,发现确实很好用,结合ts很便于代码的维护余拓展。下面直接说下怎么快速上手使用

使用

安装:
npm install vuex-class --save
或者
yarn add vuex-clss

在全局中使用

当调用全局的state、mutations、actions、getters时,可以直接通过@State、@Mutation、@Action、@Getter获取,在调用时,直接使用this调用即可

  1. 如下,首先在全局定义个conut,常规写法

export default new Vuex.Store({
  state : {
    count : -1,
  },
 
  mutations: {
   addcount(state){
      state.count++
   }
  },

  actions: {
    change({commit}){
      commit("addcount")
    }
  },
})
  1. 在组件中使用: 这里以action为演示

//首先引入

import {Action,State} from'vuex-class'

//直接使用装饰器就可以获取到了
@State('count') globalCount
@Action('change') changecount

//然后就是直接调用
create(){
    log(`vuex中的count数据为${this.globalCount}`)
}
add(){
    //调用一次add()就触发一次
    this.changecount()
}

这里已经基本掌握了如何使用装饰器获取vuex中数据,可改变状态

分模块使用

当分模块调用state、mutations、actions、getters时,需要引入namespace,并且调用的时候需要加上@nameSpaceName

直接上代码

  1. 创建一个公共的common.ts文件

import {MutationTree} from 'vuex'
//1. 定义数据类型
interface mytype {
    name : string,
    age : number
}
//2. 定义state信息
const state: mytype = {
    name:'',
    age:24
}

/*
*3. 按照需求引入 mutations ,action ,getters .....
*   这里就举个例子mutations
*/
const mutations:MutationTree = {
    ADD_AGE(state){
        state.age++
    }
}
//4.导出 
export default {
    //表示允许使用namespaced方法,必须打开
    namespaced: true,
    state,
    mutations
}
  1. index.ts中引入模块

import common from './common'
export default new Vuex.Store({
//与 state平级
  modules: {
    // here here! 
    common
  }
})
  1. 在组件中使用

import {Action, namespace,State} from'vuex-class'

//1. 获取com模块
const mymodule = namespace('common')

@Component({
  components: {
    HelloWorld,
  },
})
export default class HomeView extends Vue {

//2.通过mymodule获取 common模块里面的state数据和mutation
  @mymodule.State('age') stateAge
  @mymodule.Mutation('ADD_AGE') addage
  
//3. 完事了,可以用了
created(){
    do someting...
}
...

}

整体代码

组件代码




common.ts文件

import { MutationTree } from "vuex"

interface mytype {
    name : string,
    age : number
}

const state: mytype = {
    name:'',
    age:24
}
const mutations:MutationTree = {
    ADD_AGE(state){
        state.age++
    }
}
export default {
    namespaced: true,
    state,
    mutations
}

index.ts文件

import Vue from 'vue'
import Vuex from 'vuex'
import common from './common'

Vue.use(Vuex)

interface mystate{
  count:number,
}

export default new Vuex.Store({
  state : {
    count : -1,
  },
  getters: {
  },
  mutations: {
   addcount(state){
      state.count++
   }
  },
  actions: {
    change({commit}){
      commit("addcount")
    }
  },
  modules: {
    common
  }
})



作者:Link9527
链接:https://www.jianshu.com/p/2022bcdeb4cd
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(typescript,vue.js,前端,typescript)