英文:
How do I move focus with template refs in a v-for loop ( Vue 3 Composition API)?
问题
Here is the translated portion of your text:
我正在使用一个按钮来显示/隐藏更多或更少的列表项,并希望在单击按钮时使用 ref 来聚焦于“更多”项中的第一个项(这将是第六个项,或 listItem[5])。在 Vue Options API 中,这相对容易。但是我无法在 Composition API 中使其工作。我在 vue devtools 中看到了组件的所有 ref 列表:
listItem:Array[12] (Ref)
0:<li>
1:<li>
2:<li>
3:<li>
4:<li>
5:<li>
6:<li>
7:<li>
8:<li>
9:<li>
10:<li>
11:<li>
当按钮被点击时,我收到一个错误 Uncaught TypeError: Cannot read properties of undefined (reading 'value')
。我对 Composition API 相对较新,几乎感觉像一个进退两难的情况,我想引用某些尚不存在的东西。我在这里缺少什么?
我的代码:
<script setup>
import { ref } from 'vue'
const listItem = ref([])
const showAllCounties = ref(false)
const showhideItems = (index) => {
if (!showAllCounties.value) {
return index < 5
} else {
return true
}
}
const showFullList = () => {
document.activeElement.blur()
showAllCounties.value = !showAllCounties.value
if (listItem) {
console.log('yes') // 返回 'yes'
console.dir(listItem) // 显示带有所有 12 个项的代理数组
}
const target = listItem[5]
if (target) {
target.value.focus()
console.log('yes, ' + target)
} else {
console.log('no')
}
listItem[5].value.focus()
// 也尝试过在 onMounted() 中记录 listItem 和 listItem.value[5] 到控制台。
}
</script>
<template>
<ul>
<li
v-for="(county, index) in project.data.counties"
v-show="showhideItems(index)"
class="project-counties-list"
ref="listItem"
:key="county.id"
>
{{ county.county_name }}, {{ index }}
</li>
</ul>
<button type="button" @click="showFullList">{{ ButtonText }}</button>
</template>
请注意,这只是您提供的代码的翻译部分,不包括额外的解释或答案。
英文:
I am using a button to show/hide more or fewer list items, and want to use a ref to focus on the first of the "more" items when the button is clicked (this would be the sixth item, or listItem[5]). In the vue Options API, this is relatively easy. But I cannot get it work with the Composition API. I see all of the refs listed for the component in vue devtools:
listItem:Array[12] (Ref)
0:<li>
1:<li>
2:<li>
3:<li>
4:<li>
5:<li>
6:<li>
7:<li>
8:<li>
9:<li>
10:<li>
11:<li>
When the button gets clicked, I get an error Uncaught TypeError: Cannot read properties of undefined (reading 'value')
. I am relatively new to the Composition API, and it almost feels like a Catch-22, where I want to reference something that doesn't really exist yet. What am I missing here?
My code
<script setup>
import { ref } from 'vue'
const listItem = ref([])
const showAllCounties = ref(false)
const showhideItems = (index) => {
if (!showAllCounties.value) {
return index < 5
} else {
return true
}
}
const showFullList = () => {
document.activeElement.blur()
showAllCounties.value = !showAllCounties.value
if (listItem) {
console.log('yes') // returns 'yes'
console.dir(listItem) // shows proxy array with all 12 items
}
const target = listItem[5]
if (target) {
target.value.focus()
console.log('yes, ' +target)
} else {
console.log('no')
}
listItem[5].value.focus()
//also tried listItem.value[5].focus()
}
</script>
<template>
<ul>
<li
v-for="(county, index) in project.data.counties"
v-show="showhideItems(index)"
class="project-counties-list"
ref="listItem"
:key="county.id"
>
{{ county.county_name }}, {{ index }}
</li>
</ul>
<button type="button" @click="showFullList">{{ ButtonText }}</button>
</template>
I've also tried logging listItem
and listItem.value[5]
to the console in onMounted()
.
答案1
得分: 1
这是花了我很长时间才想出来的解决方案。关键之一是要使用 listItem.value[5]
,而不是 listItem[5].value
。希望我已经学会了如何处理 ref 数组。我还需要使用 nextTick()
来移动焦点 - 而且我之前的示例中忘记了包括 tabindex
。所以:
<script setup>
import { ref, nextTick, computed } from 'vue'
const listItem = ref([])
let showAllCounties = ref(false)
const showHideItems = (index) => {
return showAllCounties.value
? true
: index < 5
}
const showHideFullList = () => {
showAllCounties.value = !showAllCounties.value
nextTick(() => {
const target = listItem.value[5]
if (target) {
target.focus()
}
})
}
const showMoreButtonText = computed(() => {
return showAllCounties.value
? 'Show less'
: 'Show more'
})
</script>
<template>
<ul>
<li
v-for="(county, index) in project.data.counties"
v-show="showHideItems(index)"
:id="`li-${index}`"
class="project-counties-list"
ref="listItem"
:key="county.id"
:tabindex="index === 5 ? -1 : false"
>
{{ county.county_name }}
</li>
</ul>
<button
type="button"
class="toggle"
@click="showHideFullList"
>{{ showMoreButtonText }}
</button>
</template>
希望这对你有所帮助。
英文:
Here's the solution that took me forever to figure out. The big key was to use listItem.value[5]
instead of not listItem[5].value
. Lesson learned (I hope) about how to deal with ref arrays. I also needed nextTick()
to get the focus moved -- plus I had forgotten to include the tabindex
in my previous example. So:
<script setup>
import { ref, nextTick } from 'vue'
const listItem = ref([])
let showAllCounties = ref(false)
const showHideItems = (index) => {
return showAllCounties.value
? true
: index < 5
}
const showHideFullList = () => {
showAllCounties.value = !showAllCounties.value
nextTick(() => {
const target = listItem.value[5]
if (target) {
target.focus()
}
})
}
const showMoreButtonText = computed(() => {
return showAllCounties.value
? 'Show less'
: 'Show more'
})
</script>
<template>
<ul>
<li
v-for="(county, index) in project.data.counties"
v-show="showHideItems(index)"
:id="`li-${index}`"
class="project-counties-list"
ref="listItem"
:key="county.id"
:tabindex="index === 5 ? -1 : false"
>
{{ county.county_name }}
</li>
</ul>
<button
type="button"
class="toggle"
@click="showHideFullList"
>{{ showMoreButtonText }}
</button>
</template>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论