vue2組件之間雙向數據綁定問題

最近在使用element-ui的dialog組件二次封裝成獨立組件使用時,子組件須要將關閉dialog狀態返回給父組件,簡單的說就是要實現父子組件之間的數據雙向綁定問題。html

大體代碼以下:vue

1,父組件vuex

<template>
  <button @click="openDialog">打開彈窗</button>
  <dialogCompenent :show="result" :result="result" @dialogData="closeDialog"></dialogCompenent>
</template>
<script type="text/babel">
import dialogCompenent from '/dialogCompenent'
export default {
  data () {
    return {
      result: false
    }
  },
  components: {
    dialogCompenent
  },
  methods: {
    openDialog () {
      this.result = true
    },
    closeDialog (data) {
      this.result = data
    }
  }
}
</script>

2,子組件 childCompenentelement-ui

<template>
<el-dialog
  title="彈框組件"
  :visible.sync="result"
  @open="doOpen"
  @close="doClose"
  :show="result"
  size="tiny">
  <div class="content-wrapper">
    具體業務代碼...
  </div>
</el-dialog>
  </div>
</template>
<script type="text/babel">
  import videoApi from '../../api/videoApi/videoApi'
  export default {
    name: 'dialogCompenent',
    props: {
      result: Boolean
    },
    methods: {
      doOpen () {
        ...
      },
      doClose () {
        this.$emit('dialogData', false)
        ...
      }
    }
  }
</script>

程序在瀏覽器上雖然可以正常運行,可是在vue2.0卻會報錯:api

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: 
"result" (found in component )

組件內不能修改props的值,同時修改的值也不會同步到組件外層,即調用組件方不知道組件內部當前的狀態是什麼瀏覽器

這是什麼緣由形成的呢?緩存

在vue1.x版本中利用props的twoWay和.sync綁定修飾符就能夠實現props的雙向數據綁定。babel

在vue2.0中移除了組件的props的雙向數據綁定功能,若是須要雙向綁定須要本身來實現。
在vue2.0中組件的props的數據流動改成了只能單向流動,即只能由(父組件)經過組件的v-bind:attributes傳遞給(子組件),子組件只能被動接收父組件傳遞過來的數據,並在子組件內不能修改由父組件傳遞過來的props數據。app

官方文檔解釋:ide

prop 是單向綁定的:當父組件的屬性變化時,將傳導給子組件,可是不會反過來。這是爲了防止子組件無心修改了父組件的狀態——這會讓應用的數據流難以理解。

雖然廢棄了props的雙向綁定對於整個項目總體而言是有利且正確的,可是在某些時候咱們確實須要從組件內部修改props的需求

在Vue2.0中,實現組件屬性的雙向綁定方式

子組件修改:

<template>
    <el-dialog
      title="彈框組件"
      :visible.sync="openStatus"
      @open="doOpen"
      @close="doClose"
      :show="openStatus"
      size="tiny">
      <div class="content-wrapper">
        具體業務代碼...
      </div>
    </el-dialog>
  </div>
</template>
<script type="text/babel">
  import videoApi from '../../api/videoApi/videoApi'
  export default {
    name: 'dialogCompenent',
    props: {
      result: Boolean
    },
    /*建立一個openStatus變量緩存result數據
    *在子組件須要調用result的地方調用data對象openStatus
    */
    data () {
      return {
        openStatus: this.result
      }
    },
    //新增result的watch,監聽變動同步到openStatus
    //監聽父組件對props屬性result的修改,並同步到組件內的data屬性
    watch: {
      result (val) {
        this.openStatus = val
      }
    },
    methods: {
      doOpen () {
        ...
      },
      doClose () {
        this.$emit('dialogData', false)//子組件對openStatus修改後向父組件發送事件通知
        ...
      }
    }
  }
</script>

父組件修改:

<template>
  <button @click="openDialog">打開彈窗</button>
  <dialogCompenent :show="result" :result="result" @dialogData="closeDialog"></dialogCompenent>
</template>
<script type="text/babel">
import dialogCompenent from '/dialogCompenent'
export default {
  data () {
    return {
      result: false
    }
  },
  components: {
    dialogCompenent
  },
  methods: {
    openDialog () {
      this.result = true
    },
    closeDialog (data) {
      this.result = data//子組件觸發父組件事件,進行數據變動,同步result數據
    }
  }
}
</script>

至此,實現了子組件內數據與父組件的數據的雙向綁定,組件內外數據的同步。最後歸結爲一句話就是:組件內部本身變了告訴外部,外部決定要不要變。

結語
那麼爲何vue1.0還有的數據雙向綁定在vue2.0版本中反而拋棄了呢,經過上述案例咱們也能夠發現雙向綁定的props代碼多,不利於組件間的數據狀態管理,尤爲是在複雜的業務中更是如此,因此儘可能不使用這種方式的雙向綁定,過於複雜的數據處理使用vuex來進行數據管理。(https://vuex.vuejs.org/zh-cn/...

相關文章
相關標籤/搜索