web-dev-qa-db-fra.com

vue.js met l'accent sur la saisie

HTML

<span :style="{ display : displayTitle }" @dblclick="showInput()">
  {{ node.title }}
</span>
<input :style="{ display : displayTitleInput }" type="text" 
       @blur="hideInput1" @keydown="hideInput2" 
       @input="changeTitle(node.id , $event.target.value)" 
       :value="node.title">

JS

data() {
  return {
      displayTitle: "inline-block",
      displayTitleInput: "none"
    };
},
showInput() {
    this.displayTitle = "none"
    this.displayTitleInput = "inline-block"
},
hideInput1() {
   this.displayTitle = "inline-block"
   this.displayTitleInput = "none"
},
hideInput2(event) {
    if (event.keyCode === 13) {
        this.hideInput1()
    }
},

Je suis un développeur web japonais débutant. Je ne suis pas bon en anglais, désolé.

Le HTML est en "v-for" (v-for="node in list").

Lorsque vous double-cliquez sur du texte, il se transforme en <input>.

Je veux permettre de me concentrer sur l'entrée lorsqu'elle apparaît.

J'ai essayé mais ça n'a pas marché.

HTML

<span :style="{ display : displayTitle }" @dblclick="showInput(node.id)">
  {{ node.title }}
</span>
<input :ref='"input_" + node.id' :style="{display:displayTitleInput}" type="text" 
       @blur="hideInput1" @keydown="hideInput2" 
       @input="changeTitle(node.id , $event.target.value)" 
       :value="node.title">

JS

showInput(id) {
    this.displayTitle = "none"
    this.displayTitleInput = "inline-block"

    this.$nextTick(this.$refs["input_" + id][0].focus())
},

Il n'y a pas eu d'erreur sur la console, mais cela n'a pas fonctionné.

11
akao

Votre principal problème est que $nextTick prend une fonction de rappel mais vous exécutez

this.$refs["input_" + id][0].focus()

immédiatement. Vous pourriez faire fonctionner votre code correctement avec

this.$nextTick(() => {
  this.$refs["input_" + id][0].focus()
})

Cependant, je pense que vous rencontrerez d'autres problèmes et votre code peut être rendu beaucoup plus simple.

Un problème que vous constaterez est que toutes vos entrées de nœud deviendront visibles lorsque vous double-cliquez sur l'une d'entre elles en raison de vos règles de style.

Vous pouvez à la place stocker un indicateur "édition" quelque part sur le node ou dans un objet séparé.

Voici un exemple qui simplifie votre code en ...

  1. Utilisation de la nature de type tableau de ref lorsqu'il est utilisé dans un v-for loop, et
  2. Utilisation du modificateur enter sur votre @keydown liaison d'événement
new Vue({
  el: '#app',
  data: {
    list: [
      {id: 1, title: 'Node #1'},
      {id: 2, title: 'Node #2'}
    ],
    editing: {}
  },
  methods: {
    showInput(id, index) {
      this.$set(this.editing, id, true)
      
      this.$nextTick(() => {
        this.$refs.input[index].focus()
      })
    },
    hideInput(id) {
      this.editing[id] = false
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<ul id="app">
  <li v-for="(node, index) in list">
    <span v-show="!editing[node.id]" @dblclick="showInput(node.id, index)">
      {{ node.title }}
    </span>
    <input v-show="editing[node.id]" type="text"
           ref="input" :value="node.title"
           @blur="hideInput(node.id)" @keydown.enter="hideInput(node.id)">
  </li>
</ul>
16
Phil

La façon dont vous utilisez this.$nextTick(); est incorrecte. Vous devez lui passer une fonction de rappel.

this.$nextTick(function () {
    this.$refs["input_" + id].focus()
})

https://jsfiddle.net/un65e9oc/7/


Je ne suis cependant pas sûr de savoir comment cet accès au tableau fonctionne pour vous, car comme je le constate, $refs Est un objet avec les clés faisant référence au nom de la référence.

[Modifier: Merci au commentaire de @ Phil, ci-dessus est clair.]


Ce qui précède est la bonne solution à votre problème. Puisque vous avez déjà obtenu cette réponse, je vais ajouter autre chose que cela.

La raison pour laquelle vous voyez ce comportement est que parce que la référence que vous tenez dans $refs N'est pas mise à jour lorsque vous modifiez la visibilité de la zone de texte dans votre méthode showInput(). Ainsi, lorsque vous appelez this.$refs["input_" + id].focus();, il essaie en fait de définir focus sur un élément caché (car la référence actuelle n'est pas mise à jour).

C'est pourquoi vous devez appeler la $nextTick() pour la mettre à jour. Mais si vous vouliez une solution rapide à votre problème, sans appeler $nextTick(), vous pouvez le mettre à jour manuellement comme ceci:

this.displayTitleInput = "inline-block"
this.$refs["input_" + id].style.display = this.displayTitleInput

this.$refs["input_" + id].focus();

Cela fonctionnerait aussi :) J'espère que ça aide !!

2
Nimeshka Srimal

L'attribut autofocus est votre ami:

<input type="text" autofocus />