Хотите использовать Vuejs, чтобы ответить на 20 000 популярных вопросов на собеседовании 2–9

опрос

В прошлой статье речь шла только об одном вопросе. Вы еще не читали? Давайте удовлетворим наше любопытство~~

Хотите использовать Vuejs, чтобы обойти ограничение в 20 000 необходимых популярных вопросов для интервью (2) — данные

Последнийv-если и v-дляЭто позволить каждому глубоко понять общий принцип Vue? Давайте поговорим о втором вопросе

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

Найдите ответ в исходном коде: src\core\instance\state.js - initData()

Каждый раз, когда функция выполняется, она возвращает новый экземпляр объекта данных.

Код теста выглядит следующим образом

<!DOCTYPE html>
<html>

<head>
    <title>Vue事件处理</title>
</head>

<body>
    <div id="demo">
        <h1>vue组件data为什么必须是个函数? </h1>
        <comp></comp>
        <comp></comp>
    </div>
    <script src="../../dist/vue.js"></script>
    <script>
        Vue.component('comp', {
            template:'<div @click="counter++">{{counter}}</div>',
            data: {counter: 0}
        })
        // 创建实例
        const app = new Vue({
            el: '#demo',
        });
    </script>
</body>
</html>

Программа не может даже пройти обнаружение vue

В заключение

Может быть несколько экземпляров компонентов Vue.Если данные определены в виде объектов, это приведет к тому, что они будут совместно использовать объект данных, тогда изменение состояния повлияет на все экземпляры компонентов, что неразумно; если они определены в виде функции, он будет изменен при initData.Он возвращает новый объект данных в качестве фабричной функции, что эффективно позволяет избежать проблемы загрязнения состояния между несколькими экземплярами. В процессе создания корневого экземпляра Vue этого ограничения не существует, потому что корневой экземпляр может быть только один, так что в этой ситуации можно не беспокоиться.

Хотите использовать Vuejs, чтобы прорваться через 20 000 популярных вопросов на собеседовании (3) — происхождение ключа

Знаете ли вы роль и принцип работы key in vue? Расскажите о своем понимании этого.

Найдите ответ в исходном коде: src\core\vdom\patch.js - updateChildren()

Код теста выглядит следующим образом

<!DOCTYPE html>
<html>

<head>
    <title>03-key的作用及原理?</title>
</head>

<body>
    <div id="demo">
        <p v-for="item in items" :key="item">{{item}}</p>
    </div>
    <script src="../../dist/vue.js"></script>
    <script>
        // 创建实例
        const app = new Vue({
            el: '#demo',
            data: { items: ['a', 'b', 'c', 'd', 'e'] },
            mounted () {
                setTimeout(() => {
                    this.items.splice(2, 0, 'f')
                }, 2000);
            },
        });
    </script>
</body>

</html>

Приведенный выше случай воспроизводит следующий процесс

не использовать ключ

Если вы используете ключ

// 首次循环patch A
A B C D E
A B F C D E

// 第2次循环patch B
B C D E
B F C D E

// 第3次循环patch E
C D E
F C D E

// 第4次循环patch D
C D
F C D

// 第5次循环patch C
C 
F C

// oldCh全部处理结束,newCh中剩下的F,创建F并插入到C前面

В заключение

  1. Функция ключа в основном заключается в эффективном обновлении виртуального DOM.Принцип заключается в том, что Vue может точно определить, являются ли два узла одинаковыми с помощью ключа во время процесса исправления, чтобы избежать частого обновления различных элементов, что делает весь патч обрабатывайте более эффективно и уменьшайте объем операций DOM и повышайте производительность.
  2. Кроме того, если ключ не установлен, это может вызвать некоторые скрытые ошибки при обновлении списка.
  3. В vue ключевой атрибут также используется при переходе между элементами с одинаковым именем тега. Цель состоит в том, чтобы позволить vue различать их, иначе vue только заменит свои внутренние атрибуты, не вызывая эффекта перехода.

Хотите использовать Vuejs, чтобы ответить на 20 000 популярных вопросов на собеседовании (4) — сразитесь с виртуальным DOM

Как вы понимаете алгоритм diff в vue?

  • Анализ исходного кода 1: необходимость, lifecycle.js — mountComponent()

    • В данных, используемых в компоненте, может быть много ключей.
  • Анализ исходного кода 2: Метод выполнения, patch.js — patchVnode()

    • patchVnode - это место, где происходит различие, общая стратегия: сравнение в глубину, на одном уровне.
  • Анализ исходного кода 3: Эффективность, patch.js - updateChildren()

Тестовый код:

<!DOCTYPE html>
<html>

<head>
    <title>Vue源码剖析</title>
    <script src="../../dist/vue.js"></script>
</head>

<body>
    <div id="demo">
        <h1>虚拟DOM</h1>
        <p>{{foo}}</p>
    </div>
    <script>
        // 创建实例
        const app = new Vue({
            el: '#demo',
            data: { foo: 'foo' },
            mounted() {
                setTimeout(() => {
                    this.foo = 'fooooo'
                }, 1000);
            }
        });
    </script>
</body>

</html>

Суммировать

1. Алгоритм diff является неизбежным продуктом технологии виртуального DOM: при сравнении старого и нового виртуального DOM (т.е. diff) измененные места обновляются на реальном DOM, кроме того, diff также должен выполнять процесс сравнения эффективно, тем самым снижая временную сложность до O(n).

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

3. Момент выполнения diff в vue — это когда экземпляр компонента выполняет свою функцию обновления, он сравнивает предыдущий результат рендеринга oldVnode и новый результат рендеринга newVnode, этот процесс называется patch.

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

Хотите использовать Vuejs, чтобы ответить на 20 000 популярных вопросов на собеседовании (5) — компонентизация

Расскажите о понимании компонентизации vue?

Чтобы ответить на общую идею:

Приводятся определение, преимущества, сценарии использования и меры предосторожности компонентизации, и следует подчеркнуть некоторые характеристики компонентизации в Vue.

Анализ исходного кода 1: определение компонента

// 组件定义
Vue.component('comp', {
	template: '<div>this is a component</div>'
})

Определение компонента, src\core\global-api\assets.js

<template>
	<div>
        this is a component
    </div>
</template>

vue-loader скомпилирует шаблон в функцию рендеринга, а окончательный экспорт по-прежнему будет объектом конфигурации компонента.

Анализ исходного кода 2: преимущества компонентизации

lifecycle.js - mountComponent()

Отношения между компонентами, наблюдателями, функциями рендеринга и функциями обновления

Анализ исходного кода 3: Компонентная реализация

Конструктор, src\core\global-api\extend.js

Создание экземпляра и монтирование, src\core\vdom\patch.js - createElm()

Суммировать

  1. Компоненты являются независимыми и многократно используемыми единицами организации кода. Система компонентов — одна из основных функций Vue, которая позволяет разработчикам создавать большие приложения с использованием небольших, независимых и часто повторно используемых компонентов;
  2. Компонентная разработка может значительно повысить эффективность разработки приложений, их тестируемость, возможность повторного использования и т. д.;
  3. Использование компонентов подразделяется на: компоненты страницы, бизнес-компоненты, общие компоненты;
  4. Компоненты Vue основаны на конфигурации. Компоненты, которые мы обычно пишем, являются конфигурациями компонентов, а не компонентами. Фреймворк создаст свои конструкторы позже. Они основаны на VueComponent и расширяют Vue;
  5. Общие технологии компонентизации в vue включают в себя: свойство prop, пользовательское событие, слот и т. д., которые в основном используются для взаимодействия компонентов, расширения и т. д.;
  6. Разумное разделение компонентов помогает повысить производительность приложения;
  7. Компоненты должны иметь высокую связность и низкое сцепление;
  8. Следуйте принципу одностороннего потока данных.

Хотите использовать Vuejs, чтобы ответить на 20 000 популярных вопросов на собеседовании (6) — принципы проектирования

Расскажите о своем понимании принципов дизайна vue?

во вьюОфициальный сайтНа ней написаны большие определения и характеристики:

  • Прогрессивная среда JavaScript
  • Простота использования, гибкость и эффективность

Поэтому общее представление об этом вопросе можно расширить в соответствии с этим.

Прогрессивная среда JavaScript:

В отличие от других крупных фреймворков, Vue разработан так, чтобы его можно было применять слой за слоем снизу вверх. Основная библиотека Vue ориентирована только на уровень представления, который не только прост в использовании, но и легко интегрируется со сторонними библиотеками или существующими проектами. С другой стороны, когда ссовременный набор инструментови различныеБиблиотека классов поддержкиВ сочетании Vue также полностью способен работать со сложными одностраничными приложениями.

Простота использования

Vue предоставляет основные функции, такие как реагирование на данные, декларативный синтаксис шаблонов и система компонентов на основе конфигурации. Это позволяет нам сосредоточиться только на основном бизнесе приложения, и мы можем легко писать приложения Vue, пока мы можем писать js, html и css.

гибкость

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

Эффективность

Сверхбыстрый виртуальный DOM и алгоритм сравнения дают нашему приложению наилучшую производительность.

Стремление к эффективности продолжается.Введение Proxy в vue3 для улучшения реагирования на данные и улучшения компиляции статического контента в компиляторе сделает vue более эффективным.

Хотите использовать Vuejs, чтобы ответить на 20 000 популярных вопросов на собеседовании (7) — MVVM

Расскажите о своем понимании MVC, MVP и MVVM?

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

Эпоха Web1.0

В эпоху сети 1.0 нет концепции интерфейса. Разработка веб-приложения в основном написано в ASP.Net/java/php. Проект обычно состоит из нескольких файлов ASPX / JSP / PHP. Каждый файл также содержит HTML, CSS, JavaScript, C # / Java / PHP код. Система в целом схема может выглядеть так:

Преимущество этой архитектуры в том, что она проста и быстра, но недостаток также весьма очевиден: код JSP сложно поддерживать.

Для того, чтобы сделать разработку более удобной, код проще поддерживать, а обязанности переднего и заднего плана четче. Режим и структура разработки MVC являются производными, а внешний интерфейс отображается в виде шаблонов. Типичными фреймворками являются Spring, Structs и Hibernate. Общий каркас показан на рисунке:

Используя эту многоуровневую архитектуру, обязанности ясны, а код прост в обслуживании. Но MVC здесь ограничен back-end, front-end и back-end образуют некое разделение, а front-end только достраивает слой представления в back-end разработке.

Тем не менее, некоторые из тех же шаблонов существуют:

  1. Эффективность разработки front-end страницы не высока
  2. Обязанности переднего и заднего плана неясны

эпоха веб 2.0

С момента появления Gmail технология ajax пользуется популярностью во всем мире. С ajax обязанности фронтенда и бэкенда более ясны. Поскольку интерфейс может взаимодействовать с сервером через Ajax, общая схема архитектуры также изменилась и стала выглядеть следующим образом:

Обмен данными с бэкенд-сервером происходит через ajax, фронтенд-разработчикам нужно разработать только эту часть страницы, а данные может предоставить бэкэнд. Кроме того, ajax может заставить страницу частично обновляться, снижая нагрузку на сервер и потребление трафика, а также улучшая взаимодействие с пользователем. В настоящее время есть штатные фронтенд-инженеры. В то же время интерфейсная библиотека классов также начала медленно развиваться, наиболее известной из которых является jQuery.

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

Эволюция архитектуры после разделения фронтенда и бекенда — MVC, MVP и MVVM

MVC

Интерфейс MVC похож на серверную часть с представлением, контроллером и моделью.

Модель: отвечает за сохранение данных приложения и синхронизацию с внутренними данными.

Контроллер: отвечает за бизнес-логику, изменяет данные модели в соответствии с поведением пользователя.

Представление: Отвечает за отображение представления и визуализацию данных в модели.

Эти трое образуют модель, как показано на рисунке:

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

В реальных сценариях мы склонны видеть другую закономерность, как показано на рисунке:

Этот режим более гибкий в разработке, и фреймворк backbone.js является таким режимом.

Однако такая гибкость может привести к серьезным проблемам:

  1. Поток данных испорчен. Как показано ниже:

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

Пока есть дефекты, будут и изменения. В изменениях внешнего интерфейса кажется, что этот режим MVP отсутствует, потому что AngularJS рано привнес режим фреймворка MVVM во внешний интерфейс. Хотя модель MVP не распространена во фронтенд-разработке, в нативной разработке, такой как Android, разработчики все равно будут ее учитывать.

MVP

MVP очень близок к MVC, P относится к Presenter, а Presenter можно понимать как посредника, который отвечает за поток данных между View и Model, предотвращая прямую связь между View и Model. Можем посмотреть схему

Мы видим, что презентатор отвечает за двустороннее взаимодействие с Моделью и двустороннее взаимодействие с Представлением. Этот метод взаимодействия менее гибкий, чем MVC, и представление становится пассивным представлением и само становится очень маленьким. Хотя он разделяет View и Model. Однако после того, как приложение постепенно становится больше, размер презентера увеличивается, что сложно поддерживать. Для решения этой проблемы, возможно, ответ можно найти в идее MVVM.

MVVM

Прежде всего, что такое MVVM? MVVM можно разложить на (Model-View-VIewModel). ViewModel можно понимать как расширенную версию, основанную на презентаторе. как показано на рисунке:

ViewModel автоматически реагирует на изменения данных в модели, реализуя набор механизмов реагирования на данные;

В то же время Viewmodel будет реализовывать набор стратегий обновления для автоматического преобразования изменений данных в обновления представления;

Измените данные в модели в ответ на взаимодействие с пользователем в представлении посредством прослушивания событий.

Это уменьшает количество кода манипулирования DOM в ViewModel.

Сохраняя слабую связь между представлением и моделью, MVVM также сокращает код для поддержания их взаимосвязи, позволяя пользователям сосредоточиться на бизнес-логике, принимая во внимание эффективность разработки и удобство обслуживания.

Суммировать

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

  • Шаблон MVC появился раньше и в основном использовался в бэкенде, таком как Spring MVC, ASP.NET MVC и т. д., а также на заре фронтенда, таком как Backbone.js. Его преимущества — четкие слои, а недостатки — хаотический поток данных и проблемы с обслуживанием, вызванные гибкостью.

  • Режим MVP является эволюционной формой MVC.Презентатор отвечает за коммуникацию MV в качестве среднего уровня, который решает проблему связи между ними.Однако, если уровень P слишком раздут, это приведет к проблемам с обслуживанием.

  • Шаблон MVVM широко используется во внешнем интерфейсе. Он не только решает проблему связи MV, но также решает большое количество сложных кодов и кодов манипулирования DOM, которые поддерживают отношения отображения между ними. Он повышает эффективность разработки и удобочитаемость при сохранении превосходной производительности.

Хотите использовать Vuejs, чтобы ответить на 20 000 популярных вопросов на собеседовании (8) — оптимизация производительности

Какие методы оптимизации производительности Vue вы знаете?

Варианты ответов: Судя по описанию темы, здесь мы в основном обсуждаем оптимизацию на уровне кода Vue.

  • Отложенная загрузка маршрута

    const router = new VueRouter({
      routes: [
        { path: '/foo', component: () => import('./Foo.vue') }
      ]
    })
    
  • сохранить кэшированные страницы

    <template>
      <div id="app">
        <keep-alive>
          <router-view/>
        </keep-alive>
      </div>
    </template>
    
  • Повторное использование DOM с v-show

    <template>
      <div class="cell">
        <!--这种情况用v-show复用DOM,比v-if效果好-->
        <div v-show="value" class="on">
          <Heavy :n="10000"/>
        </div>
        <section v-show="!value" class="off">
          <Heavy :n="10000"/>
        </section>
      </div>
    </template>
    
    
  • v-для обхода избегайте одновременного использования v-if

    <template>
        <ul>
          <li
            v-for="user in activeUsers"
            :key="user.id">
            {{ user.name }}
          </li>
        </ul>
    </template>
    <script>
    	export default {
            computed: {
              activeUsers: function () {
                return this.users.filter(function (user) {
                 return user.isActive
                })
              }
            }
        }
    </script>
    
    
  • Оптимизация производительности длинного списка

    • Если список чистое отображение данных ничего не изменится, то и делать его отзывчивым не надо

      export default {
        data: () => ({
          users: []
        }),
        async created() {
          const users = await axios.get("/api/users");
          this.users = Object.freeze(users);
        }
      };
      
      
    • Если это длинный список больших данных, виртуальная прокрутка может использоваться для отображения только небольшой части содержимого.

      <recycle-scroller
        class="items"
        :items="items"
        :item-size="24"
      >
        <template v-slot="{ item }">
          <FetchItemView
            :item="item"
            @vote="voteItem(item)"
          />
        </template>
      </recycle-scroller>
      
      

      Ссылаться наvue-virtual-scroller,vue-virtual-scroll-list

  • уничтожение событий

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

    created() {
      this.timer = setInterval(this.refresh, 2000)
    },
    beforeDestroy() {
      clearInterval(this.timer)
    }
    
    
  • Ленивая загрузка изображения

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

    <img v-lazy="/static/img/1.png">
    
    

    Справочный проект:vue-lazyload

  • Сторонние плагины вводятся по запросу

    Сторонние библиотеки компонентов, такие как element-ui, могут быть импортированы по запросу, чтобы избежать громоздкости.

    import Vue from 'vue';
    import { Button, Select } from 'element-ui';
    
     Vue.use(Button)
     Vue.use(Select)
    
    
  • Компоненты без состояния помечены как функциональные компоненты

    <template functional>
      <div class="cell">
        <div v-if="props.value" class="on"></div>
        <section v-else class="off"></section>
      </div>
    </template>
    
    <script>
    export default {
      props: ['value']
    }
    </script>
    
    
  • Сегментация подкомпонентов

    <template>
      <div>
        <ChildComp/>
      </div>
    </template>
    
    <script>
    export default {
      components: {
        ChildComp: {
          methods: {
            heavy () { /* 耗时任务 */ }
          },
          render (h) {
            return h('div', this.heavy())
          }
        }
      }
    }
    </script>
    
    
  • переменная локализация

    <template>
      <div :style="{ opacity: start / 300 }">
        {{ result }}
      </div>
    </template>
    
    <script>
    import { heavy } from '@/utils'
    
    export default {
      props: ['start'],
      computed: {
        base () { return 42 },
        result () {
          const base = this.base // 不要频繁引用this.base
          let result = this.start
          for (let i = 0; i < 1000; i++) {
            result += heavy(base)
          }
          return result
        }
      }
    }
    </script>
    
    
  • SSR

Хотите использовать Vuejs, чтобы ответить на 20 000 популярных вопросов на собеседовании (9) — Vue3.0

Знаете ли вы что-нибудь о новых функциях Vue3.0?

Согласно резюме Youda PPT, улучшения Vue3.0 в основном заключаются в следующих пунктах:

  • Быстрее
    • Переписать виртуальный DOM
    • Оптимизируйте генерацию слотов
    • повышение статического дерева
    • Продвижение статической недвижимости
    • Реактивная система на основе прокси
  • Меньше: Оптимизируйте размер основной библиотеки за счет встряхивания дерева.
  • Легче поддерживать: TypeScript + модульность
  • более дружелюбный
    • Кроссплатформенность: ядро ​​компилятора и ядро ​​среды выполнения не зависят от платформы, что упрощает использование Vue на любой платформе (Интернет, Android, iOS).
  • проще в использовании
    • Улучшенная поддержка TypeScript, редактор обеспечивает мощную проверку типов, ошибки и предупреждения.
    • Улучшенная поддержка отладки
    • Автономный адаптивный модуль
    • Composition API

Переписать виртуальный DOM

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

Быстрый путь компонента + одиночный вызов + обнаружение типа дочернего узла

  • пропускать ненужные условные ветки
  • JS-движок легче оптимизировать

Оптимизация генерации слотов

Родительский и дочерний элементы могут быть перерисованы отдельно в vue3.

  • Убедитесь, что экземпляр правильно отслеживает зависимости
  • Избегайте ненужного повторного рендеринга родительских и дочерних компонентов

Подъем статического дерева

При статическом подъеме дерева это означает, что компилятор Vue 3 сможет определить, что является статическим, а затем поднять его, снизив затраты на рендеринг.

  • Пропускает исправление всего дерева, что снижает затраты на рендеринг
  • Работает нормально даже с несколькими вхождениями

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

640?wx_fmt=jpeg

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

Реактивная система Vue 2 использует геттеры и сеттеры Object.defineProperty. Vue 3 будет использовать ES2015 Proxy в качестве механизма наблюдения, что принесет следующие изменения:

  • Инициализация экземпляра компонента на 100% быстрее
  • Использование прокси экономит половину прежних накладных расходов на память и ускоряет скорость, но есть несовместимость с младшими версиями браузера.
  • Чтобы продолжить поддержку IE11, Vue 3 выпустит сборку, которая поддерживает старый механизм наблюдения и новую версию прокси.

640?wx_fmt=jpeg

Высокая ремонтопригодность

Vue 3 принесет более удобный исходный код. Он не только будет использовать TypeScript, но и многие пакеты будут развязаны и более модульны.

Заключительная речь

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

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

Прошлые рекомендации:

Хотите использовать Vuejs, чтобы ответить на 20 000 популярных вопросов на собеседовании (1) v-if

Используйте vue+node для создания внешней системы мониторинга исключений.

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