Vue表单类的父子组件数据传递示例_vue.js_脚本之家
使用Vue.js進(jìn)行項(xiàng)目開發(fā),那必然會使用基于組件的開發(fā)方式,這種方式的確給開發(fā)和維護(hù)帶來的一定的便利性,但如果涉及到組件之間的數(shù)據(jù)與狀態(tài)傳遞交互,就是一件麻煩事了,特別是面對有一大堆表單的頁面。
在這里記錄一下我平時(shí)常用的處理方式,這篇文章主要記錄父子組件間的數(shù)據(jù)傳遞,非父子組件主要通過Vuex處理,這篇文章暫時(shí)不作說明。
與文檔里給的方案一樣,父組件向子組件傳遞數(shù)據(jù)主要通過 props,子組件向父組件傳遞數(shù)據(jù)主要通過觸發(fā)器 $emit(),只是在用法上會有些不同。
1、傳遞基本類型數(shù)據(jù)
當(dāng)子組件內(nèi)容較少時(shí),會直接傳遞基本類型數(shù)據(jù),通常為String, Number, Boolean三種。
先看個(gè)例子:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <!-- 父組件 parent.vue --> ? <template> ??<div class="parent"> ????<h3>問卷調(diào)查</h3> ????<child v-model="form.name"></child> ????<div class=""> ??????<p>姓名:{{form.name}}</p> ????</div> ??</div> </template> ? <script> ??import child from './child.vue' ? ??export default { ????components: { ??????child ????}, ????data () { ??????return { ????????form: { ??????????name: '請輸入姓名' ????????} ??????} ????} ??} </script> |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <!-- 子組件 child.vue --> ? <template> ??<div class="child"> ????<label> ??????姓名:<input type="text" :value="currentValue" @input="changeName"> ????</label> ??</div> </template> ? <script> ??export default { ????props: { ??????// 這個(gè) prop 屬性必須是 valule,因?yàn)?v-model 展開所 v-bind 的就是 value ??????value: '' ????}, ????methods: { ??????changeName (e) { ????????// 給input元素的 input 事件綁定一個(gè)方法 changeName ????????// 每次執(zhí)行這個(gè)方法的時(shí)候都會觸發(fā)自定義事件 input,并且把輸入框的值傳遞進(jìn)去。 ????????this.$emit('input', e.target.value) ??????} ????} ??} </script> |
給子組件的 input 事件綁定一個(gè)方法 changeName,每次執(zhí)行這個(gè)方法的時(shí)候都會觸發(fā)自定義事件 input,并且把輸入框的值傳遞進(jìn)去。
父組件通過 v-model 指令綁定一個(gè)值,來接收子組件傳遞過來的數(shù)據(jù)。但這樣只是父組件響應(yīng)子組件的數(shù)據(jù),如果還要子組件響應(yīng)父組件傳遞的數(shù)據(jù),就需要給子組件定義一個(gè)props屬性 value,并且這個(gè)屬性必須是 value,不能寫個(gè)其它單詞。
v-model 其實(shí)就是一個(gè)語法糖,詳情可以參考使用自定義事件的表單輸入組件。
2、傳遞引用類型數(shù)據(jù)
當(dāng)子組件里的內(nèi)容比較多時(shí),比如子組件有多個(gè)表單元素,如果還像上面那樣給每個(gè)表單元素綁定值,那就要寫很多重復(fù)代碼了。所以這個(gè)時(shí)候通常傳遞的是一個(gè)對象,傳值的基本原理不變,不過寫法上會有些不同。
還是先看代碼:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <!-- 父組件 parent.vue --> ? <template> ??<div class="parent"> ????<h3>問卷調(diào)查</h3> ????<child :formData.sync="form"></child> ????<div class=""> ??????<p>姓名:{{form.name}}</p> ????</div> ??</div> </template> ? <script> ??import child from './child.vue' ? ??export default { ????components: { ??????child ????}, ????data () { ??????return { ????????form: { ??????????name: '請輸入姓名', ??????????age: '21' ????????} ??????} ????} ??} </script> |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | <!-- 子組件 child.vue --> ? <template> ??<div class="child"> ????<label> ??????姓名:<input type="text" v-model="form.name"> ????</label> ????<label> ??????年齡:<input type="text" v-model="form.age"> ????</label> ????<label> ??????地點(diǎn):<input type="text" v-model="form.address"> ????</label> ??</div> </template> ? <script> ??export default { ????data () { ??????return { ????????form: { ??????????name: '', ??????????age: '', ??????????address: '' ????????} ??????} ????}, ????props: { ??????// 這個(gè) prop 屬性接收父組件傳遞進(jìn)來的值 ??????formData: Object ????}, ????watch: { ??????// 因?yàn)椴荒苤苯有薷?props 里的屬性,所以不能直接把 formData 通過v-model進(jìn)行綁定 ??????// 在這里我們需要監(jiān)聽 formData,當(dāng)它發(fā)生變化時(shí),立即將值賦給 data 里的 form ??????formData: { ????????immediate: true, ????????handler (val) { ??????????this.form = val ????????} ??????} ????}, ????mounted () { ??????// props 是單向數(shù)據(jù)流,通過觸發(fā) update 事件綁定 formData, ??????// 將 data 里的 form 指向父組件通過 formData 綁定的那個(gè)對象 ??????// 父組件在綁定 formData 的時(shí)候,需要加上 .sync ??????this.$emit('update:formData', this.form) ????} ??} </script> |
props 是單向數(shù)據(jù)流,當(dāng)我們需要對 props 內(nèi)的屬性進(jìn)行雙向綁定時(shí),就需要用到.sync 修飾符,詳情請參考.sync 修飾符,這里不做贅述。
這里需要注意的是,vue 中是不能直接修改 props 的,所以如果我們要向父組件傳值,還是需要通過修改 data 里的值,prop 只是作為父子之間通話的中間人存在。
另外,如果我們想要預(yù)覽父組件最開始傳的數(shù)據(jù),就需要通過 watch 監(jiān)聽 prop 的變化,在子組件初始化的時(shí)候就把值傳進(jìn)去。
注意:?我在子組件里把 this.$emit('update:formData', this.form) 放在 mounted 當(dāng)中的,其原因是為了避免在每個(gè) input 標(biāo)簽的 input 事件中觸發(fā)自定義事件,但這樣寫的前提是,父子組件都要共用一個(gè)對象。
這也就是上面代碼中,父組件中使用 :formData.sync="form" 綁定值時(shí),form 是一個(gè)對象,而子組件中的觸發(fā)自定義事件 this.$emit('update:formData', this.form) ,this.form 也得是一個(gè)對象。
這里還需要注意的是,如果有多個(gè)子組件使用一個(gè)對象,那就要避免這種寫法,因?yàn)橐粋€(gè)組件修改了這個(gè)對象的數(shù)據(jù),那么其它子組件也就都跟著改變了。
所以我在用的時(shí)候都是給每個(gè)子組件分配了一個(gè)自己的對象,比如:
| 1 2 3 4 5 6 7 8 | data () { ?return { ??parentObject: { ???child_1_obj: {}, ???child_2_obj: {}, ??} ?} } |
這是在父組件里定義的數(shù)據(jù),當(dāng)然名字不會這樣取了。
結(jié)尾
也沒什么說的了,對 Vue 還是處于使用的階段,對其底層的東西了解還不夠,我也好想讀讀源碼,但總只是想想.....大家覺得有什么不妥的地方盡管說,大家相互交流交流。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的Vue表单类的父子组件数据传递示例_vue.js_脚本之家的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android实现圆角照片和圆形照片
- 下一篇: [软件工程] 面向对象方法学引论