Vue框架TypeScript装饰器使用指南小结


Posted in Javascript onFebruary 18, 2019

前言

装饰器是一种特殊类型的声明,它能够被附加到 类声明,方法, 访问符,属性或参数 上。 装饰器使用 @expression这种形式, expression求值 后必须为一个函数,它会在 运行时被调用 ,被装饰的声明信息做为参数传入。

本篇先从项目的宏观角度来总结一下Decorator如何组织。

目录

  • 主要的Decorator依赖
    • vue-class-component
    • vuex-class
    • vue-property-decorator
    • core-decorators
  • 自定义Decorator示例
  • 哪些功能适合用Decorator实现
  • Decorator实现小Tips
  • See also

主要的Decorator依赖

vue-cli3 默认支持Decorator, 年初重写了一个design库主要依赖官方和社区提供的Decorator来实现的组件。 Decorator可以非侵入的装饰类、方法、属性,解耦业务逻辑和辅助功能逻辑。以下是主要的三方Decorator组件:

vue-class-component

  • @Component 如果您在声明组件时更喜欢基于类的 API,则可以使用官方维护的 vue-class-component 装饰器
  • 实时计算computed属性, get computedMsg () {return 'computed ' + this.msg}
  • 生命周期钩子 mounted () {this.greet()}

vuex-class

让Vuex和Vue之间的绑定更清晰和可拓展

  • @State
  • @Getter
  • @Action
  • @Mutation

vue-property-decorator

这个组件完全依赖于vue-class-component.它具备以下几个属性:

  • @Component (完全继承于vue-class-component)
  • @Prop:父子组件之间值的传递
  • @Emit:子组件向父组件传递
  • @Model:双向绑定
  • @Watch:观察的表达式变动
  • @Provice:在组件嵌套层级过深时。父组件不便于向子组件传递数据。就把数据通过Provide传递下去。
  • @Inject:然后子组件通过Inject来获取
  • Mixins (在vue-class-component中定义);

core-decorators

  • @readonly
  • @autobind : TSX 回调函数中的 this,类的方法默认是不会绑定 this 的,可以使用autobind装饰器
  • @override

总结一下主要就分成这三类:

  • 修饰类的:@Component、@autobind;
  • 修饰方法的:@Emit、@Watch、@readonly、@override;
  • 修饰属性的:@Prop、@readonly;

以上引用方法等详系内容可查看官方文档。下面自定义部分来实现一个记录日志功能的装饰器。

自定义Decorator示例

@Logger,Logger日志装饰器通常是修饰方法,Decorater则是在 运行时就被触发了 ,日志记录是在 方法被调用时触发 ,示例中通过自动发布事件实现调用时触发。为增加日志记录的灵活性,需要通过暴露钩子函数的方式来改变日志记录的内容。
期望的日志格式

{
  "logId":"", // 事件Id
  "input":"", // 方法输入的内容
  "output":"", // 方法输出的内容
  "custom":"" // 自定义的日志内容
}

实现

export function Logger(logId?: string, hander?: Function) {
  const loggerInfo =Object.seal({logId:logId, input:'',output:'', custom: ''});
  const channelName = '__logger';
  const msgChannel = postal.channel(channelName);
  msgChannel.subscribe(logId, logData => {
    // 根据业务逻辑来处理日志
    console.log(logData);
  });

  return function (target: any,
    key: string,
    descriptor: TypedPropertyDescriptor<any>): TypedPropertyDescriptor<any> {
      const oldValue = descriptor.value
      descriptor.value = function () {
        const args: Array<any> = [];
        for (let index in arguments) {
        args.push(arguments[index]);
        }
        loggerInfo.input = `${key}(${args.join(',')})`;
        // 执行原方法
        const value = oldValue.apply(this, arguments);
        loggerInfo.output = value;
        hander && (loggerInfo.custom = hander(loggerInfo.input, loggerInfo.output) || '');
        // 被调用时,会自动发出一个事件
        msgChannel.publish(logId, loggerInfo);
      }
      return descriptor
  }
}

使用

@Logger('event_get_detial1')
getDetial(id?: string, category?: string) {
  return "详细内容";
}
// 或者
@Logger('event_get_detial2', (input, output) => {
    return '我是自定义内容';
})
getDetial2(id?: string, category?: string) {
  return "详细内容";
}
...
<button @click="getDetial2('1000', 'a')">获取详情</button>

效果: {logId: "event_get_detial2", input: "getDetial(1000,a)", output: "详细内容", custom: "我是自定义内容"} , 每次点击按钮都会触发一次。

TODO: 这里还需要对输入参数和输出参数中的引用数据类型做处理。

同时还需要掌握: 装饰器工厂、装饰器组合、装饰器求值、参数装饰器、元数据

哪些功能适合用Decorator实现

官网和社区提供的这些Decorator, 可以作为自己框架的底层设计。

日志功能全局都得用,调用方法基本一致,是最适合使用装饰器来实现,并且每个项目的日志记录各有差异,最适合自定义这部分。

Decorator实现小Tips

  • 考虑下各类Decorator叠加和共存的问题,可以参考官网关于装饰器组合描述
  • Decorator 的目标是在原有功能基础上,添加功能,切忌覆盖原有功能
  • 类装饰器不能用在声明文件中( .d.ts),也不能用在任何外部上下文中(比如declare的类)
  • 装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。类是不会提升的,所以就没有这方面的问题。
  • 注意迁移速度、避免一口吃成胖子的做法
  • 不要另起炉灶对主流库创建Decorator库,主流库维护成本很高还是得有官方来维护,为保证质量不使用个人编写的Decorator库。自己在创建Decorator库时也要有这个意识,仅做一些有必要自定义的。
  • Decorator 不是管道模式,decorator之间不存在交互,所以必须注意保持decorator独立性、透明性
  • Decorator 更适用于非业务功能需求
  • 确定 decorator 的用途后,切记执行判断参数类型
  • decorator 针对每个装饰目标,仅执行一次

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
解析javascript 浏览器关闭事件
Jul 08 Javascript
js动态调用css属性的小规律及实例说明
Dec 28 Javascript
javascript针对cookie的基本操作实例详解
Nov 30 Javascript
深入解析JavaScript框架Backbone.js中的事件机制
Feb 14 Javascript
Jquery遍历select option和添加移除option的实现方法
Aug 26 Javascript
jQuery插件FusionCharts实现的3D帕累托图效果示例【附demo源码】
Mar 25 jQuery
微信小程序实现动态设置placeholder提示文字及按钮选中/取消状态的方法
Dec 14 Javascript
jQuery实现下拉菜单动态添加数据点击滑出收起其他功能
Jun 14 jQuery
详解在HTTPS 项目中使用百度地图 API
Apr 26 Javascript
详解微信小程序支付流程与梳理
Jul 16 Javascript
使用VUE实现在table中文字信息超过5个隐藏鼠标移到时弹窗显示全部
Sep 16 Javascript
vue中动态select的使用方法示例
Oct 28 Javascript
深入理解vue-class-component源码阅读
Feb 18 #Javascript
详解TypeScript+Vue 插件 vue-class-component的使用总结
Feb 18 #Javascript
jQuery实现的卷帘门滑入滑出效果【案例】
Feb 18 #jQuery
详解ES7 Decorator 入门解析
Feb 18 #Javascript
jQuery插件实现非常实用的tab栏切换功能【案例】
Feb 18 #jQuery
详解关于微信setData回调函数中的坑
Feb 18 #Javascript
jQuery实现的五星点评功能【案例】
Feb 18 #jQuery
You might like
Drupal读取Excel并导入数据库实例
2014/03/02 PHP
javascript知识点收藏
2007/02/22 Javascript
jQuery 核心函数以及jQuery对象
2010/03/23 Javascript
js escape,unescape解决中文乱码问题的方法
2010/05/26 Javascript
10款新鲜出炉的 jQuery 插件(Ajax 插件,有幻灯片、图片画廊、菜单等)
2011/06/08 Javascript
jquery多行滚动/向左或向上滚动/响应鼠标实现思路及代码
2013/01/23 Javascript
jQuery 淡入淡出 png图在ie8下有黑色边框的解决方法
2013/03/05 Javascript
Array栈方法和队列方法的特点说明
2014/01/24 Javascript
jquery实现简易的移动端验证表单
2015/11/08 Javascript
javascript高级选择器querySelector和querySelectorAll全面解析
2016/04/07 Javascript
带有定位当前位置的百度地图前端web api实例代码
2016/06/21 Javascript
基于ajax与msmq技术的消息推送功能实现代码
2016/12/26 Javascript
JS仿JQuery选择器功能
2017/03/08 Javascript
详解vue项目构建与实战
2017/06/27 Javascript
基于vue组件实现猜数字游戏
2020/05/28 Javascript
详解React开发必不可少的eslint配置
2018/02/05 Javascript
详解Vue This$Store总结
2018/12/17 Javascript
VUE v-model表单数据双向绑定完整示例
2019/01/21 Javascript
微信小程序使用map组件实现解析经纬度功能示例
2019/01/22 Javascript
[14:57]DOTA2 HEROS教学视频教你分分钟做大人-幽鬼
2014/06/13 DOTA
Python计算三维矢量幅度的方法
2015/06/15 Python
Django如何实现内容缓存示例详解
2017/09/24 Python
python GUI编程(Tkinter) 创建子窗口及在窗口上用图片绘图实例
2020/03/04 Python
德国婴儿推车和儿童安全座椅商店:BABYSHOP
2016/09/01 全球购物
TripAdvisor瑞典:全球领先的旅游网站
2017/12/11 全球购物
20年同学聚会感言
2014/02/03 职场文书
消防安全员岗位职责
2014/03/10 职场文书
《少年王勃》教学反思
2014/04/27 职场文书
青安岗事迹材料
2014/05/14 职场文书
化妆品活动策划方案
2014/05/23 职场文书
新闻学专业求职信
2014/07/28 职场文书
社区娱乐活动方案
2014/08/21 职场文书
元旦趣味活动方案
2014/08/22 职场文书
幼儿园工作总结2015
2015/04/01 职场文书
阿里云服务器部署RabbitMQ集群的详细教程
2022/06/01 Servers
python index() 与 rindex() 方法的使用示例详解
2022/12/24 Python