7
6

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で縦に自動伸縮するtextareaの作り方 | How to make auto resizing <textarea>with Vue.js

Last updated at Posted at 2020-04-02

english ver

インターネッツで調べてみても中途半端なtextareaしか出てこなかったので、備忘も兼ねた記事です。

伸びるけど縮まないとか、縮むけど1文字いれるごとに2pxずつしか縮まないとか、意味なくない!?!?!?!?!?!?

んおお!?!?!?!?

まずは結果

ezgif-6-b2be62c1e8d5.gif

うおおおおおおおお
うおおおおおおおお
うおおおおおおおお
うおおおおおおおお
うおおおおおおおおうおおおおおおおお
うおおおおおおおお
うおおおおおおおおうおおおおおおおおうおおおおおおおお
うおおおおおおおお
うおおおおおおおお
うおおおおおおおお

コード

今気づいたけどマークダウンの候補にvuejsってある。。
便利すぎない?

業務で書いたコードからいらないやつ消した感じなので、このまま動かなかったらごめんなさい。
編集リクエスト送っていただければーーー

MyTextarea.vue
<template>
  <textarea
    class="textarea bg-white"
    :style="textareaStyle"
    :placeholder="placeholder"
    :value="value"
    @input="handleInput($event)"
  />
</template>

<script lang="ts">
import Vue from "vue"

export default Vue.extend({
  props: {
    placeholder: { type: String, default: "" },
    value: { type: String, default: '' }
  },
  data() {
    return {
      textareaHeight: 100 // デフォルト値いれとく。minHeightといっしょでよい。borderあるのでちょっとずれる
    }
  },
  computed: {
    textareaStyle(): object { // 動的にtextareaのheightをいじれるようにしている
      return {
        height: `${this.textareaHeight}px`
      }
    }
  },
  methods: {
    async handleInput(event: any) { // 入力されるたびによばれる。anyなのはゆるして。。。
      this.$emit('input', event.target.value) // これは親に伝えるためだけ。

      this.textareaHeight = 0 // ミソ。一旦textareaのheightを0にしちゃう

      await this.$nextTick() // さらにミソ。ここで待たないとDOMの更新前に下のコードが走って変な挙動になる

      // heightが0になった瞬間textareaはminHeight: 100になる
      // 入力済み文字列の高さが100を超えたら、scrollHeightが必要な分だけ大きくなる = それをheightにしちゃえばOK!
      this.textareaHeight = event.target.scrollHeight
    }
  }
})
</script>

<style lang="stylus" scoped>
.textarea-container {
  width: 100%;
}

.textarea {
  width: 100%;
  min-height: 100px; // ここはお好み。変えるならdata()の値も変えるとよいよ
  border: 1px solid #D9D9D9
  border-radius: 4px;
  padding: 5px 12px;

  &::placeholder {
    color: #D9D9D9
  }
}
</style>

TL;DR

this.$nextTickがミソなんじゃぞ。

7
6
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
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?