Vue数字入力ボックスコンポーネントの使い方を詳しく説明します。


前の話
基礎部品について紹介します。もう更新しました。この記事はコンポーネントの基礎知識を用いて、デジタル入力ブロックコンポーネントを開発します。命令、イベント、コンポーネント間通信に関する。

基礎的な需要
  • 数字だけ入力できます。
  • 初期値、最大値、最小値
  • を設定します。
  • 入力枠をフォーカスすると、キーボードの上下キーに対するサポートが増加します。
  • 制御手順prop-stepを追加します。例えば、10に設定して、プラスボタンをクリックして、一回に10を増加します。
  • プロジェクトの構築
    需要を理解した後、プロジェクトの初期化を行います。
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>Document</title>
     <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>
    <body>
     <div id="app">
     <input-number></input-number>
     </div>
    </body>
    </html>
    <script>
     Vue.component('input-number',{
     template: `
      <div class="input-number">
      <input type="text" />
      <button>-</button>
      <button>+</button>
      </div>
     `}
     var app = new Vue({
     el:'#app'
     })
    </script>
    初期化構造が整ったら、初期値、最大値、最小値を設定するために、親コンポーネントのにこれらの値を設定し、親コンポーネントのデータをPropsでサブコンポーネントに転送します。
    親コンポーネントにデータを追加します。valueはキーバインディング値ですので、v-modelを使って、双方向バインディングを実現します。
    
    <input-number v-model="value" :max="100" :min="0"></input-number>
    サブコンポーネントにpropsオプションを追加します。
    
     props: {
      max: {
      type: Number,
      default: Infinity
      },
      min: {
      type: Number,
      default: -Infinity
      },
      value: {
      type: Number,
      default: 0
      }
     },
    私たちは、Vueコンポーネントは単一のデータストリームなので、親コンポーネントからのデータを変更することができません。ここでは、サブコンポーネントはvalue値だけを変更します。だから、サブコンポーネントにdataデータを設定して、デフォルトではvalue値を参照して、コンポーネントの内部でdataを維持します。
    
    data() {
      return{
      //             
      currentValue : this.value,
      }
     }
    そしてサブコンポーネントのinput元素にvalueをバインドします。
    
    <input type="text" :value="currentValue" />
    このように、初期化時に親コンポーネントvalueを引用するだけの問題が解決されましたが、もし親コンポーネントがvalueを修正したら、サブコンポーネントが感知できなくなり、current Valueを一緒に更新したいです。では、wacthのモニターオプションを使ってvalueを監督します。
  • 親コンポーネントvalueが変化すると、サブコンポーネントのcurrent Valueも変化します。
  • サブアセンブリcurrentValueが変化するとき、$emitを使用してv-modelをトリガし、親コンポーネントvalueも変化する。
  • 
    watch: {
      //     currentValue value
      currentValue(val) {
      // currentValue   ,      value   
      this.$emit('input', val);
      
    
      },
      value(val) {
      //    value   ,   currentValue   
      this.updataValue(val);
      }
     },
     methods: {
      updataValue(val) {
      if(val > this.max) val = this.max;
      if(val < this.min) val = this.min;
      this.currentValue = val;
      }
      },
      //        ,  value    
     mounted: function() {
      this.updataValue(this.value);
     }
    上記のコードの中で、ライフサイクルmountedフックもudateValueメソッドを使用しています。初期化時にもvalueを検証するためです。
    親子間の通信がほぼ解決しました。次はボタンの操作を完成します。handleDownとhandleUp方法を追加します。
    
    template: `
      <div class="input-number">
      <input type="text" :value="currentValue" />
      <button @click="handleDown" :disabled="currentValue <= min">-</button>
      <button @click="handleUp" :disabled="currentValue >= max">+</button>
      </div>
     `,
      methods: {
      updataValue(val) {
      if(val > this.max) val = this.max;
      if(val < this.min) val = this.min;
      this.currentValue = val;
      },
      //       10
      handleDown() {
      if(this.currentValue < this.min) return 
      this.currentValue -= this.prop_step;
      },
      //       10 
      handleUp() {
      if(this.currentValue < this.min) return
      this.currentValue += this.prop_step;
      },
    ユーザーが入力ボックスに具体的な値を入力したい場合、どうすればいいですか?
    inputのためにオリジナルのchangeイベントをバインドし、入力の有無を判断する。
    
    <input type="text" :value="currentValue" @change="handleChange" /> 
    methodsオプションに、handleChangeメソッドを追加します。
    
    //       
     handleChange(event) {
     var val = event.target.value.trim();
     var max = this.max;
     var min = this.min;
      if(isValueNumber(val)) {
       val = Number(val);
       if(val > max) {
       this.currentValue = max;
       }
       if(val < min) {
       this.currentValue = min;
       }
       this.currentValue = val;
       console.log(this.value);
      }else {
       event.target.value = this.currentValue;
      }
    外層に数字かどうかを判断する方法isValueNumberを追加します。
    
    function isValueNumber(value) {
     return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).test(value+ '');
     }
    この数字入力ボックスのコンポーネントは基本的に完成しましたが、前に提出した後の二つの要求も実現しなければなりません。簡単です。inputにkeydownイベントを結びつけて、dataオプションにデータpropを追加します。ステップ
    
    <input type="text" :value="currentValue" @change="handleChange" @keydown="handleChange2" />
    
    data() {
      return{
      //             
      currentValue : this.value,
      prop_step: 10
      }
     }
    
     //     ,      
      handleChange2(event) {
      console.log(event.keyCode)
      if(event.keyCode == '38') {
       this.currentValue ++;
      }
      if(event.keyCode == '40') {
       this.currentValue --;
      }
      }
    完全コード:
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>Document</title>
     <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>
    <body>
     <div id="app">
      <input-number v-model="value" :max="100" :min="0"></input-number>
     </div>
    </body>
    </html>
    <script>
     function isValueNumber(value) {
      return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).test(value+ '');
     }
     Vue.component('input-number',{
      props: {
       max: {
        type: Number,
        default: Infinity
       },
       min: {
        type: Number,
        default: -Infinity
       },
       value: {
        type: Number,
        default: 0
       }
      },
      template: `
       <div class="input-number">
        <input type="text" :value="currentValue" @change="handleChange" @keydown="handleChange2" />
        <button @click="handleDown" :disabled="currentValue <= min">-</button>
        <button @click="handleUp" :disabled="currentValue >= max">+</button>
       </div>
      `,
      data() {
       return{
        //             
        currentValue : this.value,
        prop_step: 10
       }
      },
      watch: {
       //     currentValue value
       currentValue(val) {
       // currentValue   ,      value   
       this.$emit('input', val);
       
    
       },
       value(val) {
       //    value   ,   currentValue   
        this.updataValue(val);
       }
      },
      methods: {
       updataValue(val) {
        if(val > this.max) val = this.max;
        if(val < this.min) val = this.min;
        this.currentValue = val;
       },
       //       10
       handleDown() {
        if(this.currentValue < this.min) return 
        this.currentValue -= this.prop_step;
       },
       //       10 
       handleUp() {
        if(this.currentValue < this.min) return
        this.currentValue += this.prop_step;
       },
       //       
       handleChange(event) {
        var val = event.target.value.trim();
        var max = this.max;
        var min = this.min;
        if(isValueNumber(val)) {
         val = Number(val);
         if(val > max) {
          this.currentValue = max;
         }
         if(val < min) {
          this.currentValue = min;
         }
         this.currentValue = val;
         console.log(this.value);
        }else {
         event.target.value = this.currentValue;
        }
       },
       //     ,      
       handleChange2(event) {
        console.log(event.keyCode)
        if(event.keyCode == '38') {
         this.currentValue ++;
        }
        if(event.keyCode == '40') {
         this.currentValue --;
        }
       }
    
      },
      //        ,  value    
      mounted: function() {
       
       this.updataValue(this.value);
      }
    
    
     })
     var app = new Vue({
      el:'#app',
      data:{
       value: 5
      }
     })
    </script>
    以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。