# Theme 组件的 j/s 执行顺序由什么控制？

**URL:** <https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410>\
**Category:** Development\
**Created:** [2021年五月14日 12:17 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410 "2021-05-14T12:17:05Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![craigconstantine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/craigconstantine/32/511195_2.png) [@craigconstantine](https://meta.discourse.org/u/craigconstantine)\
**Post date:** [2021年五月14日 12:17 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/1 "2021-05-14T12:17:05Z")

</div>

我的主题中包含 JavaScript（我是不是已经臭名昭著了？`;)`），它通过 `api.decorateCooked(…` 修改 DOM，动态添加元素。它会插入各种 HTML head 元素。

我还安装了 DiscoTOC 主题组件。

然而，添加 DiscoTOC 能识别并展开的常规 `<div data-theme-toc="true"></div>` 后，生成的目录并不包含我动态插入的元素。

我猜测这可能只是执行顺序的问题……如果 DiscoTOC 在我通过 JavaScript 添加更多元素之前就进行了处理……

当多个主题 JavaScript 代码片段都调用 `api.cooked(` 时，执行顺序是由什么决定的？

---

<div class="post-metadata">

**Author:** ![craigconstantine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/craigconstantine/32/511195_2.png) [@craigconstantine](https://meta.discourse.org/u/craigconstantine)\
**Post date:** [2021年五月26日 13:57 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/2 "2021-05-26T13:57:49Z")

</div>

顶一下？🙂

再加一点无厘头内容凑够 20 个字符

---

<div class="post-metadata">

**Author:** ![riking](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/riking/32/170938_2.png) [@riking](https://meta.discourse.org/u/riking)\
**Post date:** [2021年五月26日 14:19 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/3 "2021-05-26T14:19:31Z")

</div>

请注意，DiscoTOC 仅在帖子内容中运行——如果您在帖子外部插入这些元素，它将无法检测到它们。

我认为我们尚未需要定义 JS 的执行顺序。

---

<div class="post-metadata">

**Author:** ![craigconstantine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/craigconstantine/32/511195_2.png) [@craigconstantine](https://meta.discourse.org/u/craigconstantine)\
**Post date:** [2021年五月26日 16:00 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/4 "2021-05-26T16:00:18Z")

</div>

我是在帖子内部插入的，没错。所以我怀疑是执行顺序的问题。

有一段代码决定了执行顺序……这就是我让组件在目录（TOC）之前加载的关键点。例如，如果是按组件名称的字母顺序排列（即管理后台组件列表中显示的顺序），那我就可以尝试相应地命名我的组件，以此类推。

---

<div class="post-metadata">

**Author:** ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)\
**Post date:** [2021年五月26日 16:59 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/5 "2021-05-26T16:59:52Z")

</div>

我很确定组件的执行顺序[并非基于组件名称](https://meta.discourse.org/t/theme-component-order-of-precedence/156615/5?u=johani)。默认情况下，它是基于 ID 的。

不过，对于高级用例，你_确实_可以设置初始化器的顺序。我可以将 DiscoTOC 放入一个命名的初始化器中，这样你就可以在 DiscoTOC 之前运行你的代码。但首先我需要了解你想做什么，才能给你一个明确的答复。

> [@craigconstantine](#):
>
> 通过添加元素来修改 DOM

你这里的修改是基于 HTTP/AJAX 请求，对吗？

---

<div class="post-metadata">

**Author:** ![craigconstantine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/craigconstantine/32/511195_2.png) [@craigconstantine](https://meta.discourse.org/u/craigconstantine)\
**Post date:** [2021年五月26日 17:16 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/6 "2021-05-26T17:16:59Z")

</div>

是的，使用 AJAX，但采用的是同步调用。（我一直很喜欢“同步 AJAX”这个自相矛盾的说法 `:^)`

我觉得下一步是创建一个真正的组件——目前它只是被我粘贴到主题头部的一些 JavaScript 代码。然后我可以尝试调整一个精心挑选的 ID。“\_foo”或"0-foo”可能就足够了。

---

<div class="post-metadata">

**Author:** ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)\
**Post date:** [2021年五月26日 17:49 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/7 "2021-05-26T17:49:35Z")

</div>

> [@craigconstantine](#):
>
> （我一直很喜欢“同步 AJAX"这个矛盾修辞法 :^））

谁说不是呢 😉

> [@craigconstantine](#):
>
> 我觉得我下一步应该是创建一个真正的组件。

没错。如果你想使用具名初始化器和初始化顺序，你的组件需要在 `/javascript` 文件夹中拥有一个初始化器。

不过别担心，我可以帮你搞定所有这些。我明天会给你一个完整的答复。

---

<div class="post-metadata">

**Author:** ![craigconstantine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/craigconstantine/32/511195_2.png) [@craigconstantine](https://meta.discourse.org/u/craigconstantine)\
**Post date:** [2021年十二月27日 14:02 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/9 "2021-12-27T14:02:35Z")

</div>

不久前，我将我的 j/s 破解改造成了一个主题组件。

> **[GitHub - Umbrella-CAST/discourse-umbrella-connector: Discourse theme component for manipulating inline...](https://github.com/Umbrella-CAST/discourse-umbrella-connector)**
>
> Discourse theme component for manipulating inline content via AJAX connections to extern servers.

我很想回到让我的组件在 Discourse table-of-contents 之前运行的排序问题上。

---

<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:** [2021年十二月27日 16:20 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/10 "2021-12-27T16:20:28Z")

</div>

我记得，主题组件是在插件之后进行评估的。

可能记错了，但它们是按名称顺序加载的，所以在名称前加上 `x-` 过去曾帮助我确保特定的主题组件最后被评估。

---

<div class="post-metadata">

**Author:** ![craigconstantine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/craigconstantine/32/511195_2.png) [@craigconstantine](https://meta.discourse.org/u/craigconstantine)\
**Post date:** [2021年十二月27日 16:38 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/11 "2021-12-27T16:38:05Z")

</div>

> [@merefield](#):
>
> iirc，主题组件是在插件 _之后_ 进行评估的。

没关系。我正在尝试调整 DiscoTOC（[https://github.com/discourse/DiscoTOC.git](https://github.com/discourse/DiscoTOC.git)）组件和我自己创建的组件的顺序。

> [@merefield](#):
>
> 而且我可能错了，但它们是按名称顺序加载的，所以在名称前面加上 `x-` 在过去曾帮助我确保特定的主题组件最后被评估。

其他人的回复表明组件的\_名称\_不会影响执行顺序。我刚刚将它们重命名为 aa-mycomponent 和 x-last-DiscoTOC，但它不起作用。[DiscoTOC 不包括动态添加到 DOM 的标题——是的，在帖子正文中]

[https://forum.moversmindset.com/t/list-of-movers-mindset-podcast-episodes/1160](https://forum.moversmindset.com/t/list-of-movers-mindset-podcast-episodes/1160)

@Johani 从你五月份的思路中还有其他想法吗？

---

<div class="post-metadata">

**Author:** ![craigconstantine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/craigconstantine/32/511195_2.png) [@craigconstantine](https://meta.discourse.org/u/craigconstantine)\
**Post date:** [2021年十二月27日 16:40 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/12 "2021-12-27T16:40:34Z")

</div>

hmmmmmmm… 也许问题不仅仅是排序。我刚刚检查了一下……我以为是 HTML 标题的东西在 DOM 中实际上是带有 `class=\"d-toc-ignore\"` 的 DIV 标签。

是时候深入挖掘了。我的 _标题_ 去哪儿了？ 🙂

---

<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:** [2021年十二月27日 16:49 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/13 "2021-12-27T16:49:36Z")

</div>

> [@craigconstantine](#):
>
> 其他人的回复建议组件的_名称_不影响执行顺序

嗯，我认为你可以通过尝试一个非常简单的例子来证明这一点。

创建两个简单的组件，覆盖或连接同一个东西，也许是一个带有细微差别的简单模板，给其中一个起一个字母表中靠后的名字，注意哪个组件最终会覆盖主题。

这里的代码非常清楚地按名称排序：

> <https://github.com/discourse/discourse/blob/d91d67a442a1223e44772bd339c2ffc9d901b3b4/app/models/theme.rb#L21>

---

<div class="post-metadata">

**Author:** ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)\
**Post date:** [2021年十二月27日 18:32 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/14 "2021-12-27T18:32:02Z")

</div>

名称不影响执行顺序。@merefield 您链接的行会影响它们在管理员 UI 中的显示方式，但并不用于实际执行。

这是与执行顺序相关的行：

> <https://github.com/discourse/discourse/blob/3ca1b17589f22c7ad3ae0e1e30df5d9fa4033d7b/app/models/theme.rb#L231-L231>

因此，它们将按数据库中“id”的升序执行。

在 Discourse 实例之间可移植的唯一保证是， **主题** 代码始终在主题 **组件** 代码之前执行。

正如 @Johani 在上面提到的，如果您需要在使用其他组件加载后运行代码，最好的方法可能是使用 Ember initializer，它[支持排序](https://guides.emberjs.com/release/applications/initializers/#toc_specifying-initializer-order)。不幸的是，在这种情况下，这可能无法立即实现，因为 DiscoTOC 似乎没有使用 Ember initializer。将 DiscoTOC 更新为使用[多文件 JavaScript](https://meta.discourse.org/t/splitting-up-theme-javascript-into-multiple-files/119369)（因此是 Ember initializer）当然是 #pr-welcome。

---

<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:** [2021年十二月27日 19:16 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/15 "2021-12-27T19:16:49Z")

</div>

这很不幸，因为它可能很有用。无论如何，感谢您的澄清！

---

<div class="post-metadata">

**Author:** ![craigconstantine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/craigconstantine/32/511195_2.png) [@craigconstantine](https://meta.discourse.org/u/craigconstantine)\
**Post date:** [2022年二月2日 14:26 UTC](https://meta.discourse.org/t/what-controls-the-order-of-execution-for-theme-components-j-s/190410/16 "2022-02-02T14:26:40Z")

</div>

（……这与 [Theme component order of precedence](https://meta.discourse.org/t/theme-component-order-of-precedence/156615) 相关）

只是回来再说一下，数据库 ID 的优先级确实有效；解决了我的需求。谢谢大家！
