如何从父级关注组件的子元素?

How to focus on a component's child element from the parent?

我有一个组件,模板如下:

<template>
<div class="referenceparent">
    <input
    v-model="searchterm"
    type="text"
    @input="Search"
    >
    <ul
    >
    <li
        v-for="(res, index) in searcheventresults"
        :key="index"
    >
        {{ res }}
    </li>
    </ul>
</div>
</template>

我有一个家长像这样使用这个组件:

<div class="col-sm-1">
    <input
    id="el1"
    :ref="'DurnRef' + index"
    v-model="editedPrescription[index].durn"
    type="text"
    class="form-control Durn input-sm"
    placeholder="5"
    aria-label="Durn"
    @keyup.enter="DurnSelected(index)"
    >
</div>
<div class="col-sm-2">
    <autocomplete-input 
    :ref="'DurnUnitRef' + index"
    placeholder="days"
    arialabel="DurationUnits"
    :searcheventresults="freqresults[index]"
    :defaultterm="editedPrescription[index].freq"
    @changed="(term) => {FreqSearch(term, index)}"
    @selected="(term) => {FreqSelected(term, index)}"
    />

我想做的是,当我在 el1 上按 Enter 键时,我需要以编程方式将焦点移动到自动完成输入中的输入元素。我尝试像上面那样向自动完成输入添加一个引用,希望引用会传播到子输入元素。但是当我打电话给裁判时:

this.$refs[`DurnUnitRef${index}`].focus();

但这不起作用。当我检查那个对象时,我发现它没有焦点方法。我怎样才能实现我想要的,即从嵌入组件的父元素以编程方式关注作为组件子元素的特定元素?

很难在没有正常工作的情况下了解您遇到的问题 fiddle,但是 我注意到有两件事可能导致或促成这种行为。

您要求聚焦附加到组件的引用,但带有输入的内部组件包裹在 div 中。这样做,将在该 div 元素上调用焦点,并且该元素没有 tabindex 属性 集,默认情况下 div 不可聚焦。

另一个问题原因是您没有等待 nextTick,尽管也可能在更新 DOM 内容之前设置焦点。

我在这里放了一个 fiddle 来解释这两个概念。让我知道这是否有帮助

var myApp = new Vue({
  el: '#app',
  data() {
     return {
        focus: false
     }
  },
  methods: {
    switchAndFocus() {
       this.$nextTick(function(){
        this.$refs.toFocus.focus();
        this.focus = true;
       });
      
    },
  },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
<style>

.container {
  padding: 10px;

}
.testing {
     border: solid lightgray 1px;
}
.testing:focus {
     border: solid red 1px;
}
</style>
<div id="app" class="container">
  <div >
  <button @click="switchAndFocus">Click to focus</button>
  <h class="testing"  ref="toFocus" tabindex="1">Is {{!focus ? '' : 'focused'}}
  </div>
</div>

可能的解决方案:

目的:输入元素中的事件需要将焦点设置在触发事件的输入元素的兄弟元素的子元素上。

#Parent Element
<div class="col-sm-1">
    <input
    :ref="'DurnRef' + index"
    type="text"        
    @keyup.enter="FocusDurnUnit(index)"
    >
</div>
<div class="col-sm-2">
    <autocomplete-input 
    :ref="'DurnUnitRef' + index"
    :ref-str="'DurnUnitRef' + index"       
    />
</div>

在上面,输入标签上的 @keyup.enter 需要将焦点设置在 autocomplete-input 组件的子组件上。为此,我首先为 autocomplete-input 组件设置一个引用,并传递一个包含相同引用字符串名称的道具。

在 autocomplete-input 组件中,我得到了属性 refStr,并将与 ref 相同的属性分配给嵌套在 autocomplete-input 组件内的输入元素,如下所示:

#AutocompleteInput.vue
<template>
<div
    class="referenceparent"
    tabindex="0"
>
    <input
    :ref="refStr"       
    type="text"       
    >
</div>
</template>

然后,回到父组件,在处理需要触发聚焦的事件的方法FocusDurnUnit(index)中,我通过以下代码引用子(嵌套组件)的元素:

FocusDurnUnit(index) {
  let myref = this.$refs[`DurnUnitRef${index}`].$refs[`DurnUnitRef${index}`]
  myref.focus()
},

所以关键的信息是,可以通过引用父组件的 ref 来获取嵌套子组件的 ref,如果存在,则为父组件设置一个。

这里,this.$refs[DurnUnitRef${index}]autocomplete-input元素的ref,.$refs[DurnUnitRef${index}是指autocomplete-input

中子input元素的ref

这解决了我的问题并且效果很好。如果有更简单的解决方案,请分享。