在Vue中,prop是能夠接受由父組件傳遞給子組件的屬性,但prop沒法進行修改的(因此我加了引號,嘿嘿)。html
若是prop被強制修改,會有警告⚠️vue
❝[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.markdown
❞
「因此,咱們只能「變相」地修改prop~」ide
固然,若是你對以上的話一臉懵逼能夠看看官網文檔關於Prop的內容函數
上面的警告大概意思說:單獨在子組件中修改數值,在父組件從新渲染更新的時候仍是傳同樣的值進去,形成一個重寫的狀況。oop
說得白話一點:哪一個組件定義數值,應該哪一個組件定義方法(函數)進行修改。ui
和Vuex的狀態管理相似,爲何state中的數值只能由mutation進行修改操做,最核心的緣由——可回溯。this
只由一個「管理員」進行修改操做,避免多個不一樣身份進行修改操做,這樣就不會「亂套」了,而在狀態追溯時候只要看mutation作了什麼操做,這樣就會一目瞭然。spa
那天然,若是傳遞給子組件的prop數據是在父組件上定義,那修改的prop的數據的方法(函數)能夠在父組件中定義。雙向綁定
<!--父組件-->
<template> <div> <Child :propNum="num" @propFun="changeNum"/> </div> </template> <script> // 引入 src/components/Child // 引入要根據文件目錄進行修改 import Child from '@/components/Child' export default { components: { // 註冊組件 Child }, data () { return { // 定義num數值 num: 0 } }, methods: { // 定義修改數值方法 changeNum () { this.num = this.num + 1 } } } </script> 複製代碼
<!--子組件-->
<template> <div> <span> {{propNum}} </span> <button type="button" @click="onClick"> add </button> </div> </template> <script> export default { props: { propNum: { // 接受父子組件傳遞的屬性 type: Number, default: 0 } }, methods: { onClick () { // 在點擊按鈕觸發,父組件傳遞給子組件的方法 this.$emit('propFun') } } } </script> 複製代碼
「注意!是vue 2.30以上才能使用,由於剛開始的vue2.0廢除的這個修飾符 官網文檔」
這裏也寫一個和上述相似的例子
<!--父組件-->
<template> <div> <Child :propNum.sync="num"/> </div> </template> <script> // 引入 src/components/Child // 引入要根據文件目錄進行修改 import Child from '@/components/Child' export default { components: { Child }, data () { return { num: 0 } } } </script> 複製代碼
<!--子組件-->
<template> <div> <span> {{propNum}} </span> <button type="button" @click="onClick"> add </button> </div> </template> <script> export default { props: { propNum: { type: Number, default: 0 } }, methods: { onClick () { const num = this.propNum + 1 // 定義num數值 this.$emit('update:propNum', num) // 傳遞更新數值 } } } </script> 複製代碼
和vue封裝好v-mode的不一樣,如下使用的是自定義組件的v-model
「固然仍是要注意使用版本:2.20+」
<!--父組件-->
<template> <div> <Child v-model="num"/> </div> </template> <script> // 引入 src/components/Child // 引入要根據文件目錄進行修改 import Child from '@/components/Child' export default { components: { Child }, data () { return { num: 0 } } } </script> 複製代碼
<!--子組件-->
<template> <div> <span> {{propNum}} </span> <button type="button" @click="onClick"> add </button> </div> </template> <script> export default { model: { prop: 'propNum', // v-model選擇prop中傳遞名 event: 'changeNum' // 定義事件 }, props: { propNum: { type: Number, default: 0 } }, methods: { onClick () { const num = this.propNum + 1 this.$emit('changeNum', num) // 使用$emit觸發事件並傳值 } } } </script> 複製代碼
以上三種方法均可以「變相修改」props,其中使用父子組件傳值是引用「定義狀態同時定義修改狀態方法」,然後兩中.sync和v-model則是使用「雙向綁定」。
彷佛第一種好像還能夠理解,但後兩種又怎麼驗證呢?,其實只在父和子組件加上使用watch,如在使用.sync修飾符上加watch:
<!--父組件-->
<template> <div> <Child :propNum.sync="num"/> </div> </template> <script> // 引入 src/components/Child // 引入要根據文件目錄進行修改 import Child from '@/components/Child' export default { components: { Child }, data () { return { num: 0 } }, watch: { // 監聽父組件num屬性 num: { handler () { console.log('父組件num', this.num) } } } } </script> 複製代碼
<!--子組件-->
<template> <div> <span> {{propNum}} </span> <button type="button" @click="onClick"> add </button> </div> </template> <script> export default { props: { propNum: { type: Number, default: 0 } }, methods: { onClick () { const num = this.propNum + 1 // 定義num數值 this.$emit('update:propNum', num) // 傳遞更新數值 } }, watch: { // 監聽子組件propNum屬性 propNum: { handler () { console.log('子組件propNum', this.propNum) } } } } </script> 複製代碼
運行,點擊add按鈕就有如下結果
相似使用自定義組件但v-model,也能夠使用這種方法驗證,你們能夠自行驗證,就再也不贅述~
感謝閱讀