# Как обойти DOMContentLoaded для навигации?

**URL:** https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748
**Category:** Development
**Created:** [11.Февраль.2025 21:38:15 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748 "2025-02-11T21:38:15Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [11.Февраль.2025 21:38:15 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/1 "2025-02-11T21:38:15Z")

</div>

У нас есть JS-функция, которая выполняется при событии DOMContentLoaded: document.addEventListener(“DOMContentLoaded”, OURFUNCTION).

Это работает корректно при перезагрузке страницы, но не срабатывает при навигации по сайту. Я предполагаю, что это связано с тем, что Discourse загружает DOM только один раз, а дальнейшая навигация обрабатывается на стороне клиента, как в SPA. Поэтому меня интересует, как можно запускать эту функцию при изменении маршрута в самом Discourse? Раньше для этого были простые способы через API плагинов, но эти API устарели, и я больше не вижу их использования в компонентах. Есть ли простой способ сделать это сейчас? Или нам нужно создавать целый компонент только для выполнения JavaScript при смене навигации? Спасибо.

---

<div class="post-metadata">

### Author: ![Arkshine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/arkshine/32/298682_2.png) [@Arkshine](https://meta.discourse.org/u/Arkshine)
#### Post date: [11.Февраль.2025 21:47:54 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/2 "2025-02-11T21:47:54Z")

</div>

Привет,

Если вы ищете событие, срабатывающее при загрузке страницы, обратите внимание на [`api.onPageChange`](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/lib/plugin-api.gjs#L1088).

```js
api.onPageChange((url, title) => {
   console.log('страница изменилась на: ' + url + ' и заголовок ' + title);
});

```

Если вы имели в виду что-то другое, пожалуйста, уточните, чего именно вы хотите добиться. Мы сможем дать более точный ответ.

Кстати, у нас есть множество документов, которые могут вам пригодиться: [Developer Guides - Discourse Meta](https://meta.discourse.org/c/documentation/developer-guides).

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [11.Февраль.2025 22:05:38 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/3 "2025-02-11T22:05:38Z")

</div>

Хм… Я не уверен, что это гарантирует загрузку содержимого DOM. Мне кажется, это событие срабатывает при смене маршрута, что происходит гораздо раньше.

Если загрузка DOM важна, вам стоит рассмотреть возможность прикрепления компонента к плагину-разъему и срабатывания модификатора didInsert.

Если же важно только изменение маршрута, то да, onPageChange должно сработать 👍

---

<div class="post-metadata">

### Author: ![Arkshine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/arkshine/32/298682_2.png) [@Arkshine](https://meta.discourse.org/u/Arkshine)
#### Post date: [11.Февраль.2025 22:31:57 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/4 "2025-02-11T22:31:57Z")

</div>

Возможно, вы правы! 🤔

`onPageChange` вызывается в следующем цикле выполнения, поэтому, думаю, в большинстве случаев он всё равно будет вызван после `DOMContentLoaded`, но я не могу гарантировать это на 100%.

Я вижу случаи использования, когда полагаются на `onPageChange` и сразу работают с элементами DOM. Кстати, откуда именно генерируется событие `routeDidChange` (РЕДАКТИРОВАНО: из Ember: [RouterService | 6.11.0 | Ember API Documentation](https://api.emberjs.com/ember/release/classes/routerservice/events/))?

Согласен с модификатором `didInsert`, действительно здорово!

---

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [11.Февраль.2025 22:55:51 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/5 "2025-02-11T22:55:51Z")

</div>

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

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [11.Февраль.2025 23:18:36 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/6 "2025-02-11T23:18:36Z")

</div>

> [@ddsgad](#):
>
> API плагинов устаревает и скоро будет выведена из употребления

Я не думаю, что это верно.

> [@Using the JS API](https://meta.discourse.org/t/using-the-pluginapi-in-site-customizations/41281?u=merefield):
>
> Discourse’s JavaScript API allows themes and plugins to make extensive customizations to the user experience. The simplest way to use it is to create a new theme from the admin panel, click “Edit Code”, and then head to the JS tab. For file-based themes, the API can be used by creating a file in the api-initializers directory. For theme’s that’s {theme}/javascripts/api-initializers/init-theme.gjs, and for plugins, it’s {plugin}/assets/javascripts/discourse/api-initializers/init-plugin.js. The c…

был обновлён на прошлой неделе.

Что выводится из употребления:

- API виджетов
- Сырые шаблоны
- Переопределение шаблонов в целом

---

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [11.Февраль.2025 23:25:51 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/7 "2025-02-11T23:25:51Z")

</div>

Спасибо за уточнение! Значит, дело только в API виджета. Хорошо, сначала попробую предложенные выше варианты работы с API.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [11.Февраль.2025 23:27:34 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/8 "2025-02-11T23:27:34Z")

</div>

> [@DDSGadget](#):
>
> Это просто API виджета

Это скорее благословение 😅, Glimmer гораздо удобнее для разработчиков.

---

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [12.Февраль.2025 19:26:10 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/9 "2025-02-12T19:26:10Z")

</div>

Кстати, мы протестировали это с помощью api.OnPageChange, и всё работает отлично. У нас пока не было случаев, когда содержимое DOM не было доступно при вызове OnPageChange, поэтому кажется, что событие срабатывает после DomContentLoaded. Но я не могу быть уверен на 100%. Спасибо за помощь в этом вопросе.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [12.Февраль.2025 22:41:36 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/10 "2025-02-12T22:41:36Z")

</div>

Хорошо. Просто имейте в виду, что сроки не гарантируются. Но я рад, что это подходит для вашего случая использования!

---

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [21.Февраль.2025 15:00:11 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/11 "2025-02-21T15:00:11Z")

</div>

> [@Роберт](#):
>
> срабатывание модификатора didInsert при загрузке DOM

Не могли бы вы пояснить, что это означает? Что такое модификатор didInsert? У меня срабатывает событие decorateCookedElement. Спасибо.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [21.Февраль.2025 15:02:22 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/13 "2025-02-21T15:02:22Z")

</div>

> **[Calling Methods On First Render - Template Lifecycle, DOM, and Modifiers -...](https://guides.emberjs.com/release/components/template-lifecycle-dom-and-modifiers/#toc_calling-methods-on-first-render)**
>
> For the most part, you should be able to build Ember applications without directly manipulating the DOM. Before considering directly accessing the DOM, it's always best to first consider whether there's an Ember-native way to accomplish your goal....

---

<div class="post-metadata">

### Author: ![Arkshine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/arkshine/32/298682_2.png) [@Arkshine](https://meta.discourse.org/u/Arkshine)
#### Post date: [21.Февраль.2025 15:03:41 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/14 "2025-02-21T15:03:41Z")

</div>

Документация — лучший вариант, как отметил Роберт; вы также можете найти множество примеров в репозитории: [Code search results · GitHub](https://github.com/search?q=repo%3Adiscourse%2Fdiscourse%20%7B%7BdidInsert&type=code)

---

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [21.Февраль.2025 15:03:45 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/15 "2025-02-21T15:03:45Z")

</div>

> [@DDSGadget](#):
>
> модификатор didInsert

О, понял, так это функция Ember и не связана с Discourse? Единственная часть в коде, которая действительно относится к «Discourse» — это pluginOutlet?

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [21.Февраль.2025 15:16:57 UTC](https://meta.discourse.org/t/how-to-get-around-domcontentloaded-for-navigation/351748/16 "2025-02-21T15:16:57Z")

</div>

Да, это часть стандарта Glimmer

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

> <https://github.com/discourse/discourse/blob/1b5e4b6b0fef9811839490f2ee3b9f31d5fbed3b/app/assets/javascripts/discourse/app/components/plugin-outlet.js#L52>
