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 5 years have passed since last update.

【Ginza.js#8 - LTスライド】Vue.jsでWeb画面にBashのhistory機能を実装する

Posted at
1 / 16

Bashのhistory機能、便利ですよね?

bash-history.gif


Webのフォームにも、実装できたら便利なはず

ということで実装していきます


まずはBashのhistoryの挙動を確認

挙動1

↑キーで1つ前、↓キーで1つ後に実行したコマンドを表示できる

挙動2

実行前の編集中のコマンドもhistoryに反映される

挙動3

コマンドを実行するたび、編集中だったコマンドはリセットされる


bash-history.gif


実装の流れ

  1. まずは↑キーと↓キーで過去の入力値を表示できるようにする(Enterキーで入力値の確定をする)
  2. 次に編集時の挙動を実装する

↑キー、↓キーとEnterキーの挙動を実装

idつきのinputタグを用意

history.html
<input id="form" placeholder="some text">

何はともあれ、まずは v-model

history.html
<input
  id="form"
  placeholder="some text"
  v-model="text"
>

キーボードイベントのバインディング

history.html
<input
  ~ 省略 ~
  v-on:keydown.arrow-up.prevent="backHist"
  v-on:keydown.arrow-down.prevent="headHist"
  v-on:keydown.enter='confirm'
>

prevent でデフォルトの挙動を無効化しないと、カーソルの位置が飛ぶ

Vueインスタンス作成

history.js
const form=new Vue({
  el: "#form",
  data: {
    text: '', // フォームの初期値
    index: 0, // ヒストリのインデックス
    history: [ '' ] // ヒストリの先頭にもフォームの初期値を入れておく
  }
})

※配列の先頭が最新の値とする


↑キー↓キーイベント発火時の関数を定義

history.js
const form=new Vue({
  ~ 省略 ~
  methods: {
    backHist(){
      // indexはhistoryの長さ未満
      (this.index + 1) < this.history.length
        ? this.index++
        : undefined

      this.text=this.history[this.index];
    },
    headHist(){
      // indexは0より小さくはならない
      (this.index - 1) < 0
        ? undefined
        : this.index--

      this.text=this.history[this.index];
    },
  }
});

Enterキーイベント発火時の関数を定義

history.js
const form=new Vue({
  ~ 省略 ~
  methods: {
    ~ 省略 ~
    confirm: function(){
      this.hist[0]=this.text; // 現在の値をヒストリの最新値として格納

      // 次のヒストリの初期値を入力(現在のテキストが空のときはヒストリを追加しない)
      this.text === ''
        ? undefined
        : this.hist=[ '', ...this.hist ]

      this.index=0; // インデックスを0(最新の値)に戻す
      this.text=''; // フォームをクリア
    }
  }
});

これで↑キー、↓キーとEnterキーの挙動は再現できました


編集時の挙動を実装

キー入力イベントのバインディング

history.html
<input
  ~ 省略 ~
  v-on:input="editHist"
>

キー入力されるたびにヒストリが「編集された」と考える

ヒストリにオリジナルのテキストと、編集中のテキストを格納できるようにする

history.js
const form=new Vue({
  ~ 省略 ~
  data: {
    ~ 省略 ~
    history: [{
      text: '', // オリジナル
      edit: undefined, // 編集中のテキスト(なければundefined)
    }]
  }
})

編集イベント発火用の関数を定義

history.js
const form=new Vue({
  ~ 省略 ~
  methods: {
    ~ 省略 ~
    editHist: function(){
      this.hist[this.index].edit=this.text;
    }
  }
})

history の値変更に合わせて confirm 関数を変更する

history.js
const form=new Vue({
  ~ 省略 ~
  methods: {
    ~ 省略 ~
    confirm: function(){
      this.hist[0].text=this.text; // 現在の値をヒストリの最新値として格納

      // 編集中の値をクリア
      this.hist.forEach(
        h => h.edit=undefined
      );

      // 次のヒストリの初期値を入力(現在のテキストが空のときはヒストリを追加しない)
      this.text === ''
        ? undefined
        : this.hist=[{
            text: '',
            edit: undefined
          }, ...this.hist ]
            // .slice(0, 16) でhistoryの登録数上限(16)を指定することも可能

      this.index=0; // インデックスを0(最新の値)に戻す
      this.text=''; // フォームをクリア
    }
  }
})

以上で編集の挙動も実装できました


なぜこれを実装したか

Demo


おわりに

簡単に実装できるので、ITエンジニアをターゲットにしたサービスで実装してみてはどうでしょう


About Me

普段はインフラエンジニア

JavaScriptとShellScriptでインフラ自動化ができるOSSを開発しています

Submarine1.0-with-text-170.png

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?