1. 程式人生 > >vue自定義元件實現v-model雙向繫結

vue自定義元件實現v-model雙向繫結

vue中父子元件通訊,都是單項的,直接在子元件中修改prop傳的值vue也會給出一個警告,接下來就用一個小列子一步一步實現了vue自定義的元件實現v-model雙向繫結,父元件值變了子元件也會跟著變,子元件中傳過來的值變了,父元件值也會跟著變化。如有錯誤的地方歡迎評論指出

父級元件

<template>
  <div>
    <p>我是父級元件</p>
    <p>父級元件內容:{{ text }}</p>
    <p><button @click="onChange">改變內容<
/button></p> <hr> <child v-model="text"></child> </div> </template> <script> import Child from './child' export default { components: { Child }, data() { return { text: '我是父級元件的內容' } }, methods: { onChange() { this
.text = '我是由父級元件觸發改變了內容' } } } </script> <style scoped> </style>

子元件

<template>
  <div>
    <p>我是子元件</p>
    <p>子元件內容:{{ value }}</p>
    <p><button @click="onChange">改變內容</button></p>
  </div>
</template>

<
script> export default { props: { //此處一定要用value value: { type: String } }, methods: { onChange() { this.value = '我是由子元件觸發改變了內容' } } } </script> <style scoped> </style>

預覽

vue自定義元件實現v-model雙向繫結
這時候我們點選父級元件中的改變內容按鈕,發現一切正常,沒有問題
vue自定義元件實現v-model雙向繫結
然後我們再點選子元件中的改變內容按鈕,發現父級元件沒變化,子元件雖然變了,但是vue給出了警告,因為是單向資料流,子元件不應該直接修改prop傳的值。難道就沒喲辦法了嗎,辦法肯定是有的,繼續往下看。
vue自定義元件實現v-model雙向繫結
只需要將程式碼稍微改造下,如下,在data中頂一個myValue值,指向prop傳過來的value,點選按鈕改變內容的時候,改變myValue的值,這樣vue就不會給出警告了。

<template>
  <div>
    <p>我是子元件</p>
    <p>子元件內容:{{ myValue }}</p>
    <p><button @click="onChange">改變內容</button></p>
  </div>
</template>

<script>
export default {
  props: {
    //此處一定要用value
    value: {
      type: String
    }
  },
  data() {
    return {
      myValue: this.value
    }
  },
  methods: {
    onChange() {
      this.myValue = '我是由子元件觸發改變了內容'
    }
  }
}

</script>
<style scoped>
</style>

此時還沒完,發現子元件的內容變了,父級元件的內容卻沒有變化,點選父級元件的改變內容按鈕後,子元件的內容也沒變化,繼續對程式碼進行改造
vue自定義元件實現v-model雙向繫結
vue自定義元件實現v-model雙向繫結
最終改造後的程式碼如下,重點是加個watch,監聽父元件傳過來的value和子元件的myValue

<template>
  <div>
    <p>我是子元件</p>
    <p>子元件內容:{{ myValue }}</p>
    <p><button @click="onChange">改變內容</button></p>
  </div>
</template>
<script>
export default {
  props: {
    //此處一定要用value
    value: {
      type: String
    }
  },
  data() {
    return {
      myValue: this.value
    }
  },
  methods: {
    onChange() {
      this.myValue = '我是由子元件觸發改變了內容'
    }
  },
  watch: {
    //監聽prop傳的value,如果父級有變化了,將子元件的myValue也跟著變,達到父變子變的效果
    value(newVal) {
      this.myValue = newVal
    },
    //監聽myValue,如果子元件中的內容變化了,通知父級元件,將新的值告訴父級元件,我更新了,父級元件接受到值後頁就跟著變了
    //參考官網:https://cn.vuejs.org/v2/guide/components-custom-events.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E7%9A%84-v-model
    myValue(newVal) {
      this.$emit('input', newVal)
    }
  }
}
</script>
<style scoped>
</style>

看下動態效果圖,父變子變,子變父變,也沒有報錯警告。
vue自定義元件實現v-model雙向繫結
甚至還可以加個input框,也是沒有問題的
vue自定義元件實現v-model雙向繫結