Углубленные шаблоны проектирования JavaScript, а затем иметь теоретическую основу для оптимизации кода.

внешний интерфейс JavaScript
Углубленные шаблоны проектирования JavaScript, а затем иметь теоретическую основу для оптимизации кода.

Обзор шаблонов проектирования

Я думаю, что многие из моих друзей, как и я, видели «Дракон Бабу», когда они были молодыми.Героиня Ван Юянь в нем - знаток боевых искусств, но у нее нет настоящего боя. Например, когда Дуань Юй и Муронг Фу играли друг против друга, она неоднократно диктовала инструкции: «Дуань Лан, две руки драконьего когтя, три типа захвата бусин, береги талию и ребра, обращай внимание на точку Циху. .....", хотя это и выглядит как базовые навыки фистинга, но с комментариями сбоку, оно все равно кажется намного выше. Все верно, дизайнерский режим на самом деле похож на эти фокусы Многие режимы дают людям ощущение, что их используют не реже, но я не знаю, что это профессиональный трюк... . Но нам нужно глубоко понимать эти общие закономерности на системном уровне, которые могут не только играть роль дивергентного мышления, но и направлять нашу способность решать проблемы. Если вы раньше редко сталкивались с шаблонами проектирования, то эта статья надеется вам помочь, спасибо за внимание и лайки.

1.1 Определение режима

Определение шаблонов проектирования: краткие и элегантные решения конкретных проблем при проектировании объектно-ориентированного программного обеспечения.

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

1.2 Классификация шаблонов

Согласно стандарту существует 23 типа шаблонов проектирования в 3 категориях, и из-за некоторых особенностей JavaScript, таких как слабо типизированный язык, неинтерфейсное программирование и другие особенности, только некоторые из них являются более важными. Ниже приведены названия 23 шаблонов проектирования.

Типы имя схемы
Творчество заводской прототип синглтона
Комбинированный тип (структурный тип) Адаптер Decorator Proxy Facade Bridge
поведенческий Команда наблюдателя Посредник Государственная политика Интерпретатор Итератор Шаблон шаблона посетителя Памятка цепочки ответственности

Считаете ли вы, что эти высокоуровневые слова властны? Давайте начнем с некоторых важных моделей, которые нужно понять и углубить.

Во-вторых, заводской режим

1.1 Основные характеристики

Фабричный шаблон имеет три формы: простая фабрика, фабричный метод и абстрактная фабрика. Наиболее распространенным в js является простой фабричный шаблон. Идея оформления фабричного узора такова:

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

1.2 Основная роль

Основная роль фабричного шаблона заключается в следующем:

  • В основном он используется, чтобы скрыть сложность создания экземпляра, и ему нужно только предоставить интерфейс для внешнего мира;
  • Реализовать разделение конструкторов и создателей для соблюдения принципа открытости и замкнутости;

1.3 Классификация

  • Простой фабричный шаблон: объект фабрики создает экземпляр объекта продукта. То есть используется для создания объектов одного класса;
  • Шаблон фабричного метода: установите абстрактный базовый класс и поместите фактический фокус создания экземпляра на подклассы базового абстрактного класса;
  • Шаблон абстрактной фабрики. Абстракция фабрики класса используется для создания кластера класса продукта и не отвечает за создание экземпляра продукта определенного типа. Поскольку шаблон абстрактной фабрики редко используется в JS, в этой статье рассматриваются первые два шаблона.

1.4 Пример демонстрации

Во-первых, давайте сначала разберемся, что такое фабрика наиболее интуитивно на простом примере:

// 定义产品
class Product {
    constructor(name) {
        this.name = name;
    }
    init() {
        console.log('初始化产品')
    }
}

// 定义工厂
class Factory {
    create(name) {
        return new Product(name); // 核心思想
    }
}

let c = new Factory(); 
let p = c.create('p1');
p.init();

Наиболее интуитивно понятная часть фабричного шаблона заключается в том, что создание объектов продукта достигается не с помощью прямых новых классов продуктов, а с помощью фабричных методов. Теперь давайте опишем простую фабрику на более приятном примере:

//User类
class User {
  //构造器
  constructor(opt) {
    this.name = opt.name;
    this.viewPage = opt.viewPage;
  }

  static getInstance(role) {
    switch (role) {
      case 'superAdmin':
        return new User({ name: '超级管理员', viewPage: ['首页', '通讯录', '发现页', '应用数据', '权限管理'] });
        break;
      case 'admin':
        return new User({ name: '管理员', viewPage: ['首页', '通讯录'] });
        break;
      default:
        throw new Error('params error')
    }
  }
}

//调用
let superAdmin = User.getInstance('superAdmin');
let admin = User.getInstance('admin');

Из приведенного выше примера видно, что каждый раз, когда мы создаем новый экземпляр объекта, нам нужно только передать соответствующие параметры, чтобы получить указанный экземпляр объекта. Самый наглядный пример — если не использовать фабричный паттерн, в коде будет много нового, на что смотреть не очень удобно.

Фактически, простой фабричный шаблон смог удовлетворить большинство наших клиентских бизнес-сценариев.Если мы должны упомянуть об одном недостатке, так это то, что нам нужно переписывать этот класс User каждый раз, когда появляется новый экземпляр. некоторые конфликты. На этом этапе появляется шаблон фабричного метода.Основная идея состоит в том, чтобы отделить большой класс User и использовать его подклассы для реализации процесса создания объектов-экземпляров:

class User {
  constructor(name = '', viewPage = []) {
    this.name = name;
    this.viewPage = viewPage;
  }
}

class UserFactory extends User {
  constructor(name, viewPage) {
    super(name, viewPage)
  }
  create(role) {
    switch (role) {
      case 'superAdmin': 
        return new UserFactory( '超级管理员', ['首页', '通讯录', '发现页', '应用数据', '权限管理'] );
        break;
      case 'admin':
        return new UserFactory( '管理员', ['首页', '通讯录'] );
        break;
      default:
        throw new Error('params error');
    }
  }
}
let userFactory = new UserFactory();
let superAdmin = userFactory.create('superAdmin');
let admin = userFactory.create('admin');
let user = userFactory.create('user');

Таким образом, хотя экземпляр должен быть передан через новый, по крайней мере, нам не нужно изменять содержимое класса User.Хотя объем кода не сильно отличается от простого режима, основная мысль действительно так.

1.5 Сценарии применения

(1) селектор jQuery $(селектор)

$('div')а такжеnew $('div')Какая разница? Зачем$('div')может быть реализовано непосредственноnewэффект, при удаленииnew $('div')это$('div')удаленныйnewНедостатки сложного написания также могут обеспечить идеальное введение в код цепной операции, потому что$Встроенный механизм реализации — это фабричный шаблон. Базовый код выглядит следующим образом:

class jQuery {
    constructor(selector) {
        super(selector)
    }
    // ...
}

window.$ = function(selector) {
    return new jQuery(selector)
}

(2) Асинхронные компоненты Vue

Vue.component('async-example' , (resolve , reject) => {
    setTimeout(function() {
        resolve({
            template: `<div>I am async!</div>`
        })
    }, 1000)
})

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

3. Одноэлементный режим

3.1 Основные характеристики

Шаблон синглтона, как следует из названия, гарантирует глобальный синглтон экземпляра, который резюмируется следующим образом:

  • Единственное использование системы
  • Только один экземпляр класса (обратите внимание, что только один экземпляр должен быть одинаково сильным ===)

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

3.2 Пример демонстрации

Вот пример одноэлементного шаблона:

class Modal {
    login() {
        console.log('login...');
    }
}
Modal.create = (function() {
    let instance
    return function() {
        if(!instance) {
           instance = new Modal();
        }
        return instance
    }
})()
let m1 = Modal.create();
let m2 = Modal.create();
console.log(m1 === m2) // true

Приведенный выше код представляет собой простую версию одноэлементного режима.Посредством функции немедленного выполнения и функции закрытия js определяется начальный экземпляр, а затем может быть вынесено решение.instanceНезависимо от того, существует ли он, если он существует, он будет возвращен напрямую, в противном случае он будет создан и возвращен, то есть для обеспечения того, чтобы класс имел только один экземпляр объекта. Также существует множество «прозрачных» одноэлементных шаблонов:

let Modal = (function(){
    let instance;
    return function(name) {
        if (instance) {
           return instance;
        }
        this.name = name;
        return instance = this;
    }
})();

Modal.prototype.getName = function() {
    return this.name
}

let question = new Modal('问题框');
let answer = new Modal('回答框');

console.log(question === answer); // true
console.log(question.getName());  // '问题框'
console.log(answer.getName());  // '问题框'

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

3.3 Сценарии применения

Существует слишком много сценариев применения шаблона singleton. Во Vue мы знакомы с хранилищем во Vuex и redux.

3. Режим адаптера

3.1 Определение и характеристики

Шаблон адаптера хорошо изучен, и на самом деле он непреднамеренно используется в повседневной разработке. Шаблон адаптера (Adapter) предназначен для преобразования интерфейса (метода или свойства) класса (объекта) в другой интерфейс (метод или свойство), который адаптируется к текущей сцене.Шаблон адаптера делает те классы, которые не могут работать вместе из-за несовместимости интерфейсы ( объект ) могут выполнять некоторую работу. Следовательно, режим адаптера должен включать в себя три роли цели (Target), источника (Adaptee) и адаптера (Adapter).

3.2 Сценарии применения

Для самого яркого и простого примера в моей работе вы знаете, что адаптеры есть везде. Внешний интерфейс запрашивает набор наборов данных через интерфейс, типы — статьи, ответы и курсы, где тип даты, возвращаемый классом статьи, —2019-08-15 09:00:00строка формата, класс ответа2019/08/15 09:00:00, класс курса возвращает формат временной метки, а поле времени создания статьи и ответа называется createAt, а курс называется createTime (это то, чем мы являемся...) Возвращаемые данные выглядят следующим образом:

let result = [
      {
          id: 1
          type: 'Article',
          createAt: '2019-06-12 08:10:20',
          updateAt: '2019-08-15 09:00:00',
          ......
      },
      {
          id: 2
          type: 'Answer',
          createAt: '2019-04-11 08:11:23',
          updateAt: '2019/08/15 09:00:00',
          ......
      },
      {
          id: 3
          type: 'Course',
          createTime: 1554941483000,
          updateAt: 1565830800000,
          ......
      }
    ]

Теперь мы хотим передать формат этих сущностей на мобильную сторону. И отображать единый формат времени. В общем, когда мы сталкиваемся с типом времени, первое, о чем мы обычно думаем, это сначала создать new Date(), а затем выполнить соответствующее преобразование, но, к сожалению, в мобильной системе IOS,2019-08-15Время в этом формате, разделенном штрихами, не распознается, поэтому нам нужно сделать адаптер данных для обработки совместимости в это время:

 let endResult = result.map(item => adapter(item));
 
 let adapter = function(item) {
    switch(item.type) {
        case 'Article':
          [item.createAt, item.updateAt] = [
             new Date(item.createAt.replace(/-/g,'/')).getTime(),
             new Date(item.updateAt.replace(/-/g,'/')).getTime()
          ]
        break;
        case: 'Answer': 
          item.createAt = new Date(item.createAt.replace(/-/g,'/')).getTime();
        break;
        case: 'Course':
          item.createAt = item.createTime
        break;
    }
 }

Ну да, этот адаптер также можно назвать адаптером данных, с помощью этого метода можно адаптировать данные всех типов данных сущности.

Возьмем еще один пример адаптера на основе классов ES6:

// 目标
class Target {
    typeGB() {
        throw new Error('This method must be overwritten!');
    }
}

// 源
class Adaptee {
    typeHKB() {
        console.log("香港(Hong Kong)标准配件"); // 港独都是sb
    }
}

// 适配器
class Adapter extends Target {
    constructor(adaptee) {
        super();
        this.adaptee = adaptee;
    }
    typeGB() {
        this.adaptee.typeHKB();
    }
}

let adaptee = new Adaptee();

let adapter = new Adapter(adaptee);
adapter.typeGB(); //香港(Hong Kong)标准配件

В приведенном выше примере метод typeHKB() экземпляра объекта класса Adaptee адаптируется к универсальному методу typeGB(). Кроме того, я не хочу повторять то, что сказал чиновник, я просто хочу быть прямолинейным: Гонконг...

В-четвертых, режим декоратора

4.1 Определение и характеристики

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

  • Добавить новую функциональность объектам;
  • Его первоначальная структура и функции не меняются, то есть будут продолжать использоваться исходные функции, а сцена не изменится.

Непосредственно к предыдущему примеру:

class Circle {
    draw() {
        console.log('画一个圆形');
    }
}

class Decorator {
    constructor(circle) {
        this.circle = circle;
    }
    draw() {
        this.circle.draw();
        this.setRedBorder(circle);
    }
    setRedBorder(circle) {
        console.log('画一个红色边框');
    }
}

let circle = new Circle();
let decorator = new Decorator(circle);
decorator.draw(); //画一个圆形,画一个红色边框

В этом примере мы пишемDecoratorКласс декоратора, который переопределяет объект экземпляра.drawметод, добавляя новый метод к своему методуsetRedBorder(), поэтому его вывод оформлен в конце.

4.2 Плагин декоратора

Синтаксис декоратора существует в ES7. Вам необходимо установить соответствующий подключаемый модуль babel. Давайте посмотрим, как используется подключаемый модуль. Сначала установите подключаемый модуль и настройте соответствующий синтаксис:

npm i babel-plugin-transform-decorators-legacy 

//.babelrc
{
    "presets": ["es2015", "latest"],
    "plugins": ["transform-decorators-legacy"]
}

Добавьте декоратор testDec в класс Demo, и класс Demo будет иметь атрибуты, заданные декоратором:

@testDec
class Demo {}

function testDec(target) {
   target.isDec = true;
}

alert(Demo.isDec) // true

Из приведенного выше примера можно сделать следующие выводы по коду:

@decorator 
class A {}

// 等同于

class A {}
A = decorator(A) || A;

4.3 Сценарии прочности

Есть много примеров декораторов, в основном мы изучаем миксины и декорирование атрибутов.

(1) пример миксина

function mixins(...list) {
   return function(target) {
      Object.assign(target.prototype, ...list)
   }
}

const Foo = {
    foo() {
        alert('foo');
    }
}

@mixins(Foo)
class MyClass { }

let obj = new MyClass();
obj.foo();

В приведенном выше примере Foo используется в качестве фактического параметра цели, а MyClass используется в качестве фактического параметра списка Наконец, все методы-прототипы (foo) Foo оформляются в классе MyClass и становятся методами MyClass. Результатом выполнения окончательного кода является то, что он выполняетсяfoo().

(2) Декоратор недвижимости

Фиксированный синтаксис:

function readonly(target, name, descriptor) {
    // descriptor 属性描述对象(Object.defineProperty 中会用到)
    /*
      {
          value: specifiedFunction,
          enumerable: false,
          configurable: true
          writable: true 是否可改
      }
    */
}

Установка свойств класса только для чтения:

function readonly(target , name , descriptor) {
  descriptor.writable = false;
}

class Person {
    constructor() {
        this.first = '周';
        this.last = '杰伦';
    }

    @readonly
    name() {
        return `${this.first}${this.last}`
    }
}

const p = new Person();
console.log(p.name());  // 打印成功 ,‘周杰伦’

// 试图修改name:
p.name = function() {
    return true;
}
// Uncaught TypeError:Cannot assign to read only property 'name' of object '#<Person>'

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

5. Агентский режим

5.1 Определение и характеристики

Шаблон прокси определяется следующим образом:

Предоставляет суррогат или заполнитель для объекта для управления доступом к нему.

С точки зрения непрофессионала, режим прокси должен подчеркивать значение «прокси». Этот сценарий режима требует трех типов ролей, а именно пользователя, целевого объекта и прокси. Целью пользователя является прямой доступ к целевому объекту, но он не может получить прямой доступ и должен сначала пройти через агента. Так что режим очень похож на сцену со звездным агентом. Его характеристики:

  • Пользователь не имеет доступа к целевому объекту;
  • Добавьте агента посередине, и делайте авторизацию и управление через агента.

Режим прокси очень удобен, обычно, если вы сталкиваетесь с некоторыми операциями с большими накладными расходами, вы можете отложить создание виртуального прокси до тех пор, пока он вам не понадобится, например, отложенные операции загрузки. Или некоторые операции со многими предварительными условиями, такими как предпосылка реализации целевой операции, должны быть зарегистрированы, а идентификатор соответствует определенным характеристикам, в это время эти предварительные условия также могут быть записаны в агент. Вот пример загрузки изображения:

class ReadImg {
    constructor(fileName) {
       this.fileName = fileName;
       this.loadFromDisk();
    }

    display() {
        console.log('display...' + this.fileName);
    }

    loadFromDisk() {
        console.log('loading...' + this.fileName);
    }
}

class ProxyImg {
    constructor(fileName) {
       this.readImg = new ReadImg(fileName)
    }

    display() {
        this.readImg.display();
    }
}

let proxyImg = new ProxyImg('1.png');
proxyImg.display();

5.2 Практические приложения

(1) прокси-сервер события HTML-элемента:

События прокси-элемента HTML, также известные как события прокси-сервера веб-страницы, следующие:

<body>
    <div id="div1">
        <a href="#">a1</a>
        <a href="#">a2</a>
        <a href="#">a3</a>
        <a href="#">a4</a>
        <a href="#">a5</a>
    </div>

    <script>
       var div1 = document.getElementById('div1');
       div1.addEventListener('click', (e) => {
          var target = e.target;
          if(target.nodeName === 'A') {
             alert(target.innerHTML);
          }
       })
    </script>
</body>

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

(2) $.proxy

$.proxyдаjQueryПредоставленный нам прокси-метод, также взяв в качестве примера приведенный выше html-элемент, записывает событие клика:

// html如上例
$('#div1').click(function() {
   setTimeout(function() {
      $(this).css('background-color', 'yellow')
   },1000)
})

вышесказанноеdivЩелчок не приводит к изменению цвета фона, потому чтоsetTimeoutФактор, из-за которого this во внутренней функции указывает наwindowа не соответствующийdiv. Обычно мы делаемsetTimeoutПолучите текущую эту точку перед методом, код выглядит следующим образом:

$('#div1').click(function() {
   let _this = this;
   setTimeout(function() {
      $(_this).css('background-color', 'yellow')
   },1000)
})

И если мы не используем вышеуказанный метод, мы можем использовать$.proxyПрокси целевой элемент для достижения:

$('#div1').click(function() {
    var fn = $.proxy(function() {
        $(this).css('background-color', 'yellow')
    }, this);
    
    setTimeout(fn , 1000)
})

(3) ES6 proxy

Я думаю, что все знакомы с прокси-сервером ES6.Двусторонний принцип привязки Vue 3.0 реализован с использованием прокси-сервера ES6.Вот простой пример:

let star = {
    name: '菜徐坤',
    song: '~鸡你太美~'
    age: 40,
    phone: 13089898989
}

let agent = new Proxy(star , {
    get(target , key) {
        if(key == 'phone') {
            // 返回经济人自己的电话
            return 15667096303
        }
        if(key == 'price') {
           return 20000000000
        }
        return target[key]
    },
    set(target , key , val) {
       if(key === 'customPrice') {
          if(val < 100000000) {
              throw new Error('价格太低')
          }
          else {
              target[key] = value;
              return true
          }
       }
    }
})

// agent 对象会根据相应的代理规则,执行相应的操作:
agent.phone // 15667096303  
agent.price // 20000000000 

Не нужно объяснять, я действительно не понимаю, почему он такой горячий. . . . . .

7. Режим наблюдателя

7.1 Определение и характеристики

Насколько важен шаблон наблюдателя? Позвольте мне сказать так: если Бог сказал вам, что вы можете изучить только один режим в своей жизни, вы должны без колебаний выбрать режим наблюдателя. Режим наблюдателя, также известный как режим подписки-публикации, знаком тем, кто знаком с Vue.Этот режим определяет отношение 1-к-N (примечание: не обязательно один-ко-многим, поэтому более точное описание должно быть 1 отношение -к-N) N), так что наблюдатели одновременно прослушивают соответствующее изменение состояния определенного объекта, и как только изменение изменяется, все наблюдатели уведомляются, тем самым вызывая соответствующие события наблюдателей. Поэтому в паттерне Observer есть два типа ролей: Observer (издатель) и Observed (подписчик).

Мы можем непосредственно посмотреть на диаграмму классов UML шаблона наблюдателя:

image

Анализ диаграммы классов:

  • У каждого наблюдателя (Observer) есть метод обновления, и состояние наблюдателя ожидает срабатывания;
  • За каждым субъектом может наблюдать N наблюдателей с помощью метода присоединения, то есть наблюдатели сохраняются в массиве наблюдателей субъекта;
  • Тема имеет три общих метода: инициализировать состояние (init), получить состояние (getState) и установить состояние (setState);
  • Когда состояние субъекта изменяется, все наблюдатели уведомляются с помощью специального метода notifyAllObervers.

Это очень понятно, давайте возьмем небольшой пример для приведенного выше описания:

// 创建一个主题,保存状态,状态变化之后触发所有观察者对象
class Subject {
    constructor() {
        this.state = 0;
        this.observers = []
    }

    getState() {
        return this.state
    }

    setState(state) {
       this.state = state;
       this.notifyAllObservers()
    }

    notifyAllObservers() {
        this.observers.forEach(observer => {
            observer.update()
        })
    }

    attach(observer) {
       this.observers.push(observer)
    }
}

// 观察者
class Observer {
    constructor(name , subject) {
       this.name = name;
       this.subject = subject;
       this.subject.attach(this);
    }
    update() {
        console.log(`${this.name} update, state: ${this.subject.getState()}`)
    }
}

let s = new Subject();
let o1 = new Observer('o1' , s);
let o2 = new Observer('o2' , s);
let o3 = new Observer('o3' , s);

s.setState(1)
s.setState(2)
s.setState(3)

/*
o1 update, state: 1
 o2 update, state: 1
o3 update, state: 1
o1 update, state: 2
o2 update, state: 2
o3 update, state: 2
o2 update, state: 3
o3 update, state: 3
*/

Его нельзя увидеть через окончательный результат.Каждый раз, когда тема меняет состояние, это вызывает обновление состояния всех наблюдателей.Тема запускает состояние 3 раза, а наблюдатель должен обновить 9 раз.

7.2 Пример сцены

На самом деле, мы непреднамеренно используем множество примеров шаблонов-наблюдателей, таких как Promise, прослушиватель событий EventEmitter в Node.js, хук жизненного цикла Watch в Vue и т. д. Все это шаблоны-наблюдатели, например, в компонентах Vue. настроен ли мониторинг данных в Watch, и при изменении данных срабатывает соответствующее событие? Есть еще Promise, почему асинхронная операция входит в then или catch после получения результата? Все они основаны на шаблоне Observer. Вот цитирую очень хорошую статью«Принцип двусторонней привязки Vue и его реализация».

Что ж, содержание этой статьи подойдет к концу первым.Мы рассмотрели основные моменты 23 шаблонов проектирования.Я разберусь с оставшимися не пунктами как можно скорее.Можно обратить внимание и поставить лайк.

Спасибо, г-н Цяньян, за проверку.

Справочная статья