当父节点中有很多 v-if 时,自定义 v-focus 不起作用

Sam*_*ood 4 directive autofocus vue.js vuejs2

我在组件中定义了自定义指令“focus”:

<script>
    export default {
        name: 'demo',
        data () {
            return {
                show: true
            }
        },
        methods: {
            showInput () {
                this.show = false
            }
        },
        directives: {
            focus: {
                inserted: function (el) {
                    el.focus()
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

这是我的 html 模板:

<template>
    <div>
        <input type="number" id="readonly" v-if="show">
        <button type="button" @click="showInput" v-if="show">show</button>
        <input type="number" id="timing" v-model="timing" v-if="!show" v-focus>
   </div>
</template>
Run Code Online (Sandbox Code Playgroud)

但是当我点击 时buttoninput#timing不能自动对焦

当我把input#readonlybuttondiv,只使用一个V-如果input#timing可以自动对焦

<template>
    <div>
        <div v-if="show">
            <input type="number" id="readonly">
            <button type="button" @click="showInput">show</button>
        </div>
        <input type="number" id="timing" v-model="timing" v-if="!show" v-focus>
   </div>
</template>
Run Code Online (Sandbox Code Playgroud)

这就是为什么???

acd*_*ior 5

该指令的代码确实正在运行并聚焦<input>.

但它正在从 DOM 中删除!发生这种情况时,它会失去焦点。检查下面小提琴的控制台:https : //jsfiddle.net/acdcjunior/srfse9oe/21/

另一个重要的一点是,当inserted被调用时,<input id="timing">是在 DOM 中(如上所述),但它在 DOM 中的错误位置(介于<p>a</p><p>b</p>它不应该在的位置之间)。发生这种情况是因为 Vue试图重用元素

nextTick触发器(参见 fiddle)时,它位于正确的位置(在<p>c</p>和之间<p>d</p>),因为 Vue 将其移动到了正确的位置。这种移动是否正在分散注意力。

并且因为nextTick在 DOM 移动完成后运行,所以焦点仍然存在(见下文)。

使用Vue.nextTick()

推迟在下一个 DOM 更新周期后执行的回调。在您更改一些数据以等待 DOM 更新后立即使用它。

new Vue({
  el: '#app',
  data() {
    return {
      show: true,
      timing: 123
    }
  },
  methods: {
    showInput() {
      this.show = false
    }
  },
  directives: {
    focus: {
      inserted: function(el) {
        Vue.nextTick(() => el.focus());               // <======== changed this line
      }
    }
  }
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <div>
    <input type="number" id="readonly" v-if="show">
    <button type="button" @click="showInput" v-if="show">show</button>
    <input type="number" id="timing" v-model="timing" v-if="!show" v-focus>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)