Vue: Перехватчики жизненного цикла асинхронных компонентов Await

Созданный на 8 дек. 2017  ·  51Комментарии  ·  Источник: vuejs/vue

Какую проблему решает эта функция?

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

Как выглядит предлагаемый API?

API не меняется; только то, как это работает сейчас, ожидая асинхронных хуков.

Самый полезный комментарий

Это фактический код, которого я хочу дождаться:

  beforeMount: async function() {
       this.user = await client.get({type: 'user', id: this.$route.params.id});
    }

Что будет частью компонента UserPage .

Все 51 Комментарий

Так ты хочешь

created () {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log('created')
            resolve()
        })
    })
},
mounted () {
    console.log('mounted')
}

для отображения

mounted

?

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

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

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

@posva Разобрался - извиняюсь. Мой фактический вариант использования - это тот, где у меня есть компонент UserPage который получает user_id из параметров маршрута страницы (через this.$route.params ), а затем извлекает фактические данные пользователя из базы данных. на сервере с помощью такой команды:
this.user = await client.get({type: 'user', id: this.$route.params.id})
где this.user относится к полю user в части data компонента UserPage .

В идеале я хочу, чтобы эта строка кода выполнялась после создания компонента (чтобы было доступно this.$route.params ), но до фактического монтирования компонента, чтобы в моем шаблоне я мог безопасно использовать user interpolations без ошибок о неопределенных значениях.

@ yyx990803
Я мог бы быть здесь новичком, но не должно ли единственное изменение заключаться в добавлении ключевого слова await перед вызовом хуков жизненного цикла, таких как mounted и т. Д., Во Vue land?

Это фактический код, которого я хочу дождаться:

  beforeMount: async function() {
       this.user = await client.get({type: 'user', id: this.$route.params.id});
    }

Что будет частью компонента UserPage .

Не стоит беспокоиться! Я представлял себе этот вариант использования. Лучше обрабатывать его, как описано в документации vue-router, поскольку он открывает разные способы отображения состояния загрузки. Вы уже можете дождаться появления данных перед рендерингом компонента btw.

ОК, это имеет смысл. Теперь, однако, что, если у меня есть пользовательский компонент, который представляет собой урезанную версию пользовательской страницы (скажем, как компонент, который появляется, когда вы наводите курсор на имя пользователя в facebook и "заглядываете" в его профиль), тогда маршрутизатор здесь не участвует, и id будет передано как свойство компоненту.

Если взять здесь общую картину, функции в JavaScript теперь могут быть синхронными или асинхронными, и эти перехватчики жизненного цикла, являющиеся функциями, и то, как мы думаем о них как о функциях, должны поддерживать асинхронность (как продемонстрировано моим вариантом использования и интуитивно понятным "охватом"). для подхода, который я использую здесь).

У вас есть много способов сделать это. Самый простой - использовать переменную, которая начинается как null, получать данные и устанавливать их, переключая фактический компонент (из-за v-if). Более экзотической версией будет функция, которая разрешает компонент и использует <component :is="myDynamicComp"/> 😄
Но, пожалуйста, не превращайте проблему в вопрос 😉 используйте для этого форум или Discord

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

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

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

MainPage.vue - мой основной контейнер. Я вызываю ajax "/ init" в beforeCreate чтобы получить информацию о пользователе, а затем фиксирую его в Vuex.store.
Content.vue - это дочерний элемент внутри MainPage.vue . Я хотел бы вызывать разные вызовы api на этапе mounted соответствии с ролью пользователя, которые поступают из Vuex.store.

Если жизненный цикл вызывается в потоке async / await, он будет следовать порядку
Parent beforeCreate -> Parent create -> Child beforeCreate -> Child create -> Child установлен .... (Если я правильно понимаю жизненный цикл компонента).

Но в настоящее время я не могу получить информацию о пользователе по адресу Content.vue , как я могу найти временное решение?
Я хотел бы, чтобы api "/ init" вызывали внутри MainPage.vue потому что он используется на многих страницах (контейнер в Vue-Router).

опубликовал вопрос о stackoverflow

Спасибо

Хакерский обходной путь того, что стоит:

{
  created: function(){
    this.waitData = asyncCall();
  },
  mounted: function(){
    this.waitData.then(function(data) { ... })
  }
}


Возможное более «плоское» решение:

{
    async created () {
        let createdResolve = null
        let createdReject = null
        this.createdPromise = new Promise(function(resolve, reject){
            createdResolve = resolve
            createdReject = reject
        })
        await asyncCall1()
        await asyncCall2()
        ...
        createdResolve(someResult)
    }
    async mounted () {
        let result = await this.createdPromise
        ...
    }
    data () {
        return {
            createdPromise: null
        }
    }
}

Разве это еще не так?

data() {
 ...
},
async created() {
  const something = await exampleMethod();
  console.log(something);
}

Работает для меня (как упоминает @fifman ).

@breadadams Да, конечно. Функции _внутри_ метода created будут ожидать, но сама функция created или mounted - нет.

Таким образом, экземпляр Vue вызовет created и мгновенно mounted до того, как любой из длительно запущенных процессов в created будет завершен.

Ах , мой плохой @ darren-dev - другой вариант использования с моей стороны, но теперь я вижу проблему 😅 спасибо за разъяснения.

@breadadams Никаких проблем - мы все здесь, чтобы

Перехватчик жизненного цикла async может быть хорошей реализацией в следующей основной версии

Мне кажется, что разрешение асинхронной поддержки методов жизненного цикла по умолчанию будет поощрять плохие практики UX. Как? Асинхронные функции используются для запросов, которые не могут быть выполнены немедленно (например, длительные или сетевые запросы). Принуждение Vue к отложенному созданию или монтированию или любому из других методов жизненного цикла для ожидания вашего сетевого запроса или длительного асинхронного процесса заметно повлияет на пользователя. Представьте, что пользователь заходит на ваш сайт, а затем ему приходится ждать 4 секунды с пустым экраном, в то время как компонент ждет, пока соединение с пятнистой ячейкой пользователя завершит ваш сетевой запрос. И это не только негативно влияет на пользователя, но и вы жертвуете своим контролем над ситуацией - вы как разработчик ничего не можете сделать, чтобы ускорить воспринимаемое пользователем время загрузки или показать определенные или неопределенные индикаторы прогресса. Таким образом, встроив эту возможность в Vue, вы не сделаете Интернет лучше; вы допускаете плохие практики.

Намного лучше спланировать и спроектировать асинхронный случай с самого начала: запустите асинхронный процесс в created или mounted или где-нибудь еще, а затем сделайте свой компонент каркасной структурой или в худшем случае счетчик, пока вы ждете, пока ваш API не вернет разрешения пользователя. Намного лучший UX, и вы не жертвуете никаким контролем. И Vue не нужно добавлять код для работы с асинхронными функциями жизненного цикла, сохраняя размер пакета меньше. Победа - победа.

@seanfisher Вы поднимаете

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


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

Буквально, единственный раз, когда я (начиная с раннего Vue) подключался к created, был, когда мне приходилось вводить что-то, на что нужно полагаться vue - это не имело ничего общего с настройкой или макетом моей страницы. Тем не менее, мне пришлось ждать выполнения (коротких) асинхронных задач, которые были бы намного лучше _до_ отображения страницы (например, подключение к методам аутентификации Firebase). Наличие этого в create, а затем ожидание его завершения перед установкой полностью уменьшит потребность в хитрых обходных решениях.

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

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

Гм ... Фреймворки созданы для того, чтобы специально ограничивать, направлять или «ограничивать» разработчика определенными шаблонами и практиками проектирования. Это их основная цель. Любой хороший фреймворк будет предлагать интеллектуальный API, который точно предлагает ясный и очевидный способ работы с фреймворком, но при этом он будет ограничивать.

Да, это парадоксально, но фреймворк предлагает определенные возможности, но в то же время ограничивает разработчика определенными методами проектирования. Именно здесь мнение в рамках Frameworks может либо помочь, либо навредить. Трудно найти правильный баланс, и я думаю, что Vue или, скорее, Эван и команда разработчиков Vue проделали и отлично справляются со своими суждениями.

Скотт

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

Но вы не затронули _фактический_ аргумент о том, что созданные и смонтированные события асинхронны - вы просто добавили свое мнение (которое не является неправильным) на мое мнение, что обычно приводит к огромному провалу.

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

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

Я думал, что моя поговорка «Эван и Ко делает здравый смысл» покажет мое мнение. Но, чтобы быть более ясным. Подключенные и созданные хуки жизненного цикла не обязательно должны работать асинхронно или, скорее, тот факт, что они работают синхронно, помогает понять логику приложения. Любое «ожидание» в любом случае необходимо учитывать в пользовательском интерфейсе, и асинхронный код по-прежнему может выполняться в каждой ловушке. Теперь можно спорить о том, что необходимы крючки beforeMount и mount. Но может быть что-то, что вам может понадобиться, например, в смонтированном, к которому вы еще не можете получить доступ в created, например, скомпилированная функция рендеринга.

Скотт

Если у Vue есть какое-то мнение относительно хуков жизненного цикла async, это не должно быть предметом спекуляций. Нет необходимости строить догадки, когда стандарты, API, руководства и лучшие практики, которые Vue принимает, предоставляет или рекомендует, доступны для чтения всем.

В исходном ответе Эвана крючки жизненного цикла async отсутствуют в стандартном API не потому, что это обязательно плохая идея, а потому, что преимущества недостаточно существенны, чтобы оправдать затраты на реализацию.

Для мнения о том, что заставлять пользователя ждать async created или другого хука жизненного цикла без индикатора того, что что-то происходит, - плохая практика, можно привести аргумент, что Vue, поддерживающий асинхронные хуки, теперь, возможно, предоставляет что-то, что можно было бы назвать «фазовыми шаблонами», что также решило бы проблему (и что можно было бы легко реализовать).

Для мнения о том, что заставлять пользователя ждать создания async или другого хука жизненного цикла без индикатора того, что что-то происходит, - плохая практика,

Неужели это вообще проблема?

Скотт

Вот проблема, с которой я столкнулся - и, возможно, кто-то может подсказать, как мне СЛЕДУЕТ делать это, потому что это кажется проблематичным.

Наше приложение Vue (довольно большое) широко использует Vuex. Во многих наших компонентах Vue в жизненном цикле create () мы устанавливаем через store.dispatch () некоторые элементы в магазине (очевидно). Однако, как я заметил, store.dispatch () ВСЕГДА возвращает обещание ... даже если базовая логика и функция НЕ являются асинхронными. Поэтому я ввел async created () {await store.dispatch ('foo / action')}, но, как уже отмечалось, на самом деле не работает ..

Я также использую Typescript, и он довольно горько жалуется, когда я не жду /. Затем вызывает store.dispatch () ... имея "плавающие" обещания ..

Итак, как лучше всего использовать Vuex store.dispatch () в жизненном цикле, когда мы не можем их асинхронизировать?

Ваше здоровье!!

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

Я смотрю на «более плоское» решение @fifman выше, и я не уверен, что оно решит для меня проблему, которая гарантирует, что я загрузил свой XHR к моменту возврата mounted() . В этом решении и created() и mounted() являются асинхронными, поэтому Vue вызовет каждый из них, и они вернутся более или менее немедленно, а асинхронный материал будет выполняться в фоновом режиме. На самом деле, я не уверен, что это лучше, чем просто покончить с createdPromise и просто выполнить всю асинхронную работу в created() или mounted() , например:

async mounted() {
  let response = await fetch(my_url)
  let data = await response.text()
  my_data_member = data
}

В любом случае my_data_member будет заполнено «позже», когда XHR завершится, спустя много времени после того, как mounted() вернет свое обещание, верно?

Вы также можете попробовать использовать v-if в корневом компоненте <div id="app"/> и запустить его, когда загрузка ваших данных завершится. Я, например, использую его для токена обновления.

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

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

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

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

@cederron просто из интереса, почему вы не можете загрузить данные в родительский компонент и передать их как опору? используйте v-if чтобы показать индикатор загрузки во время загрузки данных, и когда данные появятся, вы можете показать компонент, и когда он будет создан, он будет иметь все необходимые данные.

Избегает того, чтобы компонент представлял два разных несвязанных состояния («данные не загружены, ожидание» и «данные были загружены, вы можете ими манипулировать»)

Если вам нужно повторно использовать логику в нескольких местах, возможно, даже переместить логику загрузки на Vuex, это имеет смысл, поскольку загрузка данных будет происходить в действии Vuex, а не в компоненте.

@ReinisV Я думаю, что я слишком упростил свой случай, компонент создает новые данные из данных, полученных с помощью подключенного хука mixin, и представление компонента привязано к этим новым данным.
Итак, миксин должен получать данные из базы данных> компонент создает данные из него> теперь компонент отображается

AFAIK это не сработает:

export const MyMixin = {
    data: function () {
        return {
            dbData: null
        }
    },
   mounted:  async function () {
      this.dbData = await asyncFetchDataFromDB()
   }
}


export const MyComponent = {
    mixins: [MyMixin],
    data: function () {
        return {
            newData: null
        }
    },
   mounted:  function () {
      this.newData = handleDBData(this.dbData)
   }
}

dbData будет нулевым в обработчике монтирования компонента.

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

Ничего не могу сказать о vuex, так как я его не использую

Я действительно хочу повторить то, что здесь упомянул @seanfisher . Наличие vue wait для компонентов, которые были помечены как асинхронные, не только вызывает проблемы для пользователей, но и повсюду присутствует шаблон использования async / await для запуска поиска данных. Это привело бы к явному преобразованию кода в этих хуках жизненного цикла в неожиданные обещания, чтобы явно избежать блокировки vue. В некоторых случаях это могло бы быть хорошо, и если бы функция была представлена, мне пришлось бы предложить запускать два жизненных цикла одновременно: текущий, который обрабатывает выполнение перехватчиков компонентов, и тот, который ожидает этих выполнений для глобальных обратных вызовов.

Но я действительно был бы разочарован, если бы буквально переписал каждый из моих хуков жизненного цикла, чтобы избежать блокировки vue, async/await намного чище, поэтому мы не используем обещания. Изменение этого не обратно совместимым способом меняет яму успеха (непредвиденный жизненный цикл компонента) на яму неудач.

Намного лучше спланировать и спроектировать асинхронный случай с самого начала: запустите асинхронный процесс в created или mounted или где-нибудь еще, а затем сделайте свой компонент каркасной структурой или в худшем случае счетчик, пока вы ждете, пока ваш API не вернет разрешения пользователя. Намного лучший UX, и вы не жертвуете никаким контролем. И Vue не нужно добавлять код для работы с асинхронными функциями жизненного цикла, сохраняя размер пакета меньше. Победа - победа.

@seanfisher Спасибо, это очень полезно!

Почему бы вместо этого не использовать асинхронный компонент, который будет отображаться только после возврата асинхронных вызовов?
подробнее об API здесь
https://vuejs.org/v2/guide/components-dynamic-async.html#Async -Components

new Vue({
  components: {
    root: () => ({ // Aync component
      // The component to load (should be a Promise)
      component: new Promise(async function (resolve) {
        await FetchMyVariables()
        resolve(MyComponent) // MyComponent will be rendered only when FetchMyVariables has returned
      }),
      // A component to use while the async component is loading
      loading: { render: (h) => h('div', 'loading') }, 
    })
  },
  render: h => h('root')
})

Хотя большинство этих решений кажутся хорошими, я думаю, что это одна из тех основных недостающих частей Vue, которые делают его настолько интуитивно понятным. Я думаю, что Vue 3 должен реализовать это, поскольку мы подошли к тому моменту, когда использование async await теперь стало повседневной вещью. ТАК, ПОЖАЛУЙСТА, @ yyx990803 Давай , пусть это будет в Vue 3. PLEEEEEEEASE. Вся архитектура VUE была создана без допущений к этим случаям, и большинство вещей, которые люди публикуют здесь, являются просто обходными путями и хакерскими действиями. Я думаю, что хуки действительно должны уважать асинхронные функции, а также ожидать возвращаемых значений, которые затем передаются следующей функции хуков.

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

Мне кажется, что разрешение асинхронной поддержки методов жизненного цикла по умолчанию будет поощрять плохие практики UX. Как? Асинхронные функции используются для запросов, которые не могут быть выполнены немедленно (например, длительные или сетевые запросы). Принуждение Vue к отложенному созданию или монтированию или любому из других методов жизненного цикла для ожидания вашего сетевого запроса или длительного асинхронного процесса заметно повлияет на пользователя. Представьте, что пользователь заходит на ваш сайт, а затем ему приходится ждать 4 секунды с пустым экраном, в то время как компонент ждет, пока соединение с пятнистой ячейкой пользователя завершит ваш сетевой запрос. И это не только негативно влияет на пользователя, но и вы жертвуете своим контролем над ситуацией - вы как разработчик ничего не можете сделать, чтобы ускорить воспринимаемое пользователем время загрузки или показать определенные или неопределенные индикаторы прогресса. Таким образом, встроив эту возможность в Vue, вы не сделаете Интернет лучше; вы допускаете плохие практики.

Намного лучше спланировать и спроектировать асинхронный случай с самого начала: запустите асинхронный процесс в created или mounted или где-нибудь еще, а затем сделайте свой компонент каркасной структурой или в худшем случае счетчик, пока вы ждете, пока ваш API не вернет разрешения пользователя. Намного лучший UX, и вы не жертвуете никаким контролем. И Vue не нужно добавлять код для работы с асинхронными функциями жизненного цикла, сохраняя размер пакета меньше. Победа - победа.

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

Если фреймворк борется с разработчиком, разработчик найдет другой фреймворк.

@ robob4him

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

Если фреймворк борется с разработчиком, разработчик найдет другой фреймворк.

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

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

Половина возможностей буквально любого фреймворка / языка опасна для разработчика; общедоступные методы могут быть расширены, Vue поощряет доступ к элементу ($ el) и т. д. Фреймворки предоставляют все это, потому что в конце концов разработчик должен выполнить свою работу.

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

Мне нужно использовать requirejs с vue. Не то, чтобы мне нравился requirejs, а потому, что я хочу использовать vue с LMS с открытым исходным кодом, в которой все модули есть как модули AMD. Было бы здорово, если бы я мог загрузить все необходимые библиотеки в ловушку beforeCreate. На данный момент для меня альтернатива - загрузить их вне vue, а затем передать, что более беспорядочно.

Мне кажется, что разрешение асинхронной поддержки методов жизненного цикла по умолчанию будет поощрять плохие практики UX. Как? Асинхронные функции используются для запросов, которые не могут быть выполнены немедленно (например, длительные или сетевые запросы). Принуждение Vue к отложенному созданию или монтированию или любому из других методов жизненного цикла для ожидания вашего сетевого запроса или длительного асинхронного процесса заметно повлияет на пользователя. Представьте, что пользователь заходит на ваш сайт, а затем ему приходится ждать 4 секунды с пустым экраном, в то время как компонент ждет, пока соединение с пятнистой ячейкой пользователя завершит ваш сетевой запрос. И это не только негативно влияет на пользователя, но и вы жертвуете своим контролем над ситуацией - вы как разработчик ничего не можете сделать, чтобы ускорить воспринимаемое пользователем время загрузки или показать определенные или неопределенные индикаторы прогресса. Таким образом, встроив эту возможность в Vue, вы не сделаете Интернет лучше; вы допускаете плохие практики.

Намного лучше спланировать и спроектировать асинхронный случай с самого начала: запустите асинхронный процесс в created или mounted или где-нибудь еще, а затем сделайте свой компонент каркасной структурой или в худшем случае счетчик, пока вы ждете, пока ваш API не вернет разрешения пользователя. Намного лучший UX, и вы не жертвуете никаким контролем. И Vue не нужно добавлять код для работы с асинхронными функциями жизненного цикла, сохраняя размер пакета меньше. Победа - победа.

То, что вы говорите, похоже на то, что добавление v-if/v-clock/v-show функций будет поощрять плохие практики, поэтому мы лучше обезопасим фреймворк, удалив эти функции. Затем используйте какой-то запутанный подход, чтобы сделать то же самое, чтобы Vue был меньше, чтобы не помещать эти 3 директивы. 1-е разработчики не глупы. Вторая защита фреймворка от дурака, в свою очередь, ограничивает его удобство использования, потому что вы ограничиваете то, что можно сделать, основываясь на кажущихся «дураках». Зачем ставить v-if для всего своего веб-сайта, чтобы блокировать его через асинхронные операции, оставляя весь экран пустым?

Я думаю, вы игнорируете тот факт, что в большинстве случаев использования может быть даже не пустая страница. Их не зря называют компонентами . Случаи, когда я лично хочу использовать это, - это когда что-то уже на экране делает что-то еще. Это может быть компонент, заблокированный, например, v-if и срабатывающий, когда что-то изменяется. Однако в процессе его первого рендеринга необходимо учитывать async functions т. Д. При загрузке компонента. Я просмотрел всю документацию Vue в поисках этого и, наконец, сделал это с помощью очень не очень красивого обходного пути, как в вышеприведенных хакерских примерах.

Что меня беспокоит, так это то, что кто-то / даже позже я буду поддерживать код. Это как ад обратного вызова Promise против Async ... Подождите.

На самом деле я вижу, что это улучшает гибкость и управляемость фреймворка, и это легко отслеживать. Просто взгляните на приведенные выше советы, чтобы понять, что я имею в виду. Разработчики делают все это только для того, чтобы заполнить пробел, например, в простой инструкции async mounted () { await... } . Если вы не хотите использовать эти функции, вы просто не определяете функции как async и даже не используете await вообще.

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

@emahuni , я не думаю, что кто-то не согласится с упускается из виду . Предположим, что async mounted или async created задерживают рендеринг компонента. Что в этом случае делает родитель? Является ли:

  • блок также
  • Предположим, что компонент предназначен для удаления DOM v-if до тех пор, пока он не будет загружен
  • Предположим, что компонент должен быть скрыт до завершения загрузки
  • Показать на его месте временный элемент?

Хотя я согласен с тем, что ожидания относительно динамически загружаемого компонента согласованы, я не думаю, что поведение родителя будет таким. В этих случаях это было бы IMO, раскрывающее реализацию дочернего элемента родителю и заставляющее родителя выяснить, что делать с этим динамическим компонентом. Вместо этого то, как загружаются данные, и состояние дочернего компонента должно зависеть от дочернего. Если он загружает async, ему нужно каким-то образом объяснить Vue, что должно отображаться на его месте (или не отображаться). Лучший способ справиться с этим - это то, как фреймворк уже работает, а не вводить новую сложность.

Кроме того, я не полностью следую вашим аргументам:

То, что вы говорите, похоже на то, что добавление функций v-if / v-clock / v-show будет поощрять плохие практики, поэтому мы лучше обезопасим фреймворк, удалив эти функции.

Хотя в этом случае мы ясно видим, что введение асинхронных компонентов, ожидающих монтирования или созданных, приведет к неправильной практике, не совсем ясно, что это так. Во-вторых, напрашивается вопрос: даже если они действительно вызывают плохие практики, мы должны решить их исправить , а не использовать их как оправдание для создания новых плохих практик. Если вы знаете о недобросовестных действиях, создаваемых v-if и т. Д. ... Я приглашаю вас явным образом (в другом выпуске, конечно) рассказать, в чем проблема, вместо того, чтобы пытаться использовать это как оправдание. для другого обсуждения.

@emahuni , я не думаю, что кто-то не согласится с упускается из виду . Предположим, что async mounted или async created задерживают рендеринг компонента. Что в этом случае делает родитель? Является ли:

  • блок также

Родитель может продолжить рендеринг, даже не дожидаясь ребенка, зачем это нужно? Он может пойти дальше и запустить updated после рендеринга дочернего элемента.

  • Предположим, что компонент предназначен для удаления DOM v-if до тех пор, пока он не будет загружен

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

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

Это зависит от разработчика, почему они асинхронизируют смонтированный или какой-либо другой крючок.

  • Показать на его месте временный элемент?

Это может быть совсем не так. Опять же, это зависит от разработчика, чего они намерены достичь. Дело в том, что ничего не должно быть в прямой рубашке. Когда, например, был разработан v-if это было не потому, что они понимали, почему кто-то захочет блокировать рендеринг компонента каждый раз, и что они размещают вместо этого, и защищали это от дурака. Есть много вещей, которые могут пойти не так с v-if за дизайна разработчика. Вам не стоит беспокоиться о том, что будет на экране в это время, это не забота фреймворка.

Хотя я согласен с тем, что ожидания относительно динамически загружаемого компонента согласованы, я не думаю, что поведение родителя будет таким. В этих случаях это было бы IMO, раскрывающее реализацию дочернего элемента родителю и заставляющее родителя выяснить, что делать с этим динамическим компонентом. Вместо этого то, как загружаются данные, и состояние дочернего компонента должно зависеть от дочернего. Если он загружает async, ему нужно каким-то образом объяснить Vue, что должно отображаться на его месте (или не отображаться). Лучший способ справиться с этим - это то, как фреймворк уже работает, а не вводить новую сложность.

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

Кроме того, я не полностью следую вашим аргументам:

То, что вы говорите, похоже на то, что добавление функций v-if / v-clock / v-show будет поощрять плохие практики, поэтому мы лучше обезопасим фреймворк, удалив эти функции.

Хотя в этом случае мы ясно видим, что введение асинхронных компонентов, ожидающих монтирования или созданных, приведет к неправильной практике, не совсем ясно, что это так. Во-вторых, напрашивается вопрос: даже если они действительно вызывают плохие практики, мы должны решить их исправить , а не использовать их как оправдание для создания новых плохих практик. Если вы знаете о недобросовестных действиях, создаваемых v-if и т. Д. ... Я приглашаю вас явным образом (в другом выпуске, конечно) рассказать, в чем проблема, вместо того, чтобы пытаться использовать это в качестве оправдания. для другого обсуждения.

Я просто указал на эти директивы в качестве примера функций, которые могут использоваться неправильно, чтобы заблокировать рендеринг компонента, аналогично тому, что вы говорили о async... . С ними все в порядке. Так должны ли мы удалить эти директивы только потому, что кто-то может использовать «плохие методы» для создания компонентов, которые на минуту показывают пустые страницы? На самом деле вы не видите, чтобы кто-то делал это, потому что этого не происходит, если только вы не пытаетесь привести пример крайнего зла, например, ужасного.

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

Кто-то спросил об этом https://github.com/vuejs/vue/issues/7209#issuecomment -424349370 там, и никто ему не ответил, насколько я видел. Это однозначно свидетельствует о том, что Vue отстает в этой части. Эта часть архитектуры была разработана, когда асинхронность еще не применялась. Так что обновление его для соответствия современным требованиям к современной архитектуре - несомненно, хорошая идея. В противном случае остальное - это хакерские приемы и обходные пути, которые требуют определенных способов решения, а не того, что происходит в отрасли.

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

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

Никогда не говорил об этом, я подчеркиваю, что хочу выполнять асинхронные действия по умолчанию, не блокируя рендеринг компонента. Не интуитивно понятно, что выполнение действий async в блоке mounted или created вызовет задержку рендеринга компонента. Предполагая, что это так, я бы вместо этого увидел, что сложность возникает из-за того, как будет действовать потребитель, которому нужна текущая функциональность. Пока аргумент не в том, что то, о чем просят, невозможно сделать, а в том, что то, о чем просят, должно быть по умолчанию. Вы уже можете заблокировать рендеринг вашего компонента, переключив отображаемый шаблон на основе v-if="loaded" .

Прямо сейчас рендеринг без блокировки кода выглядит так:
Прямо сейчас этот код:

<template>
  <div>  
    <spinner v-if="!loaded">
    <div v-else>
      ....
    </div>
</template>

<script>
  async created() { 
    await this.loadData();
    this.loaded = true;
  }
</script>

И рендеринг с блокировкой выглядит точно так же, поскольку вы не можете фактически блокировать. Предполагая, что async created() действительно заблокировал компонент. Теперь у нас есть разделение кода. Чтобы отобразить счетчик, мы пишем:

<template>
  <div>  
    <spinner v-if="!loaded">
    <div v-else>
      ....
    </div>
</template>

<script>
  created() { 
    this.loadData().then(() => this.loaded = true);
  }
</script>

и просто игнорируем рендеринг компонента на экране, который мы пишем

<template>
  <div>  
    <div>
      ....
    </div>
</template>

<script>
  async created() { 
    await this.loadData();
  }
</script>

Какая польза от добавления этого упрощения для блокировки ордера на рендеринг, что делает невозможность блокировки более сложной? Я просто этого не вижу.

Обработка зависимостей для компонентов

@ yyx990803 Пожалуйста, взгляните на это, это не идеально, но, тем не менее, это сложный сценарий использования.

Хорошо, вот пример использования, который можно было бы элегантно обработать, если бы хуки жизненного цикла имели async ... await:
_Я действительно хотел сделать это в приложении и получил уродливый код для этого. Это очень надуманный пример coz_

Мне нужен компонент A, чтобы дождаться срабатывания крючков mounted компонента B && C перед установкой. Таким образом, компонент A mounted должен ожидать своего хука created , который инициировал установку компонента B && C , ожидающего триггера _ (который на самом деле может что-то сделать до ожидания) _. Дело в том, что так проще и намного чище и интуитивно понятно, поскольку все остается в одном месте для соответствующего компонента.

A излучает событие запуска и прослушивает ответы от B и C _ ( B и C ждут сигнала A перед продолжением, затем выдают события после установки) _ перед продолжением, просто. Это больше похоже на сценарий зависимости для компонентов без каких-либо посторонних данных, разбросанных в другом месте для управления состоянием.

Основной компонент хостинга , все компоненты загружаются вместе, но дождитесь нужных с помощью событий и async ... await. Неважно, что делают эти дети, они сами приказывают.

<template>
  <div>
     ...
     <component-A/>
     <component-B/>
     <component-C/>
     ... other conent
  </div>
</template>
<script>
  import ComponentA...
  ...
  export default {
      components: { ComponentA... }
  }
</script>

Компонент A управляет установкой B и C как зависимостей. Запуск может быть выполнен позже в других хуках или даже через событие UX тех же компонентов. Следующее - просто чтобы продемонстрировать здесь идею.

<template>
  ...
</template>
<script>
  export default {
      async created() {
          // ...do something here before mounting thrusters, even await it
         this.root.$emit('mount-thrusters');
         await Promise.all([
            this.wasMounted('thruster-1-mounted'), 
            this.wasMounted('thruster-2-mounted')
         ]); 
      },
      mounted() {
        // will only run after components B and C have mounted
        ...
      },

     methods: {
       wasMounted(compEvent) {
          return new Promise( (resolve)=>this.root.$once(compEvent, ()=>resolve()));
       }
    }
  }
</script>

компонент B

<template>
  ...
</template>
<script>
  export default {
      async created() {
          // ...do something here, even await it, but happens at the same time as all components
         await new Promise( (resolve)=>this.root.$once('mount-thrusters', ()=>resolve()));
      },
     mounted() {
       this.root.$emit('thruster-1-mounted');
    }
  }
</script>

компонент C

<template>
  ...
</template>
<script>
  export default {
      async created() {
          // ...do something here, even await it, but happens at the same time as all components
         await new Promise( (resolve)=>this.root.$once('mount-thrusters', ()=>resolve()));
      },
     mounted() {
       this.root.$emit('thruster-2-mounted');
    }
  }
</script>

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

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

Это, очевидно, избавляет от излишне сложного и неподдерживаемого кода.

Теперь представьте это в большом приложении с 32 компонентами подруливающего устройства, которые ведут себя по-другому. У вас будет всего около 3 баллов, которые можно уменьшить даже до 2, если вы добавите миксины.

Делать вещи свежими

Конечно, это не ограничивается только монтированием и созданием, но на самом деле должно работать со всеми другими хуками жизненного цикла. Представьте, что это новый блестящий крючок beforeActivate / beforeUpdate . Мы могли бы заставить компонент ждать _активацию / обновление_ и только _активировать / обновлять_, когда обновление выполняется каждый раз, когда компонент _активирован / обновлен_; следя за тем, чтобы вещи оставались свежими.

Список бесконечен, как только это будет реализовано.

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

Никогда не говорил об этом, я подчеркиваю, что хочу выполнять асинхронные действия по умолчанию, не блокируя рендеринг компонента. Не интуитивно понятно, что выполнение действий async в блоке mounted или created вызовет задержку рендеринга компонента. Предполагая, что это так, я бы вместо этого увидел, что сложность возникает из-за того, как будет действовать потребитель, которому нужна текущая функциональность. Пока аргумент не в том, что то, о чем просят, невозможно сделать, а в том, что то, о чем просят, должно быть по умолчанию. Вы уже можете заблокировать рендеринг вашего компонента, переключив отображаемый шаблон на основе v-if="loaded" .

Прямо сейчас рендеринг без блокировки кода выглядит так:
Прямо сейчас этот код:

<template>
  <div>  
    <spinner v-if="!loaded">
    <div v-else>
      ....
    </div>
</template>

<script>
  async created() { 
    await this.loadData();
    this.loaded = true;
  }
</script>

И рендеринг с блокировкой выглядит точно так же, поскольку вы не можете фактически блокировать. Предполагая, что async created() действительно заблокировал компонент. Теперь у нас есть разделение кода. Чтобы отобразить счетчик, мы пишем:

<template>
  <div>  
    <spinner v-if="!loaded">
    <div v-else>
      ....
    </div>
</template>

<script>
  created() { 
    this.loadData().then(() => this.loaded = true);
  }
</script>

и просто игнорируем рендеринг компонента на экране, который мы пишем

<template>
  <div>  
    <div>
      ....
    </div>
</template>

<script>
  async created() { 
    await this.loadData();
  }
</script>

Какая польза от добавления этого упрощения для блокировки ордера на рендеринг, что делает невозможность блокировки более сложной? Я просто этого не вижу.

Это учебный курс по Vue 101, и в нем нет ничего нового ... этого недостаточно, например, для рассмотрения вышеупомянутых случаев. Идея здесь состоит в том, чтобы упростить пользовательскую среду, в которой фактически используется Vue, и упростить анализ кода.

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

Меня это действительно смущает, вместо того, чтобы связывать B и C с A, я бы переместил код так, чтобы «загрузить A» в A.js, а затем попросил A.js обновить «B.data» и «C.data». . Таким образом, если A.data изменяется по какой-либо причине, другие компоненты автоматически перерисовываются, а не пытаются делегировать
управление от одного компонента к другому. Даже в случае общего доступа я бы все равно отделил данные для рендеринга A от компонента A. Мы использовали один класс, который содержит такие методы, как fetchData и hasInitialized, для которых последний является обещанием, а первый разрешает последнее.
Непосредственное связывание компонентов вместе создает неожиданные деревья зависимостей, которые предотвращают повторное использование компонентов и позволяют Vue правильно их повторно отображать.

В качестве альтернативы, я бы даже emit бы событие непосредственно в родительский элемент A, B и C, а не в глобальную область видимости, и позволил бы родителю решить, отображать ли B и C, т.е.

  <template>
    <a-component @rendered="showBandC = true" />
    <b-component v-if="showBandC" />
    <c-component v-if="showBandC" />
  </template>

Что такого особенного в A, что в этом случае нам действительно нужно было бы рендерить перед рендерингом B и C. Если в методе created() , ничто не мешает заполнить хранилище через класс javascript или использовать модуль store . Но более полезен явный вариант использования, т.е. какой UX пользовательской истории не может быть зафиксирован?

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

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

В моем компоненте есть и async beforeMount и async mounted , но код в mounted запускается до того, как код в beforeMount будет завершен. Как мы можем заблокировать mounted от срабатывания до завершения beforeMount ?

Это похоже на исходный запрос, поэтому вопрос, который был задан во втором ответе, я думаю, все еще актуален: https://github.com/vuejs/vue/issues/7209#issuecomment -350284784

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

Есть ли на самом деле допустимый вариант использования необходимости блокировать ранее выполненные хуки жизненного цикла, или правильно ли, чтобы хуки жизненного цикла были синхронными. До сих пор обсуждение носило философский характер (как это обычно бывает при обсуждении хорошей архитектуры), но на самом деле вопрос в том, была ли действительно веская причина для этого. Я ни на секунду не сомневаюсь, что для фреймворка разумно ожидать асинхронного кода. У меня была точная проблема в N других библиотеках, которые не делали этого или не передавали обратный вызов (или передавали обратный вызов, но не передавали обратный вызов в обратный вызов). Однако на самом деле разумно иметь крючок жизненного цикла async, или причины в результате попытки сделать что-то, что «делать не следует»?

То есть, что происходит, когда вы пытаетесь unmount компонент, который еще не закончил быть created , вау, было бы плохо ждать этого еще. Или destroying тот, который еще не закончил быть mounted , я не завидую разработчику этой функциональности.

Меня это действительно смущает, вместо того, чтобы связывать B и C с A, я бы переместил код так, чтобы «загрузить A» в A.js, а затем попросил A.js обновить «B.data» и «C.data». . Таким образом, если A.data изменяется по какой-либо причине, другие компоненты автоматически перерисовываются, а не пытаются делегировать

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

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

Теперь это слишком сильно связывает компоненты. Мы хотим, чтобы они работали друг без друга, за исключением A.

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

На самом деле вы упускаете суть, они слабо связаны в той степени, в которой каждый из них можно использовать и поддерживать, не влияя на другой. Фактически, вы можете отбрасывать любой из них несколько раз в любом месте, не записывая больше кода в родительских элементах, кроме <component-x /> , без v-if , vuex для управления его состоянием или чего-либо еще.

Я соединил их A с B и C, чтобы продемонстрировать, я мог бы красиво разделить это или просто подсчитать, сколько компонентов ответили, а затем продолжить, когда будет достигнуто определенное ожидаемое число (2 в данном случае), например:

 this.$root.$emit('thruster-mounted') // in B and C
// instead of 
 this.$root.$emit('thruster-1-mounted') // for B and 2 for C

// then count the responses and resolve once they are >= 2 in component A

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

В качестве альтернативы, я бы даже emit бы событие непосредственно в родительский элемент A, B и C, а не в глобальную область видимости, и позволил бы родителю решить, отображать ли B и C, т.е.

Я знал, что вы собираетесь это сказать, но это нежелательно. Эти компоненты не должны контролироваться ничем другим, поэтому я подчеркнул, что основной компонент меньше заботится о том, что делают его дети, они должны оставаться независимыми. Я хочу иметь возможность размещать их в любом месте приложения и при этом работать так же . В тот момент, когда вы сделаете то, о чем говорите, посмотрите, как все разваливается на части. Но я могу легко разместить компоненты в любом месте DOM-дерева, даже не вздрогнув, и все будет просто работать. У меня даже может быть несколько копий этого, и он все равно будет работать. Все благодаря async ... await за жизненные циклы.

  <template>
    <a-component @rendered="showBandC = true" />
    <b-component v-if="showBandC" />
    <c-component v-if="showBandC" />
  </template>

Что такого особенного в A, что в этом случае нам действительно нужно было бы рендерить перед рендерингом B и C.

Мы хотим, чтобы каждый компонент выполнял уникальную работу перед установкой. Но все компоненты будут отображаться только тогда, когда все остальные компоненты закончат свою работу. Вот такая вот история.
Так что удачи в управлении состоянием и v-if просто для управления этим, не говоря уже о фактических данных, которые он, вероятно, будет создавать в магазине vuex . У вас будет много дублированного кода, написанного везде, где бы ни использовался компонент. Допустим, у вас есть другой компонент, который содержит только A и C и в другой конфигурации? Вы должны написать эти v-if , управление состоянием vuex, чтобы это работало. Ты видишь проблему? позвольте мне проиллюстрировать:

  // component Z totally different from foo, so we can't make this a component for reuse
  <template>
    <a-component @rendered="showBandC = true" />
    <c-component v-if="showBandC" />
  </template>
 ...
computed: {
showBandB() { ...vuex ...,
showBandC() { ...vuex ...,
}
  // component Foo totally unique, probably has other things it does
  <template>
    <b-component v-if="showBandC" />
    <c-component v-if="showBandC" />
  </template>
 ...
computed: {
// ok you could mixin this, fair, but complex nevertheless
showBandB() { ...vuex ...,
showBandC() { ...vuex ...,
}

..... и так далее

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

  // component Z
  <template>
    <a-component />
    <b-component />
  </template>
  // component Foo
  <template>
    <b-component  />
    <c-component />
  </template>

... и так далее

Если в методе created() , ничто не мешает ему заполнить хранилище через класс javascript или использовать модуль store . Но более полезен явный вариант использования, т.е. какой UX пользовательской истории не может быть зафиксирован?

Помните, что я говорил про повсюду заваленное государственное управление? Мы не хотим, чтобы управление этими компонентами означало, что мы будем управлять многими вещами где-то еще, а это очень сложно вместо того, что я только что сделал. Кроме того, он не будет делать то, что я хочу от этого; монтировать только тогда, когда каждый компонент завершил то, что должен был делать, с очень небольшой сложностью.

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

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

В моем компоненте есть и async beforeMount и async mounted , но код в mounted запускается до того, как код в beforeMount будет завершен. Как мы можем заблокировать mounted от срабатывания до завершения beforeMount ?

Дело в том, что мы хотим, чтобы что-то произошло до рендеринга любого из этих компонентов и чтобы их можно было использовать без особого ввода вне самих компонентов. Это реальная вещь, которую я заметил, я мог бы сделать лучше, если бы это было приложение, которое мы делаем. Я закончил тем, что написал код, который имеет много миксинов, vuex и сильно связанных родителей, везде (с использованием миксинов) компоненты использовались, потому что этого нет. Это не какая-то запутанная история, я просто рассказываю вам, что произошло. Нам пришлось переосмыслить то, как предполагалось разработать и поддерживать пользовательский интерфейс. Он стал немного менее интересным визуально и стал намного сложнее с точки зрения кода.

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

@wparad

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

Это где:

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

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

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

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

Была ли эта страница полезной?
0 / 5 - 0 рейтинги