Front-end холодные знания - декоратор

внешний интерфейс
Front-end холодные знания - декоратор

Существительное декоратор, если не пишетсяangular,nestДругие передовые студенты .,方法,属性,参数, добавляя к нему более мощные функции и отделяя его от исходной логики.aopРеализация программирования.

Или, может быть, я использовал некоторые

Напримерreactиспользуется вredux, использовал@connect

@connect(mapStateToProps, mapDispatchToProps)
class Index extends React.Component{}

существуетvue2в, используетсяvue-property-decoratorплагин

@Component({})
class Index extends Vue {}

Сегодня я покажу вам, что такое декоратор.

Предложение декоратора в javascript

javascriptесть装饰器Это предложение, но его долгое время не удавалось реализовать.

В первые дни предложение декоратора было другим, чем сейчас, иTypescriptРеализовал декоратор рано, в самый разangular2тщательно использованныйTypescriptпровести рефакторинг, активно используя декораторы, которые в то время все еще были предложением.

Но сейчас предложение декоратора давно отличается от того, что было в то время, и изменено до неузнаваемости.angularкоманда и позжеnestКоманда, определенно не согласна с новым предложением декоратора. как тогдаPromise A+, также управляется сообществом, но в официальной реализацииPromiseСообщество использовало его раньшеPromiseбиблиотеки, для совместимости с этими библиотеками, теперь дляPromiseсуждения теперь основаны наthenableОб этом типе утки судить не поinstanceofЭто более точное суждение снизу.

а такжеPromiseразные,PromiseЭто двойная инверсия управления.Упор делается на порядок выполнения.Как это реализовать на самом деле не очень важно.Людей больше волнует его полезность. Декоратор — это уровень логики реального кода, изменение определенного правила означает, что общая логика может быть совершенно другой. Принудительно, для предыдущего использованияangular,nestПроект полностью разрушительный удар,angularкоманда иnestкоманда, ужеTypescriptкоманда, вtc39Конечно, не готовы передать предложение. Это привело к тому, что предложение декоратора было отложено на полку.

Но также интересно сказать, что, вообще говоря, после того, как предложение отклонено, ему нужно вернуться кstage1Начал с нуля, но декоратор продолжает получатьstage2.

Использовать декоратор

До официальной реализации этого предложения мы должны использовать декораторы, как правило, двумя способами

  • использоватьbabelплагин
  • использоватьTypescript

Я сказал раньше,TypescriptКоманда уже давно реализовала функционал декоратора, так что нам осталось только создать.tsфайл, вы можете свободно использовать декоратор, конечно, чтобы открытьexperimentalDecoratorsопции.

декораторская фабрика

Перед тем, как представить декораторы, давайте кратко познакомимся с понятием — фабрики декораторов.

Как следует из названия, фабрика — это место, где происходит сборка, а фабрика декораторов — это то, что собирает определенные ценности и предметы для украшения.

По сравнению с обычной функцией декоратора, у нее есть еще один вызов для передачи данных для сборки, поэтому самая большая разница между фабрикой декораторов и обычным декоратором заключается в ее настраиваемых параметрах.

декоратор класса

декоратор класса, объявленный вclassнад ключевым словом.

Простое понимание состоит в том, чтобы передать этот класс в качестве параметра декоратора.В функции декоратора вы можете выполнять различные операции с этим классом.

Не говорите чушь, просто посмотрите на код

@Init
class Index {
  public age = 12
}

function Init<T extends {new (...args: any[]): {}}>(constructor: T) {
  return class extends constructor {
    age = 21
  }
}

console.log(new Index())

// class_1 { age: 21 }

// function Init<T extends new (...args: any[]) => {}>(constructor: T): {
//  new (...args: any[]): (Anonymous class);
//  prototype: Init<any>.(Anonymous class);
// } & T

при создании этогоIndexкласс, его декоратор будет вызван одновременноInit, и воляIndexПередаем его, и на этом основании мы можем выполнять различные операции над классом через эту функцию.

Давайте посмотрим на фабрику декораторов класса decorator, как ею пользоваться, что обычно используется@connectтакой метод

@InjectSex('男')
class Two {}

function InjectSex(sex: '男' | '女') {
  return function<T extends {new (...args: any): {}}>(target: T) {
    target.prototype.sex = sex
    return target
  }
}

console.log(Reflect.getPrototypeOf(new Two()))

// { sex: '男' }

декоратор метода

Декораторы методов используются для оформления методов, и существует только один декоратор класса.targetПараметры разные, декоратор метода получает всего три параметра, которые

  • targetэкземпляр класса
  • keyимя метода
  • descriptorДескриптор, используемый для описания этого метода, т.е.Object.definePropertyВ третьем параметре методаvalue,writable,enummerable,configurable
class Fun {
  @AddOne
  log(x: number) {
    console.log(x)
  }
}

function AddOne(target, key, descriptor) {
  console.log(target, 'target') // { log: [Function (anonymous)] } target
  console.log(key, 'key') // log key
  console.log(descriptor, 'descriptor')
  // {
  //   value: [Function (anonymous)],
  //   writable: true,
  //   enumerable: true,
  //   configurable: true
	// } descriptor
  
  const val = descriptor.value
  descriptor.value = function(...args) {
    return val(args[0] + 1)
  }
  return descriptor
}

const fun = new Fun
fun.log(1)

// 2

мы проходимdescriptorсерединаvalueсвойства, захватить исходный метод и переписать его так, чтобы существующий метод можно было модифицировать с наименьшим аспектом.

Если это фабрика декораторов, нам все равно нужно обернуть слой функций снаружи

class FuncTwo {
  @InjectPrefix('托尼-')
  log(x) {
    console.log(x)
  }
}

function InjectPrefix(prefix: string) {
  return function(target, key, descriptor) {
    const val = descriptor.value
    descriptor.value = function(...args) {
      return val(prefix + args[0])
    }
    return descriptor
  }
}

const funcTwo = new FuncTwo
funcTwo.log('斯塔克')

// 托尼-斯塔克

декоратор недвижимости

Декоратор свойств обычно используется для перехвата свойств.Он получает два параметра:targetи имя текущего свойства, мы можем использовать фабрику декораторов, чтобы добавить значения в украшенное свойство.

class Prop {
  @init(16)
  age: number
}

function init(age: number) {
  return function(target, key) {
    target[key] = age
    return target
  }
}

const prop = new Prop
console.log(prop.age)

// 16

декоратор параметров

Декоратор параметров получает три параметра, которыеtarget,key(текущий метод) иindex(индекс текущего параметра)

class Param {
  log(@require name: string, @require age: number) {
    console.log(name, age)
  }
}

function require(target, key, index) {
  console.log(target, key, index)
  return target
}

const param = new Param
param.log('张三', 18)

// { log: [Function (anonymous)] } log 1
// { log: [Function (anonymous)] } log 0
// 张三 18

Однако декораторы методов обычно используются в соответствии с их назначением, например, в следующем примере.

class Param {
  @Validate
  log(@require name?: string, @require age?: number) {
    console.log(name, age)
  }
}

function Validate(target, key, descriptor) {
  const val = descriptor.value
  const required = val.required
  console.log(required) // [0, 1]
  descriptor.value = function(...args) {
    required.forEach(index => {
      if (!args[index]) {
        throw new Error('缺少参数')
      }
    })
    return val(...args)
  }
  return descriptor
}

function require(target, key, index) {
  target[key].required = [index, ...(target[key].required || [])]
  return target
}

const param = new Param
param.log()

// /Users/asarua/Desktop/demo/decorator/params-decorator.ts:13
//    required.forEach(index => {
             ^
// Error: 缺少参数

пройти черезrequireдекоратор параметров, чтобыtarget[key]добавлен методrequiredпараметры, затем передатьValidateПроверьте это.

Эпилог

Декоратор всегда использовался инженерами Java, в каждомController,Service, есть методы, плюс много.

На самом деле фронтенд-инженеры тоже могут попробовать это в своей повседневной работе.logВ любом методе использование декораторов может лучше отделить ненужную логику и лучше поддерживать ее.