Vue js - v-for 循环中的 ref 始终返回 null
我正在尝试访问 Vue 中的一个元素,因为我想查看它的类何时更改(我正在使用 Bootstrap,所以我想监视类何时更改为显示)。问题是,一旦我将 ref'd 元素放入 v-for 循环中,它总是返回 null。我尝试将引用的名称附加到循环项的索引,然后尝试将其记录到控制台,但它总是返回“null”。
一旦我将元素从 v-for 循环中取出,它就会很好地返回该元素。
我似乎找不到解决办法。这是 Vue 根本不支持的东西吗?如果没有,是否有更好的方法来观察 DOM 以查看元素的类是否发生变化?
PS 我正在使用组合 API。
模板:
<template>
<div v-for="room in rooms" :key="room.id" class="">
<p class="test" :ref="'test'+room.id">Hello world</p>
</div>
</template
脚本:
setup(){
const test1 = ref(null)
onMounted(() => {
console.log("test1: ", test1.value)
})
return { test1 }
}
I am trying to access an element in Vue as I want to see when it's class changes (I'm using Bootstrap so I want to watch for when a class changes to shown). The problem is that as soon as I put a ref'd element into a v-for loop it always returns null. I have tried appending the ref's name with the index of the loop item, and then trying to log this to the console it just always returns 'null'.
As soon as I take the element out of the v-for loop it returns the element fine.
I can't seem to find a solution. Is this something that Vue just simply doesn't support? If not, is there a better way for me to watch the DOM to see if an element's class changes?
P.S. I'm using the composition API.
Template:
<template>
<div v-for="room in rooms" :key="room.id" class="">
<p class="test" :ref="'test'+room.id">Hello world</p>
</div>
</template
Script:
setup(){
const test1 = ref(null)
onMounted(() => {
console.log("test1: ", test1.value)
})
return { test1 }
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这看起来是一个非常常见的问题,所以我深入研究了 Vue 源代码并发现了以下内容:
这是 Vue 更新和渲染方式的限制。如果同一个模板有多个 s,那么每个模板都有自己的补丁队列。每个补丁队列都按照自己的时间表进行处理,因此一个补丁队列有可能在另一个队列开始之前完成。如果发生这种情况,则排队的更新之一将不会发生。这意味着 Vue 不会检测到元素的更改,因此根本不会进行任何重新渲染,这就是为什么你的元素不会显示在控制台输出中!
您可以通过确保所有更新队列在彼此开始之前完成来解决此问题,我们可以通过向相关组件添加
update: {sync: true }
配置来解决此问题。这将迫使 Vue 在处理应用程序中的任何其他更改之前同步处理所有更新队列。您还可以将
sync: true
配置添加到父组件中,以包装所有其他组件并确保它们全部同步。This looks like a pretty common problem, so I went digging through the Vue source and found the following:
It's a limitation of the way Vue does updates and renders. If you have multiple s for the same template, then each of them has its own patch queue. Each patch queue gets processed on its own schedule, so it's possible for one to finish before another even starts. If that happens, then one of the queued updates won't happen. That would mean Vue wouldn't detect changes to your element and hence wouldn't do any re-rendering at all, which is why your element doesn't show up in your console output!
You can work around this by making sure all update queues finish before each other begins, which we can do by adding an
update: { sync: true }
config to your component in question. This will force Vue to process all of your update queues synchronously before processing any other changes in the application.You could also add a
sync: true
config to your parent's component that wraps all of your other components and make sure they all sync.v-for
中的模板引用存在一个已知错误 (
vuejs/core#5525
),其中数组引用未正确填充。一种解决方法是绑定一个将元素引用推入数组的函数:
Template refs in a
v-for
There's a known bug (
vuejs/core#5525
), where array refs are not properly populated.One workaround is to bind a function that pushes the element refs into the array:
demo 1
Watching
class
changesTo observe changes to the
class
attribute of the elements, use aMutationObserver
.mounted
hook: For eachroomRefs
item:Create a
MutationObserver
with a callback that handles mutations (i.e., a change to the observed attribute).Use that
MutationObserver
instance toobserve
theclass
attribute on theroomRefs
item.Collect each observer into an array, as we'll need to disconnect the observer upon unmounting.
unmounted
hook:disconnect
all observers to stop watching for changes. This cleanup step is necessary to avoid a memory leak.demo 2