インターネッツで調べてみても中途半端なtextareaしか出てこなかったので、備忘も兼ねた記事です。
伸びるけど縮まないとか、縮むけど1文字いれるごとに2pxずつしか縮まないとか、意味なくない!?!?!?!?!?!?
んおお!?!?!?!?
まずは結果
うおおおおおおおお
うおおおおおおおお
うおおおおおおおお
うおおおおおおおお
うおおおおおおおおうおおおおおおおお
うおおおおおおおお
うおおおおおおおおうおおおおおおおおうおおおおおおおお
うおおおおおおおお
うおおおおおおおお
うおおおおおおおお
コード
今気づいたけどマークダウンの候補に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がミソなんじゃぞ。