1. 程式人生 > >vue父子元件通過sync實現雙向繫結

vue父子元件通過sync實現雙向繫結

背景:

日常開發時,我們總會遇到需要父子元件雙向繫結的問題,但是考慮到元件的可維護性,vue中是不允許子元件改變父元件傳的props值的。那麼同時,vue中也提供了一種解決方案.sync修飾符。在此之前,希望你已經知道了vue中是如何通過事件的方式實現子元件修改父元件的data的。如果你對此還不瞭解父子元件如何通過$emit實現雙向通訊,那就點我先了解下吧

.sync修飾符:

首先我們知道,在子元件中可以通過$emit向父元件通訊,通過這種間接的方式改變父元件的data,從而實現子元件改變props的值。比如向下邊這這樣:

子元件使用$emit向父元件傳送事件:

this.$emit('update:title', newTitle)

父元件監聽這個事件並更新一個本地的資料title:

<text-document
  :title="title"
  @update:title="val => title = val"
></text-document>

為了方便這種寫法,vue提供了.sync修飾符,說白了就是一種簡寫的方式,我們可以將其當作是一種語法糖,比如v-on: click可以簡寫為@click。而上邊父元件的這種寫法,換成sync的方式就像下邊這樣:

<text-document
  :sync.title="title"
></text-document>

有沒有發現很清晰,而子元件中我們的寫法不變,其實這兩種寫法是等價的,只是一個語法糖而已,如果到這裡你還不太明白。下邊是個完整的demo,可以copy自己的專案中嘗試一下。相信你會恍然大悟。

子元件:

<template>
  <div>
    <input :value="name" @input="abc" type="text">
  </div>
</template>
<script>
  export default {
    props: {
      name: {
        type: String,
        required: true
      }
    },
    methods: {
      abc(e) {
        console.log(e.target.value);
        this.$emit('update:name', e.target.value);
      }
    }
  }
</script>

父元件:

<template>
  <div>
    <child :name.sync="name"></child>
    <button @click="al">點選</button>
    <button @click="change">改變</button>
  </div>
</template>

<script>
import child from './child'
export default {
  name: 'list',
  components: {
    child
  },
  data () {
    return {
      listItems: ['buy food', 'play games', 'sleep'],
      name: 'xiaoming'
    }
  },
  methods: {
    al() {
      alert(this.name);
    },
    change() {
      this.name = '123';
    }
  }
}
</script>

ok,當你執行起來時,就會發現這樣便實現了父子元件的雙向繫結。

引用型別實現雙向繫結:

如果你實在覺得$emit的實現方式麻煩,那也可以利用引用型別的特性,去實現雙向繫結,具體實現就是,將props傳入的值改為一個物件。這樣你在子元件裡邊無論如何修改這個物件的屬性,vue都檢測不到。但是不要去修改這個props物件。具體原因大家可以看一下js引用型別。這裡就不做demo展示了,畢竟是不推薦的做法。

總結:

sync修飾符,與我們平常使用$emit實現父子元件通訊沒有區別,只不過是寫法上方便一些。當然,利用引用型別的特性實現雙向繫結我認為也並非完全不可取。