如何访问 Vue 3 + Typescript + Composition 中嵌套 v-for 的引用 API
How to access refs for a nested v-for in Vue 3 + Typescript + Composition API
我正在尝试使用 Typescript 将一些 Vue2 转换为 Vue3 组合 API。 Refs 的工作方式似乎不同,我不确定如何让它在 Vue3 中工作。在 Vue 2 中,它非常简单 this.$refs[docForm.value.fields[i].name][0].focus()
我不能只使用文档中描述的方法,您只需将 ref 放在 v-for 上并通过索引访问它,因为当我需要访问它时,我只会知道字段名称,而不是索引顺序(长话短说)。
<div v-for="(p, i) in docForm.pages">
<div v-for="(f, i) in p.fields">
<input type="text" :name="f.name" :ref="f.name" />
</div>
</div>
const goToNextEmptyField = (): void => {
if (docForm.value) {
for (var i = 0; i < docForm.value.fields.length; i++) {
if (docForm.value.fields[i].value == null || docForm.value.fields[i].value == '') {
refs[docForm.value.fields[i].name][0].focus() //THIS LINE NEEDS FIXING - WORKED IN Vue2
return
}
}
}
}
docForm 对象的结构是这样的(简化):
export interface DocForm {
pages: DocFormPageModel[]
fields: DocFieldModel[]
}
export interface DocFormPageModel {
fields: DocFormField[]
...
}
export interface DocFieldModel {
name: string
....
}
在 Vue 3 中你需要声明引用。
试试这个:
import { ref } from 'vue'
const inputs = ref([]);
// This is a guess at TS implementation
// const inputs : Ref<HTML element[]> = ref([]);
const goToNextEmptyField = (): void => {
if (docForm.value) {
for (var i = 0; i < docForm.value.fields.length; i++) {
if (docForm.value.fields[i].value == null || docForm.value.fields[i].value == '') {
inputs.value[docForm.value.fields[i].name][0].focus()
return
}
}
}
}
这是在初始化一个反应对象,该对象在检测到 refs 时填充。
另请注意,您始终需要在脚本(而不是模板)中通过 value
属性 引用 ref
。
这在 Vue 文档中有解释。
https://vuejs.org/guide/essentials/template-refs.html#refs-inside-v-for
确保您按下了“合成 API”切换开关!
Danial Storey 让我走上了正确的道路,这是可行的解决方案:
<script setup lang="ts">
import { ref, onMounted } from 'vue'
interface DocForm {
pages: DocFormPageModel[]
fields: DocFieldModel[]
}
interface DocFormPageModel {
fields: DocFormField[]
}
interface DocFieldModel {
name: string
value: string
}
const docForm = ref<DocForm>(
{pages: [
{ fields: [
{ name: "test1", value: "1", masterFieldIndex: 0 },
{ name: "test2", value: "", masterFieldIndex: 1 },
{ name: "test3", value: "", masterFieldIndex: 2 },
]}
], fields: [
{ name: "test1", value: "1", masterFieldIndex: 0 },
{ name: "test2", value: "", masterFieldIndex: 1 },
{ name: "test3", value: "", masterFieldIndex: 2 },
]}
)
const pageRefs = ref<HtmlElement[]>([])
const fieldRefs = ref<HtmlElement[]>([])
const goToNextEmptyField = (): void => {
if (docForm.value) {
for (var i = 0; i < docForm.value.fields.length; i++) {
if (docForm.value.fields[i].value == null || docForm.value.fields[i].value == '') {
var inputToFocus = fieldRefs.value.filter((f)=>{
return f.children[0].name == docForm.value.fields[i].name
})
inputToFocus[0].children[docForm.value.fields[i].name].focus()
return
}
}
}
}
</script>
<template>
<div v-for="p in docForm.pages">
<div v-for="f in p.fields" ref="fieldRefs">
<input type="text" v-model="docForm.fields[f.masterFieldIndex].value" :name="f.name" />
</div>
</div><br />
<button @click="goToNextEmptyField">
Go to on First Empty Field
</button>
</template>
您可以将上面的代码here粘贴到运行中。
我正在尝试使用 Typescript 将一些 Vue2 转换为 Vue3 组合 API。 Refs 的工作方式似乎不同,我不确定如何让它在 Vue3 中工作。在 Vue 2 中,它非常简单 this.$refs[docForm.value.fields[i].name][0].focus()
我不能只使用文档中描述的方法,您只需将 ref 放在 v-for 上并通过索引访问它,因为当我需要访问它时,我只会知道字段名称,而不是索引顺序(长话短说)。
<div v-for="(p, i) in docForm.pages">
<div v-for="(f, i) in p.fields">
<input type="text" :name="f.name" :ref="f.name" />
</div>
</div>
const goToNextEmptyField = (): void => {
if (docForm.value) {
for (var i = 0; i < docForm.value.fields.length; i++) {
if (docForm.value.fields[i].value == null || docForm.value.fields[i].value == '') {
refs[docForm.value.fields[i].name][0].focus() //THIS LINE NEEDS FIXING - WORKED IN Vue2
return
}
}
}
}
docForm 对象的结构是这样的(简化):
export interface DocForm {
pages: DocFormPageModel[]
fields: DocFieldModel[]
}
export interface DocFormPageModel {
fields: DocFormField[]
...
}
export interface DocFieldModel {
name: string
....
}
在 Vue 3 中你需要声明引用。
试试这个:
import { ref } from 'vue'
const inputs = ref([]);
// This is a guess at TS implementation
// const inputs : Ref<HTML element[]> = ref([]);
const goToNextEmptyField = (): void => {
if (docForm.value) {
for (var i = 0; i < docForm.value.fields.length; i++) {
if (docForm.value.fields[i].value == null || docForm.value.fields[i].value == '') {
inputs.value[docForm.value.fields[i].name][0].focus()
return
}
}
}
}
这是在初始化一个反应对象,该对象在检测到 refs 时填充。
另请注意,您始终需要在脚本(而不是模板)中通过 value
属性 引用 ref
。
这在 Vue 文档中有解释。 https://vuejs.org/guide/essentials/template-refs.html#refs-inside-v-for
确保您按下了“合成 API”切换开关!
Danial Storey 让我走上了正确的道路,这是可行的解决方案:
<script setup lang="ts">
import { ref, onMounted } from 'vue'
interface DocForm {
pages: DocFormPageModel[]
fields: DocFieldModel[]
}
interface DocFormPageModel {
fields: DocFormField[]
}
interface DocFieldModel {
name: string
value: string
}
const docForm = ref<DocForm>(
{pages: [
{ fields: [
{ name: "test1", value: "1", masterFieldIndex: 0 },
{ name: "test2", value: "", masterFieldIndex: 1 },
{ name: "test3", value: "", masterFieldIndex: 2 },
]}
], fields: [
{ name: "test1", value: "1", masterFieldIndex: 0 },
{ name: "test2", value: "", masterFieldIndex: 1 },
{ name: "test3", value: "", masterFieldIndex: 2 },
]}
)
const pageRefs = ref<HtmlElement[]>([])
const fieldRefs = ref<HtmlElement[]>([])
const goToNextEmptyField = (): void => {
if (docForm.value) {
for (var i = 0; i < docForm.value.fields.length; i++) {
if (docForm.value.fields[i].value == null || docForm.value.fields[i].value == '') {
var inputToFocus = fieldRefs.value.filter((f)=>{
return f.children[0].name == docForm.value.fields[i].name
})
inputToFocus[0].children[docForm.value.fields[i].name].focus()
return
}
}
}
}
</script>
<template>
<div v-for="p in docForm.pages">
<div v-for="f in p.fields" ref="fieldRefs">
<input type="text" v-model="docForm.fields[f.masterFieldIndex].value" :name="f.name" />
</div>
</div><br />
<button @click="goToNextEmptyField">
Go to on First Empty Field
</button>
</template>
您可以将上面的代码here粘贴到运行中。