自定义属性附加事件为时过早? [英] Custom Attribute attached event too early?

查看:64
本文介绍了自定义属性附加事件为时过早?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自定义组件
我创建了一个用于导航应用程序的自定义组件.它由ul元素组成,并且其所有li元素都是根据路由器的导航列表中的项目动态创建的.这是在组件的附加事件中发生的.没什么特别的.

The custom component
I've created a custom component for the navigation of my app. It consists of an ul element and all its li elements are dynamically created based on the items in the router's navigation list. This is happening in the attached event of the component. Nothing special is going on here.

自定义属性
但是因为我想拥有一个漂亮的菜单,所以我还创建了一个自定义属性,并将其实现到自定义组件的根ul元素中.在自定义属性的attached事件中,我想进行一些dom操作,以使菜单看起来像是那些很酷的孩子创建的菜单.

The custom attribute
But because I want to have a good looking fancy menu I also created a custom attribute and implemented it into the root ul element of the custom component. In the attached event of the custom attribute I'd like to do some dom manipulations so that my menu looks like a menu created by those cool kids.

问题
尽管自定义组件的attached事件之后触发了自定义属性的attached事件,但动态创建的li项尚不属于自定义属性的attached事件中dom的一部分.

The problem
Although the attached event of the custom attribute is fired AFTER the attached event of the custom component, the dynamically created li items are not part of the dom in the attached event of the custom attribute yet.

问题
我的假设是,在attached事件中,实际组件的view都将附加到dom,并且之前的所有组件也都将附加到dom.当我完成attached事件时,还将附加此处动态创建的html.我误会了吗?

The question
My assumption was that on attached event the view of the actual component is attached to dom and that all components before are also attached to the dom. And when I am done with the attached event the html that has been dynamically created here is also attached. Am I mistaken?

旁注
我知道使用TaskQueue可以解决我的问题.但是,我想知道是否首先有其他方法/解决方案,因为我相信及时移动事物可能会导致一系列悖论,使您陷入维护的噩梦.

On a side note
I am aware of using TaskQueue could solve my problem. However, I would like to know if there's a different approach/solution first because I believe that moving things in time could cause a chain of paradoxes leaving you in a maintenance nightmare.

推荐答案

让我消除您对TaskQueue的误解.

Allow me take away your misconception about the TaskQueue.

您及时移动事物导致维护问题的想法肯定适用于使用setTimeout(),因为这会导致实际的延迟,并迫使执行进入下一个事件循环. queueTask()差不多是同一件事(内部使用setTimeout()).

Your idea of moving things in time causing maintenance issues would certainly apply to using setTimeout() because that incurs an actual delay, and forces execution onto the next event loop. queueTask() is more or less the same thing (it uses setTimeout() internally).

但是,TaskQueue的queueMicroTask()方法的工作方式却大不相同.

However, the TaskQueue's queueMicroTask() method works very differently.

当您调用queueMicroTask()时,与queueTask()setTimeout()不同,该任务被安排为在同一事件循环上立即执行.这是一种非常健壮的机制,可以保证执行顺序,通常在进行任何DOM操作之前在attached()中使用它都是一种好习惯.

When you call queueMicroTask(), unlike queueTask() and setTimeout(), the task is scheduled for immediate execution on the same event loop. This is a very robust mechanism with a guaranteed execution order, and it's generally considered good practice to use it within attached() before doing any DOM manipulation.

实际上,Aurelia在不同地方内部使用了queueMicroTask()(主要在bindingtemplating-resources中).两个值得注意的地方是:

In fact, queueMicroTask() is used internally by Aurelia in various places (mostly in binding and templating-resources). Two notable places are:

  • 属性和集合观察者使用它来延迟"通知订阅者,直到所有其他绑定完成其内部更新工作为止
  • repeat属性用于设置ignoreMutations标志(在刷新队列后取消设置),以防止在更新其内部集合时进行无限递归
  • Property- and collection observers use it to "delay" notifying subscribers until all other bindings have completed their internal updating work
  • The repeat attribute uses it to set an ignoreMutations flag (and unset it after the queue is flushed) to prevent infinite recursion while updating its inner collection

您通常可以认为bind()和Attached()挂钩有两个阶段":非排队阶段和排队阶段.排队阶段是组件完成工作时,它首先要依靠其他(通常是递归的)过程来完成整个组件图.

You can generally consider there to be two "phases" to the bind() and attached() hooks: a non-queued, and a queued phase. The queued phase is when components do work that relies on the whole component graph to first be done with some other (usually recursive) process.

queueMicroTask() 不延迟执行,只需将其推入调用堆栈的末尾即可

queueMicroTask() does not delay execution, just pushes it to the end of the call stack

在功能上等同于将函数作为回调传递到调用堆栈的末尾,但省去了编写定位最后一个调用并将其全部连接所需的意大利面条代码的麻烦.超级干净.

It's the functional equivalent of passing the function as a callback to the end of the call stack, but saves you the trouble of writing the spaghetti code required to locate that last call and wire it all up. It's super clean.

其所有li元素都是根据 路由器的导航列表.这是在 attached 事件中发生的 组件

all its li elements are dynamically created based on the items in the router's navigation list. This is happening in the attached event of the component

请参见,每当在attached()期间创建任何内容时,您都不能依赖于在另一个组件attached()期间存在的东西,因为这取决于编译/组成的顺序.这是内部问题.对于自定义属性,尤其是为true.自定义属性(尤其是样式库中的属性)在各处都使用TaskQueue,因为这是它们依赖DOM的唯一方法.

See, whenever you create anything during attached(), you can't rely on that thing being there during another component's attached() as this depends on the order of compilation/composition. That's an internal matter. This is especially true for custom attributes. Custom attributes (particularly those in style libraries) use the TaskQueue all over the place because it's the only way they can rely on the DOM being done.

在这里使用queueMicroTask()将保证两件事:

Using queueMicroTask() here will guarantee two things:

  • 使用附件和渲染的第一遍"完全完成aurelia时执行.
  • 完成aurelia后,将立即立即执行-甚至不会延迟一微秒.
  • It's executed when aurelia is completely done with the "first pass" of attacheds and rendering
  • It's executed immediately when aurelia is done with that - not even a microsecond delayed.

解决这个问题的最佳方法(也许是唯一正确的方法)的确是使用TaskQueue-我保证:)

The best (and perhaps only correct) way to address this is indeed by using the TaskQueue - I promise :)

这篇关于自定义属性附加事件为时过早?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆