这篇文章主要介绍了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
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
@Mutation
namespace
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调用即可
如下,首先在全局定义个conut,常规写法
export default new Vuex.Store({
state : {
count : -1,
},
mutations: {
addcount(state){
state.count++
}
},
actions: {
change({commit}){
commit("addcount")
}
},
})
在组件中使用: 这里以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
直接上代码
创建一个公共的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
}
在index.ts
中引入模块
import common from './common'
export default new Vuex.Store({
//与 state平级
modules: {
// here here!
common
}
})
在组件中使用
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...
}
...
}
整体代码
组件代码
模块的数据:{{stateAge}}
全局的数据:{{globalCount}}
模块+++
全局++
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 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。