1. 程式人生 > 其它 >Vue中子元件通過v-model動態修改父元件中的值

Vue中子元件通過v-model動態修改父元件中的值

父子通訊中的子傳父-使用v-model實現雙向資料繫結

  • 現有需求:通過子元件中的輸入框來動態繫結父元件中data中的資料。

    • 程式碼實現

        1. 父元件使用porps來向子元件傳值
        2. 子元件通過自己定義的兩個屬性(number1,number2)來接受父元件的值(num1,num2)
        3. 通過v-model屬性將輸入框與子元件的number1和number2來進行繫結
    • 結果

      • 上面功能的實現的確沒有問題,但思路有問題,而且在一般情況下,vue是不建議通過這種方式來直接修改父元件中的值的。

      • 程式碼如下:

      <body>
        <div id="app">
          <cpn :number1="num1" :number2="num2"></cpn>
        </div>
      
        <template id="cpm">
          <div>
            <h2>props:{{number1}}</h2>
            <h2>data:{{dnumber1}}</h2>
            <input type="text" v-model="number1">
           
            <h2>props:{{number2}}</h2>
            <h2>data:{{dnumber2}}</h2>
            <input type="text" v-model="number2">
      
          </div>
        </template>
      
        <script>
          const app = new Vue({
            el: '#app',
            data: {
              num1: 1,
              num2: 0
            },
            components: {
              cpn: {
                template: '#cpm',
                props: {
                  number1: Number,
                  number2: Number
                },
              },
            },
          })
        </script>
      </body>
  • 執行截圖

反思:這樣雖然可以實現子元件向元件傳值,但這種方法在vue看來是極為不推薦的。

  • 程式碼改進
    • 程式碼實現
      • 在上面的基礎上,我在子元件中定義兩個data屬性(dnumber1,dnumber2),用來儲存父元件傳過來的值
      • 將input繫結的屬性從number1改為dnumber1,number2同理
<body>
  <div id="app">
    <cpn :number1="num1" :number2="num2"></cpn>
  </div>

  <template id="cpm">
    <div>
      <!-- 用來檢視父子元件中,值的變化情況 -->
      <h2>props:{{number1}}</h2>
      <h2>data:{{dnumber1}}</h2>
      <input type="text" v-model="dnumber1">
     
      <!-- 用來檢視父子元件中,值的變化情況 -->
      <h2>props:{{number2}}</h2>
      <h2>data:{{dnumber2}}</h2>
      <input type="text" v-model="dnumber2">
      
    </div>
  </template>

  <script>
    const app = new Vue({
      el: '#app',
      data: {
        num1: 1,
        num2: 0
      },
      components: {
        cpn: {
          template: '#cpm',
          props: {
            number1: Number,
            number2: Number
          },
          data() {
            return {
              dnumber1: this.number1,
              dnumber2: this.number2
            }

          }
        },
      },
    })
  </script>
</body>
  • 執行截圖

反思:這樣是不報錯了,但是父元件中的值沒有被修改呀,看來得使用自定義事件來向父元件傳值了!

  • 程式碼改進

    • 自元件使用$emit自定義事件建立一個自定義事件dnumber1change,dnumber2change,並將dnumber1,和dnumber2傳遞過去。

      • 父元件定義監聽函式number1chage,number2change,在這個函式中,將取得的值value傳遞給父元件data中的值,從而將num1,和num2的值進行修改。
<body>
  <div id="app">
    <cpn :number1="num1" :number2="num2" @dnumber1change="number1chage" @dnumber2change="number2change"></cpn>
  </div>

  <template id="cpm">
    <div>
      <!-- 用來檢視父子元件中,值的變化情況 -->
      <h2>props:{{number1}}</h2>
      <h2>data:{{dnumber1}}</h2>
      <input type="text" :value="dnumber1" @input="num1Input">
      <!-- 用來檢視父子元件中,值的變化情況 -->
      <h2>props:{{number2}}</h2>
      <h2>data:{{dnumber2}}</h2>
      <input type="text" :value="dnumber2" @input="num2Input">
    </div>
  </template>

  <script>
    const app = new Vue({
      el: '#app',
      data: {
        num1: 1,
        num2: 0
      },
      methods: {
        number1chage(value) {
          this.num1 = parseInt(value)
        },
        number2change(value) {
          this.num2 = parseInt(value)

        }
      },
      components: {
        cpn: {
          template: '#cpm',
          props: {
            number1: Number,
            number2: Number
          },
          data() {
            return {
              dnumber1: this.number1,
              dnumber2: this.number2
            }
          },
          methods: {
            num1Input(event) {
              this.dnumber1 = event.target.value;
              // 為了父元件可以修改值,發出一個事件
              this.$emit('dnumber1change', this.dnumber1);
            },
            num2Input(event) {
              this.dnumber2 = event.target.value;
              //  為了父元件可以修改值,發出一個事件
              this.$emit('dnumber2change', this.dnumber2);
            }
          }
        },
      }
    })
  </script>
</body>
      
  • 執行截圖

總結:v-model的本質

  1. < input type="text" v-model="dnumber1">
  2. < input type="text" v-bind:value="dnumber1" @input="dnumber1=$event.target.value">

下面的程式碼等同於上面的程式碼, 這也就是需求實現的關鍵