美文网首页
10-TypeScirpt-装饰器-混入

10-TypeScirpt-装饰器-混入

作者: 低头看云 | 来源:发表于2020-10-05 07:55 被阅读0次

装饰器

1.什么是装饰器?

  • Decorator 是 ES7 的一个新语法,目前仍处于提案中,
  • 装饰器是一种特殊类型的声明,它能够被附加到类,方法, 访问器,属性或参数上
  • 被添加到不同地方的装饰器有不同的名称和特点
    • 附加到类上, 类装饰器
    • 附加到方法上,方法装饰器
    • 附加到访问器上,访问器装饰器
    • 附加到属性上,属性装饰器
    • 附加到参数上,参数装饰器
  1. 装饰器基本格式
    2.1普通装饰器
    2.2装饰器工厂
    2.3装饰器组合

3.如何在TS中使用装饰器?
在TS中装饰器也是一项实验性的特性, 所以要使用装饰器需要手动打开相关配置
修改配置文件 experimentalDecorators


  function test(target) {
    console.log('test')
    console.log('target', target)
  }
  // 如果一个函数返回一个回调函数, 如果这个函数作为装饰器来使用
  // 那么这个函数就是装饰器工厂
  function test1() {
    console.log('test1 out')
    return (target) => {
      console.log('target', target)
      console.log('test1 in')
    }
  }

  function test2(target) {
    console.log('test2')
  }

  function test3() {
    console.log('test3  out')
    return (target) => {
      console.log('test3 in')
    }
  }

  // 执行顺序
  // 结合起来使用, 回想从上至下执行所有的装饰器工厂, 拿到所有真正的装饰器
  // 然后再从下至上执行所有的装饰器
  // test1 out /  test3 out / test3 in / test2 / test1 in / test

  @test
  @test1()
  @test2
  @test3()
  class Person {}

类装饰器

  • 类装饰器在类声明之前绑定(紧靠着类声明)。

  • 类装饰器可以用来监视,修改或替换类定义

  • 在执行类装饰器函数的时候, 会把绑定的类作为其唯一的参数传递给装饰器

  • 如果类装饰器返回一个新的类,它会新的类来替换原有类的定义

    2.装饰器和装饰器工厂区别
    时候可以传递自定义参数

  function demo<T extends { new (...args: any[]) }>(target: T) {
    return class extends target {
      name: string = 'css'
      age: number = 18
    }
  }

  @demo
  class Person1 {}

  let p1 = new Person1()
  console.log(p1)

defineProperty

  • Object.defineProperty()

    • 可以直接在一个对象上定义一个新属性
    • 或者修改一个对象的享有属性, 并返回此对象
  • 定义一个新的属性

  let obj = { age: 18 }

  Object.defineProperty(obj, 'name', {
    value: 'css',
  })

  console.log('obj', obj) // {age: 18, name: "css"}
  • 修改原有属性
  let obj1 = { age: 18 }

  Object.defineProperty(obj1, 'age', {
    value: 22,
  })

  console.log('obj1', obj1) // {age: 22}
  • 修改属性配置 - 读写
  let obj2 = { age: 18 }
  Object.defineProperty(obj2, 'age', {
    writable: false,
    //   writable: true,
  })

  obj2.age = 111
  console.log('obj2', obj2) // {age: 18}
  • 修改属性配置 - 迭代
  let obj3 = { age: 14, name: 'js' }

  Object.defineProperty(obj3, 'name', {
    enumerable: false,
  })
  for (let key in obj3) {
    console.log(key) // age
  }
  • 修改属性配置-配置
  let obj4 = { age: 18, name: 'lnj' }
  Object.defineProperty(obj4, 'name', {
    enumerable: false,
    configurable: false,
  })
  Object.defineProperty(obj4, 'name', {
    enumerable: true,
    configurable: false,
  })
  for (let key in obj4) {
    console.log(key)
  }

方法装饰器

  • 方法装饰器写在在一个方法的声明之前(紧靠着方法声明)。

  • 方法装饰器可以用来监视,修改或者替换方法定义。

  • 方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

    • 对于静态方法而言就是当前的类, 对于实力方法而言就是当前的实例
    • 被绑定方法的名字。
    • 被绑定方法的属性描述符。
  function test(
    target: any,
    propertKe: string,
    descriptor: PropertyDescriptor
  ) {
    console.log('descriptor', descriptor)
    console.log('propertKe', propertKe)
    console.log('target', target)
   
    // configurable?: boolean;
    // enumerable?: boolean;
    // value?: any;
    // writable?: boolean;

    //   descriptor.enumerable = false
    descriptor.value = () => {
      console.log('323232332')
    }
  }

  class Person {
    // @test
    sayName(): void {
      console.log('my name is css')
    }
    @test
    sayAge(): void {
      console.log('my age is 18')
    }
    // @test
    static say(): void {
      console.log('say hello world')
    }
  }

  let p = new Person()

  p.sayAge()

访问器装饰器

  • 访问器装饰器声明在一个访问器的声明之前(紧靠着访问器声明)。
    访问器装饰器应用于访问器的 属性描述符并且可以用来监视,修改或替换一个访问器的定义

  • 访问器装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

    • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
    • 成员的名字。
    • 成员的属性描述符。
  • 注意:
    TypeScript不允许同时装饰一个成员的get和set访问器。
    取而代之的是,一个成员的所有装饰的必须应用在文档顺序的第一个访问器上

  function test(
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    // console.log(target);
    // console.log(propertyKey);
    // console.log(descriptor);
    descriptor.set = (value: string) => {
      console.log('value', value)
      target.myName = value
    }
    descriptor.get = (): string => {
      return target.myName
    }
  }

  class Person {
    private _name: string
    constructor(name: string) {
      this._name = name
    }
    @test
    get name(): string {
      return this._name
    }
    set name(value: string) {
      this._name = value
    }
  }

  let p = new Person('css')
  p.name = 'react'

  console.log(p.name)

  console.log('p', p)
  

参数装饰器

  • 参数装饰器写在一个参数声明之前(紧靠着参数声明)。

  • 参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

    • 对于静态成员来说是当前的类,对于实例成员是当前实例。
    • 参数所在的方法名称。
    • 参数在参数列表中的索引。
  • 其它
    属性装饰器,参数装饰器最常见的应用场景就是配合元数据(reflect-metadata),
    在不改变原有结构的同时添加一些额外的信息
    但是元数据目前也是在提案中, 也还没有纳入正式的标准
    所以对于装饰器而言, 我们只需要了解即可,
    因为提案中的所有内容将来都是有可能被修改的
    因为提案中的所有内容目前都有兼容性问题

  function test(target: any, proptyName: string, index: number) {
    console.log(target)
    console.log(proptyName)
    console.log(index)
  }
  class Person {
    say(age: number, @test name: string): void {}
  }

属性装饰器

  • 属性装饰器写在一个属性声明之前(紧靠着属性声明)
  • 属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:
    • 对于静态属性来说就是当前的类, 对于实例属性来说就是当前实例
    • 成员的名字。
  function test(target: any, proptyName: string) {
    console.log(target)
    console.log(proptyName)
    target[proptyName] = 'css'
  }
  class Person {
    @test
    static age: number
    //   @test
    name?: string
  }
  let p = new Person()
  console.log(p)
  console.log(Person.age)

混入

  • 1.对象混入
let obj1 = {name:'lnj'};
let obj2 = {age:34};
Object.assign(obj1, obj2);
console.log(obj1);
console.log(obj2);
  • 2.类混入
  • 需求: 定义两个类, 将两个类的内容混入到一个新的类中
 class Dog {
    name: string = 'wc'
    say(): void {
      console.log('wang wang')
    }
  }
  class Cat {
    age: number = 3
    run(): void {
      console.log('run run')
    }
  }
  // 注意点: 一次只能继承一个类
  // class Animal extends Dog, Cat{
  //
  // }
  class Animal implements Dog, Cat {
    name: string
    age: number
    say: () => void
    run: () => void
  }
  function myMixin(target: any, from: any[]) {
    from.forEach((fromItem) => {
      Object.getOwnPropertyNames(fromItem.prototype).forEach((name) => {
        target.prototype[name] = fromItem.prototype[name]
      })
    })
  }
  myMixin(Animal, [Dog, Cat])
  let a = new Animal()
  console.log(a)
  a.say()
  a.run()
  // console.log(a.name);
  // console.log(a.age);
 

相关文章

  • 10-TypeScirpt-装饰器-混入

    装饰器 1.什么是装饰器? Decorator 是 ES7 的一个新语法,目前仍处于提案中, 装饰器是一种特殊类型...

  • 装饰器模式

    装饰器模式 装饰器模式是一种旨在提升代码复用率的结构性模式。有点类似于混入模式,它被认为是一种可以替代子类的可行方...

  • LESS - Mixins(混入)

    混入 Mixins 混入是指把已存在的样式混入到别的样式中。 你可以把 class 选择器 和 id 选择器混入到...

  • 装饰器

    """@装饰器- 普通装饰器- 带参数的装饰器- 通用装饰器- 装饰器装饰类- 内置装饰器- 缓存装饰器- 类实现...

  • typescript 五种装饰器

    装饰器类型 装饰器的类型有:类装饰器、访问器装饰器、属性装饰器、方法装饰器、参数装饰器,但是没有函数装饰器(fun...

  • python——装饰器详解

    一、装饰器概念 1、装饰器 装饰器:一种返回值也是一个函数的函数,即装饰器。 2、装饰器目的 装饰器的目的:装饰器...

  • Python装饰器

    Python装饰器 一、函数装饰器 1.无参装饰器 示例:日志记录装饰器 2.带参装饰器 示例: 二、类装饰器 示例:

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • 装饰器

    装饰器 decorator类装饰器 带参数的装饰器 举例(装饰器函数;装饰器类;有参与无参) https://fo...

  • TypeScript装饰器

    前言 装饰器分类 类装饰器 属性装饰器 方法装饰器 参数装饰器需要在tsconfig.json中启用experim...

网友评论

      本文标题:10-TypeScirpt-装饰器-混入

      本文链接:https://www.haomeiwen.com/subject/fwguuktx.html