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

custom v-focus not work when there are many v-if in parent node

我在我的组件中定义了自定义指令 "focus":

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

这是我的 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>

但是当我点击button时,input#timing不能自动对焦

当我将input#readonlybutton放入一个div中并且只使用一个v-if时,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>

这是为什么???

指令的代码确实是 运行 并且关注 <input>.

但它正在从 DOM 中删除!发生这种情况时,它会失去焦点。检查下面 fiddle 的控制台: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 移动完成后运行,所以焦点仍然存在(见下文)。

Using Vue.nextTick():

Defer the callback to be executed after the next DOM update cycle. Use it immediately after you’ve changed some data to wait for the DOM update.

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
      }
    }
  }
})
<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>