1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Vue / Nuxt】inputコンポーネントにenterでフォーカス移動する

Posted at

input内でenterを押下した際に次のinputにフォーカスさせる処理、よくありますよね。
フォーカスしたいinputがコンポーネントの時に悩んだので備忘録です。

#子コンポーネントの書き方

Input.vue
<template>
  <div>
    <input
      ref="input"
      :value="value"
      :type="type"
      :placeholder="placeholder"
      @keydown="event=>$emit('focus', event)" />
  </div>
</template>
<script>
export default {
    name: 'Input',
    props: {
        type: {
        type: String,
        required: false,
        default: 'text'
        },
        value: {
        type: String,
        required: false,
        default: ''
        },
        placeholder: {
        type: String,
        required: false,
        default: ''
        }
    },
    methods: {
        focus () {
          this.$refs.input.focus()
        }
    }
}
</script>

#親コンポーネントの書き方
コンポーネントのinput -> 通常input -> コンポーネントのinputの順でフォーカス移動するサンプルにしました。

index.vue
<template>
<div>
  <Input
    :value="value"
    type="text"
    placeholder="name"
    @focus="event=>nextFocus(event,'emailRef')"/> 
  <input
    ref="emailRef"
    :value="value"
    type="text"
    placeholder="email"
    @keydown="event=>nextFocus(event,'passwordRef')"/> 
  <Input
    ref="passwordRef"
    :value="value"
    type="text"
    placeholder="password"/> 
</div>
</template>

<script>
import Input from '@/components/Input.vue'
export default {
  components: { Input },
  data() {
    return {
    value: ''
    }
  },
  methods: {
    nextFocus(event, refName) {
      if (event.keyCode != 13) {return}
       this.$refs[refName].focus()
    }
  }
}
</script>

6FA4092A-6C30-4394-9106-779E8F4D2E12_1_102_a.jpeg

#解説

Input.vue
    <input
      ref="input"
      :value="value"
      :type="type"
      :placeholder="placeholder"
      @keydown="event=>$emit('focus', event)" />

子コンポーネント側の@keydown="event=>$emit('focus', event)" で、何かしらキーが押下されるたびにeventを渡すfocusメソッドを読んでいます。

このeventを元にフォーカス処理をするために@focus="event=>nextFocus(event,'ref名')"でメソッドを呼びます。
通常のinputの場合は直接@keydownで問題ありません。
     

index.vue
    nextFocus(event, refName) {
      if (event.keyCode != 13) {return}
       this.$refs[refName].focus()
    }

nextFocusメソッドでイベントと対象のref名をもらいます。今回はenterの場合に移動したいので、keyCodeが13(enter)の時以外はなにも処理しません。
this.$refs[refName].focus()で受け取ったref名に対して focus処理をしています。
    

Input.vue
        focus () {
          this.$refs.input.focus()
        }

フォーカス先がコンポーネントの場合、コンポーネント(Input)のrefではなく、コンポーネント内に実際に書かれているinput要素にフォーカスする必要があります。
そのため実際にフォーカスしたいコンポーネント内のinputに対するフォーカスのメソッドが必要になります(説明が下手ですみません)

私はこれを書かなかったことによりfocus() is undefined になり原因解明に時間がかかってしまいました。。。

#最後に
他にもっといい書き方がありそうな気がしますが、フォーカス移動付きコンポーネントに関する記事が全く見つからなかったので私にはこれが限界でした。。。

今の現場では$listenersを使用する方法で記述していましたが、vue3では廃止されているようなので自分で考えて書いてみました。ものすごく時間がかかった。。。
もっといい書き方があるよ〜とか、俺ならこう書くぜ!などコメントいただけると大変嬉しいです。

最後まで読んでいただきありがとうございます!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?