如何从 v-for 获取和观察对元素的引用?
How to get and observe ref to element from a v-for?
似乎解决类似问题的所有答案都与 Vue 2 相关,或者根本没有给出预期的结果。即使 the docs 中描述的内容也不起作用,因为如果我记录 ref 的值,我只会看到一个空对象。
我有一个这样的模板:
<template>
<post-content v-for="post in posts" :post-data="post" :key="post.id" ref="lastPost" />
</template>
PostContent 组件的内容并不重要,将其想象成 div 显示 post.content
中的内容。
在脚本中,我从 API 中获取 posts
,我希望在引用 lastPost
中加载最后一个 post,这样我可以访问它的HTMLElement
(我需要它来做东西,但在这里我只是尝试记录它)。
// This uses composition API with <script setup> syntax
const posts = ref<{id: number, content: string}[]>([])
getPostsFromApi()
.then((thePost: {id: number, content: string}) => posts.value.push(thePost))
const lastPost = ref<typeof PostContent>()
watch(lastPost, () => nextTick(() => console.log(lastPost.value)), {flush: "post"})
但是,这会导致日志成为一个简单的空对象 {}
。
- 我需要能够在 HTMLElement 加载后访问它本身。
- 我需要观察引用的变化,这样我每次添加posts时都能得到元素。
- 在任何给定时间我只需要最后一个post,我不关心以前的。我一次只会添加 posts 个。这就是我不使用数组作为参考的原因。
为什么记录的是一个空对象,而不是根据文档所期望的?我做错了什么?
与具有常规 <script>
块的 SFC 不同,<script setup>
组件 默认关闭 -- 即 <script setup>
范围内的变量是除非通过 defineExpose()
显式公开,否则不会公开给父级。记录的模板引用中的空对象表示您没有公开任何属性。
要公开 PostContent
的根元素,请在组件中使用模板引用,并使用 [=15= 公开 ref
(例如,名为“$el
”) ]:
// PostContent.vue
<script setup lang="ts">
const $el = ref()
defineExpose({ $el })
</script>
<template>
<div ref="$el">...</div>
</template>
顺便说一句,watch()
和 { flush: 'post' }
可以简化为 watchPostEffect()
:
watch(lastPost, () => nextTick(() => console.log(lastPost.value.$el)), {flush: "post"})
// OR more simply:
watchPostEffect(() => console.log(lastPost.value.$el))
似乎解决类似问题的所有答案都与 Vue 2 相关,或者根本没有给出预期的结果。即使 the docs 中描述的内容也不起作用,因为如果我记录 ref 的值,我只会看到一个空对象。
我有一个这样的模板:
<template>
<post-content v-for="post in posts" :post-data="post" :key="post.id" ref="lastPost" />
</template>
PostContent 组件的内容并不重要,将其想象成 div 显示 post.content
中的内容。
在脚本中,我从 API 中获取 posts
,我希望在引用 lastPost
中加载最后一个 post,这样我可以访问它的HTMLElement
(我需要它来做东西,但在这里我只是尝试记录它)。
// This uses composition API with <script setup> syntax
const posts = ref<{id: number, content: string}[]>([])
getPostsFromApi()
.then((thePost: {id: number, content: string}) => posts.value.push(thePost))
const lastPost = ref<typeof PostContent>()
watch(lastPost, () => nextTick(() => console.log(lastPost.value)), {flush: "post"})
但是,这会导致日志成为一个简单的空对象 {}
。
- 我需要能够在 HTMLElement 加载后访问它本身。
- 我需要观察引用的变化,这样我每次添加posts时都能得到元素。
- 在任何给定时间我只需要最后一个post,我不关心以前的。我一次只会添加 posts 个。这就是我不使用数组作为参考的原因。
为什么记录的是一个空对象,而不是根据文档所期望的?我做错了什么?
与具有常规 <script>
块的 SFC 不同,<script setup>
组件 默认关闭 -- 即 <script setup>
范围内的变量是除非通过 defineExpose()
显式公开,否则不会公开给父级。记录的模板引用中的空对象表示您没有公开任何属性。
要公开 PostContent
的根元素,请在组件中使用模板引用,并使用 [=15= 公开 ref
(例如,名为“$el
”) ]:
// PostContent.vue
<script setup lang="ts">
const $el = ref()
defineExpose({ $el })
</script>
<template>
<div ref="$el">...</div>
</template>
顺便说一句,watch()
和 { flush: 'post' }
可以简化为 watchPostEffect()
:
watch(lastPost, () => nextTick(() => console.log(lastPost.value.$el)), {flush: "post"})
// OR more simply:
watchPostEffect(() => console.log(lastPost.value.$el))