仓库地址:

/* npm 仓库地址 */
// https://www.npmjs.com/package/vue-property-decorator /* github地址 */
// https://github.com/kaorun343/vue-property-decorator

@Component(options)

这一个是与另一个 vue 的库 vue-class-component一样的用法. 这个装饰器库源自 class 库, 只是再封装了一层, 使代码更为简洁明了. options 里面需要配置 decorator 库不支持的属性, 哪些是不支持的呢?

那就请看完全文, 凡是没写的都是不支持的. 比如components, filters, directives

components

表示该组件引入了哪些子组件

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

filters

filter 表示对数据的筛选, 跟 linux 中的管道符十分相似, 数据通过 filter 进行处理变成新的数据.

注意, 在这里配置时一定要使用 filters, 不要忘了 s, 否则不会报错但是也没作用.

<template>
<div>{{msg | filterA}}</div>
</template> <script lang="ts">
@Component({
filters: {
addWorld: (value: string) => `${value} world`,
},
})
export default class App extends Vue {
private msg = 'Hello' // filter 之后显示 hello world
}
</script>
 

directives

具体的介绍可以看 Vue 的官方介绍. 简单来说就是 DOM 节点在一些特定钩子触发时添加一些额外的功能

钩子函数有:

  • bind 指令绑定到元素时调用, 可以进行一次性设置
  • inserted 绑定元素被插入到父节点时调用
  • update VNode 更新时调用
  • componentUpdated VNode 及子 VNode 全部更新后调用
  • unbind 元素解绑时调用

如果bind 和 update 时调用一样可以进行简写, 不用指定某个钩子

钩子函数参数:

  • el 对应绑定的 DOM
  • binding
    • name 指令名 v-demo="1+1" 为 "demo"
    • value 绑定的值 v-demo="1+1" 为 2
    • oldValue 在 update componentUpdated 可用
    • expression 字符串形式的表达式 v-demo="1+1" 为 "1+1"
    • arg 指令的参数 v-demo:foo 为 'foo', 注意要在 modifier 前使用 arg, 不然会将 arg 作为 modifier 的一部分, 如v-demo.a:foo arg 为 undefined, modifier 为{'a:foo': true}
    • modifiers 包含修饰符的对象 比如 v-demo.a 这个值为 {a:true}
  • vnode vue 的虚拟节点, 可参考源码查看可用属性
  • oldVnode 上一个虚拟节点(update 和 componentUpdated 可用)

看个简单的实例:

<template>
<span v-demo:foo.a="1+1">test</span>
</template> <script lang="ts">
@Component({
directives: {
demo: {
bind(el, binding, vnode) {
console.log(`bindingName: ${binding.name}, value: ${binding.value}, args: ${binding.arg}, expression: ${binding.expression}`); // bindingName: demo, value: 2, args: foo, expression: 1+1
console.log('modifier:', binding.modifiers); // {a:true}, 无法转为 primitive, 所以单独打印
},
},
demoSimplify(el, binding, vnode) {
// do stuff
},
},
})
export default class App extends Vue {}
</script>
 

@Prop()

父子组件传递数据 props的修饰符, 参数可以传

  • Constructor 例如String, Number, Boolean
  • Constructor[], 构造函数的队列, 类型在这队列中即可
  • 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 为一个函数, 参数为传入的值, 比如(value) => value > 100

父组件:

<template>
<div id="app">
<PropComponent :count='count' />
</div>
</template>
<script lang="ts">
@Component
class Parent extends Vue {
private count =
}
</script>
 

子组件:

<template>
<div>{{count}}</div>
</template> <script lang="ts">
@Component
export default class PropsComponent extends Vue {
@Prop({
type: Number,
validator: (value) => {
return value > ;
},
required: true
}) private count!: string // !表示有值, 否则 ts 会告警未初始化
}
</script>
 

@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 是只读的.
}
</script>
 

也可结合 input 元素的 v-model 绑定数据, 实时更新. 由读者自行实现.

@Watch

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

  • immediate?: boolean 是否在侦听开始之后立即调用该函数
  • deep?: boolean 是否深度监听.
<template>
<div>
<button @click="innerName.name.firstName = 'lorry'">change deeper</button>
<button @click="innerName.name = 'lorry'">change deep</button>
</div>
</template>
<script lang="ts">
@Component
export default class PropSyncComponent extends Vue {
private person = { name: { firstName: 'jiang' } } @Watch('person', {
deep: true,
})
private firstNameChange(person: number, oldPerson:number) {
console.log(`count change from${oldName.name.first}to: ${oldName.name.}`);
}
}
</script>
 

@Emit

  • 接受一个参数 event?: string, 如果没有的话会自动将 camelCase 转为 dash-case 作为事件名.
  • 会将函数的返回值作为回调函数的第二个参数, 如果是 Promise 对象,则回调函数会等 Promise resolve 掉之后触发.
  • 如果$emit 还有别的参数, 比如点击事件的 event , 会在返回值之后, 也就是第三个参数.

子组件:

<template>
<div>
<button @click="emitChange">Emit!!</button>
</div>
</template> <script lang="ts">
@Component
export default class EmitComponent extends Vue {
private count = ; @Emit('button-click')
private emitChange() {
this.count += ;
return this.count;
}
}
</script>


父组件, 父组件的对应元素上绑定事件即可:

<template>
<EmitComponent v-on:button-click='listenChange'/>
</template> <script lang="ts">
@Component({
components: {
EmitComponent,
},
})
export default class App extends Vue {
private listenChange(value: number, event: any) {
console.log(value, e);
}
}
</script>
 

@Ref

跟 react 中的一样, ref 是用于引用实际的 DOM 元素或者子组件.应尽可能避免直接使用, 但如果不得不用 ref 比 document 拿要方便很多, 参数传一个字符串refKey?:string, 注意这里如果省略传输参数, 那么会自动将属性名作为参数, 注意与@Emit的区别, @Emit在不传参数的情况下会转为 dash-case, 而 @Ref不会转, 为原属性名

<template>
<div>
<span>Name:</span>
<input type="text" v-model="value" ref='name' />
</div>
</template> <script lang="ts">
@Component
export default class RefComponent extends Vue {
@Ref('name') readonly name!: string;
private value = 'lorry'
private mounted() {
console.log(this.inputName); // <input type="text">
// do stuff to ref
}
}
</script>
 

@Provide/@inject && @ProvideReactive/@InjectReactive

其本质是转换为 injectprovide, 这是 vue 中元素向更深层的子组件传递数据的方式.两者需要一起使用.与 react 的 context 十分的像.

任意代的子组件:

<template>
<span>Inject deeper: {{bar}}</span>
</template> <script lang="ts">
@Component
export default class InjectComponent extends Vue {
@Inject() private bar!: string private mounted() {
console.log(this.bar);
}
}
</script>
 

任意祖先元素:

<script>
export default class App extends Vue {
@Provide() private bar = 'deeper lorry'
}
</script>
 

方便很多, 如果为了避免命名冲突, 可以使用 ES6 的 Symbol 特性作为 key, 以祖先元素举例:

需要注意的是避免相互引用的问题, symbol 的引用最好放到组件外单独有个文件存起来.

export const s = Symbol()

父组件:

<script>
export default class App extends Vue {
@Provide(s) private bar = 'deeper lorry'
}
</script>

子组件:

<script>
@Component
export default class App extends Vue {
@Inject(s) private baz = 'deeper lorry'
}
</script>
 

@ProvideReactive/@InjectReactive 顾名思义就是响应式的注入, 会同步更新到子组件中.比如下例可以实现在 input 中的输入实时注入到子组件中 父组件

<template>
<div id="app">
<input type="text" v-model="bar">
<InjectComponent />
</div>
</template>
<script>
@Component({
InjectComponent
})
export default class App extends Vue {
@ProvideReactive(s) private bar = 'deeper lorry'
}
</script>
 

子组件:

<script>
@Component
export default class InjectComponent extends Vue {
@InjectReactive(s) private baz!: string
}
</script>

欢迎关注公众号,进一步技术交流:

vue-property-decorator知识梳理的更多相关文章

  1. Vue.js 2.x API 知识梳理(一) 全局配置

    Vue.js 2.x API 知识梳理(一) 全局配置 Vue.config是一个对象,包含Vue的全局配置.可以在启动应用之前修改指定属性. 这里不是指的@vue/cli的vue.config.js ...

  2. Vue基础开发入门之简单语法知识梳理(思维导图详解)

    基于个人写的以下关于Vue框架基础学习的三篇随笔,在此基础上,做一个阶段性的知识总结,以此来检验自己对Vue这一段时间学习的成果,内容不多,但很值得一看.(思维导图详解)

  3. Jmeter 接口测试知识梳理——持续集成篇

    Jmeter 使用也有很长时间了,但是一直没有做一下知识梳理,近期会对公司同事做一下这方面的培训,借此机会,把使用过程中应用到的知识,或是遇到的问题,整理出来,方便大家学习! Jmeter + Ant ...

  4. spring远程服务知识梳理

    序:本文主要是总结和归纳spring的远程服务相关知识,可作为入门学习笔记.写博客目的也是为了进行知识梳理,便于以后查看.本文主要参考资料 spring 实战第三版 本文主要讨论内容如下: 远程调度概 ...

  5. iOS多线程知识梳理

    iOS多线程知识梳理 线程进程基础概念 进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 线程 1个进程要想执行任务,必须得有线程(每1个 ...

  6. iOS 多线程知识梳理

    #iOS多线程知识梳理 ##线程进程基础概念 ###进程 进程是指在系统中正在运行的一个应用程序每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 ###线程 1个进程要想执行任务,必须 ...

  7. [SQL] SQL 基础知识梳理(一)- 数据库与 SQL

    SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...

  8. [SQL] SQL 基础知识梳理(二) - 查询基础

    SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...

  9. [SQL] SQL 基础知识梳理(三) - 聚合和排序

    SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...

  10. [SQL] SQL 基础知识梳理(四) - 数据更新

    SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 序 这是<SQL 基础知识梳理( ...

随机推荐

  1. C#面向对象19 值传递和引用传递

    值类型:int double char decimal bool enum struct引用类型:string 数组 自定义类 集合 object 接口 **值传递和引用传递1.值类型在复制的时候,传 ...

  2. Visual Studio 2012网站如何只生成一个DLL文件

    简介: 在Visual Studio 2005,2008,2010版本中,都有Web Deployment工具将网站进行发布,所有代码文件和库文件发布,生成为一个动态链接库文件,而在Visual St ...

  3. 题解 CF670C 【Cinema】

    题目链接: https://www.luogu.org/problemnew/show/CF670C 思路: step-1: 语言的数据范围是10^9,所以我们采取用map离散化,这样就能方便且不ML ...

  4. 用帝国cms 反馈内容的时候自动发送邮箱开发流程

    开发流程是这样的. 第一步:先找好一个发送的邮箱.以及一个接受的邮箱.这里是 测试的,我都用的qq邮箱,帝国cms后台配置如下: 注意:这里的SMTP服务器是腾讯的,如果你用163的或者其他的请自行百 ...

  5. 实现代码重启android app.

    var Form1: TForm1; implementation uses System.DateUtils, Androidapi.JNI.GraphicsContentViewText, FMX ...

  6. Linux工具之watch

    watch   watch   监测一个命令的运行结果 -n       指定间隔的时间 -d       watch会高亮显示变化的区域. -t        会关闭watch命令在顶部的时间间隔, ...

  7. Android异常与性能优化相关面试问题-内存管理面试问题详解

    内存管理机制概述: 分配机制:操作系统会为每一个进程分配一个合理的内存大小,从而保证每一个进程能够正常的运行,不至于内存不够使用,或者某个进程占用过多的内存. 回收机制:在系统内存不足的时候,系统有一 ...

  8. BZOJ 1016 生成树计数

    现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的).由于不同的最小生成树 ...

  9. 第十五届四川省省赛 SCU - 4439 Vertex Cover

    给你一个一般图 保证每条边的一端下标不大于30 问最小覆盖集的大小为多少 爆搜:枚举前30个点是否在覆盖集内 剪枝1:如果不在的话 那么他所连的下标大于30的点都必须选 剪纸2:最优解剪枝 #incl ...

  10. Python的函数式编程: map, reduce, sorted, filter, lambda

    Python的函数式编程 摘录: Python对函数式编程提供部分支持.由于Python允许使用变量,因此,Python不是纯函数式编程语言. 函数是Python内建支持的一种封装,我们通过把大段代码 ...