vue中v-model如何綁定多循環(huán)表達(dá)式實(shí)戰(zhàn)案例
一、存在問(wèn)題
在v-model
想綁定表達(dá)式 || 函數(shù)方法,發(fā)現(xiàn)控制臺(tái)報(bào)錯(cuò)了,不允許這波操作。
下面我們分析存在該問(wèn)題的原因和解決方法。
實(shí)戰(zhàn)經(jīng)驗(yàn)。
二、還原場(chǎng)景
有這樣子的數(shù)組對(duì)象結(jié)構(gòu)
const arr = [ { value: 'a' }, { value: 'b' } ] const item { a: 1, b: 2, __config__:{ required: false }, }
想循環(huán)arr數(shù)組,然后通過(guò)arr.value
去找item
里面的屬性,然后綁定在v-model
上。
理想效果是:
arr我們有兩個(gè)對(duì)象,就循環(huán)兩個(gè)出來(lái),通過(guò)arr[0].value
去尋找item的屬性。
<div> <van-switch v-model="item[arr[0].value]" /> <van-switch v-model="item[arr[1].value]" /> </div>
于是,我們可以很順利的??寫出遍歷
<div v-for="(cell, cellKey) in arr" :key="cellKey" > <van-switch v-model="item[cell.value]" /> </div>
需求提升
前面只是為下面做鋪墊,其實(shí)真實(shí)的場(chǎng)景會(huì)更復(fù)雜點(diǎn)。
數(shù)組對(duì)象結(jié)構(gòu)是這樣子的:
想通過(guò)arr.value
去找item里面的屬性,然后綁定在v-model
上。
現(xiàn)在的arr數(shù)組的對(duì)象不再是一層了,而是多層,如:
{ value: '__config__.required' }
這樣的結(jié)構(gòu)怎么在template上遍歷呢?
const arr = [ { value: 'a' }, { value: '__config__.required' } ] const item { a: 1, b: 2, __config__:{ required: false }, }
三、進(jìn)行分析
3.1 直接賦值法
于是,有了第一個(gè)想法,就是arr數(shù)組寫著:
{ value: '__config__.required' }
直接看v-for遍歷出來(lái)是怎么樣的。
<div v-for="(cell, cellKey) in arr" :key="cellKey" > <van-switch v-model="item[cell.value]" /> </div>
他不是在__config__
對(duì)象中去設(shè)置required
,而是把__config__.required
當(dāng)做一個(gè)屬性了。
v-model
不僅僅是語(yǔ)法糖,它還有副作用。
如果 v-model
綁定的是響應(yīng)式對(duì)象上某個(gè)不存在的屬性,那么 vue
會(huì)悄悄地增加這個(gè)屬性,并讓它響應(yīng)式。
很明顯,這個(gè)方法不行?,只適用于item.a
,不能支持多層item.__config__.required
。
再嘗試另外一種方法??。
3.2 通過(guò)方法解析
我想在v-model綁定一個(gè)函數(shù)專門來(lái)讓其value里面的'__config__.required'
取出。
理想是通過(guò)一個(gè)方法,比如叫_get方法,這個(gè)方法可以讓他處理成item['__config__']['required']
,這樣子我們就可以取到正確的值了。
開(kāi)干!
* @description 實(shí)現(xiàn) lodash 的_.get * * @param {Array/Object} source 目標(biāo)數(shù)組/對(duì)象 * @param {String} path 獲取對(duì)象的字符串路徑 * @param {*} [defaultValue=undefined] 若值為空,則可傳入默認(rèn)值作為返回值 * @return {*} * @example * const get1 = tool._get({ a: null }, "a.b.c", 3) // output: 3 const get2 = tool._get({ a: [{ b: 1 }] }, "a[0].b") // output: 1 */ _get(source, path, defaultValue = undefined) { // a[3].b -> a.3.b -> [a,3,b] // path 中也可能是數(shù)組的路徑,全部轉(zhuǎn)化成 . 運(yùn)算符并組成數(shù)組 const paths = path.replace(/\[(\d+)\]/g, ".$1").split(".") let result = source for (const p of paths) { // 注意 null 與 undefined 取屬性會(huì)報(bào)錯(cuò),所以使用 Object 包裝一下。 result = Object(result)[p] if (result == undefined) { return defaultValue } } return result }
然后在模板里面遍歷,通過(guò)_get解析取值。
<div v-for="(cell, cellKey) in arr" :key="cellKey" > <van-switch v-model="_get(item, cell.value)" /> </div> data(){ return { const arr = [ { value: 'a' }, { value: '__config__.required' } ] const item { a: 1, b: 2, __config__:{ required: false }, } } }
發(fā)現(xiàn)控制臺(tái)報(bào)錯(cuò)了。
v-model‘ directives require the attribute value which is valid as LHS
??中文翻譯: “v-model”指令要求屬性值必須與LHS一樣有效
?原因:v-model將始終把Vue實(shí)例的data視為數(shù)據(jù)真實(shí)的來(lái)源,你應(yīng)該在組件的JavaScript里的data中聲明初始值,這意味著你不能要求v-model一次觀察多個(gè)變量。
通俗易懂的說(shuō):你不能在v-model綁定函數(shù)或者表達(dá)式。
看來(lái),這個(gè)方法也?行不通,繼續(xù)探索解決方案??。
3.3 通過(guò)computed計(jì)算屬性
v-model 的值只能是一個(gè)變量。
值得一提,v-model
可以綁定計(jì)算屬性的值,因?yàn)橛?jì)算屬性也是data數(shù)據(jù)真實(shí)的數(shù)據(jù),是一個(gè)變量。
那我們就可以在computed
計(jì)算屬性里面去通過(guò)_get
方法解析取值。
<div v-for="(cell, cellKey) in arr" :key="cellKey" > <van-switch v-model="getItem" /> </div> computed:{ getItem(){ return _get(this.item, 寫啥) } }
我們可以發(fā)現(xiàn),寫不下去了,如果沒(méi)有v-for遍歷,只是一個(gè)值的話,就可以。
但是,咱們這里的遍歷的,我們不能在遍歷的時(shí)候,傳參數(shù)給計(jì)算屬性getItem
,傳了就變成方法了,就會(huì)報(bào)錯(cuò)。
計(jì)算屬性可以用,但在v-model不能傳參。
<van-switch v-model="getItem" /> // 我們不能寫 <van-switch v-model="getItem(item, cell.value)" />
看來(lái),計(jì)算屬性在我們這里是?行不通了,但計(jì)算屬性可以解決我們v-model不能去調(diào)用方法的問(wèn)題。
計(jì)算屬性還是可以很好的解決單個(gè)值寫表達(dá)式的。
3.4 two value
我想到一個(gè)最傻的方案。
就是寫兩個(gè)value,然后判斷一下,如下代碼:
<div v-for="(cell, cellKey) in arr" :key="cellKey" > <template v-if="cell.value1"> <van-switch v-model="item[cell.value][cell.value1]" /> </template> <template v-else> <van-switch v-model="item[cell.value]" /> </template> </div> data(){ return { const arr = [ { value: 'a' }, { value: '__config__', value1: 'required' } ] const item { a: 1, b: 2, __config__:{ required: false }, } } }
如果可以寫表達(dá)式,里面就不需要寫兩條了,直接寫:
<van-switch v-model="cell.value1 ? item[cell.value][cell.value1] : item[cell.value]" />
當(dāng)然,直接寫個(gè)方法來(lái)解析獲取__config__.required
會(huì)更好。
3.5 父子組件 + 計(jì)算屬性
有了以上的實(shí)踐,我們可以來(lái)總結(jié)一下目前的情況:
可以使用計(jì)算屬性寫表達(dá)式。
但局限于,我們的場(chǎng)景是循環(huán)的,那我們使用計(jì)算屬性的話需要傳參,但一旦傳參則認(rèn)為是方法,v-model無(wú)法支持。
我們可以想到,可以創(chuàng)建一個(gè)新的組件,然后組件內(nèi)接收每次循環(huán)的item,在新的組件里面寫v-model
綁定計(jì)算屬性。
Perfect完美。
代碼如下:
父組件
<div v-for="(cell, cellKey) in arr" :key="cellKey"> <Item :item="item" :cell="cell" /> </div> data(){ return { const arr = [ { value: 'a' }, { value: '__config__', value1: 'required' } ] const item { a: 1, b: 2, __config__:{ required: false }, } } }
子組件Item.vue
<div> <van-switch v-model="itemVal" /> </div> <script> props:['item', 'cell'] computed:{ itemVal(){ return this.cell.value1 ? this.item[this.cell.value][this.cell.value1] : this.item[this.cell.value] } }, </script>
于是,我們愉快的打開(kāi)頁(yè)面看下效果成功了沒(méi),發(fā)現(xiàn)控制臺(tái)吐了塊紅色的錯(cuò)誤。
Computed property "itemVal" was assigned to but it has no setter.
意思是:計(jì)算屬性 itemVal
被賦值了,但此它并未定義 set
方法 。
要解決這個(gè)問(wèn)題,首先要明確這個(gè)問(wèn)題出現(xiàn)的原因。這個(gè)警告是由于Vue的計(jì)算屬性內(nèi)部沒(méi)有set方法,即:計(jì)算屬性不支持值的修改(只能針對(duì)data中的值進(jìn)行計(jì)算)。
因?yàn)槲覀兪?code>v-model雙向綁定,所以會(huì)觸發(fā)到值的修改。
computed:{ itemVal:{ get(){ return this.cell.value1 ? this.item[this.cell.value][this.cell.value1] : this.item[this.cell.value] }, set(v){ if(this.cell.value1){ this.item[this.cell.value][this.cell.value1] = v }else{ this.item[this.cell.value] = v } } } },
如上面所示,只要手動(dòng)給計(jì)算屬性添加get和set方法的不同操作,這個(gè)警告就解決了。
那既然可以寫方法了,我們可以利用上面的_get
方法去解析,就不需要寫兩個(gè)value、value1
了,寫一個(gè)value: "__config__.required"
,通過(guò)_get
去解析即可。
后記
巧妙的利用計(jì)算屬性可以是變量,來(lái)為v-model
進(jìn)行綁定。
這是在開(kāi)發(fā)過(guò)程中的一些思路、一些嘗試點(diǎn)。
代碼總是一點(diǎn)一點(diǎn)優(yōu)化,有時(shí)候先把功能點(diǎn)走通,再花點(diǎn)時(shí)間看看,能不能優(yōu)化,精而再精??。
這也是在實(shí)際項(xiàng)目中真實(shí)遇到的場(chǎng)景。
到此這篇關(guān)于vue中v-model如何綁定多循環(huán)表達(dá)式的文章就介紹到這了,更多相關(guān)v-model綁定多循環(huán)表達(dá)式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- vue-router使用next()跳轉(zhuǎn)到指定路徑時(shí)會(huì)無(wú)限循環(huán)問(wèn)題
- vue循環(huán)中調(diào)用接口-promise.all();按順序執(zhí)行異步處理方式
- vue中v-for循環(huán)數(shù)組,在方法中splice刪除數(shù)組元素踩坑記錄
- vue?循環(huán)動(dòng)態(tài)設(shè)置ref并獲取$refs方式
- vue如何在for循環(huán)中設(shè)置ref并獲取$refs
- Vue中實(shí)現(xiàn)v-for循環(huán)遍歷圖片的方法
- vue中的循環(huán)遍歷對(duì)象、數(shù)組和字符串
- vue實(shí)現(xiàn)列表無(wú)縫循環(huán)滾動(dòng)
- vue中forEach循環(huán)的使用講解
- Vue3基礎(chǔ)篇之常用的循環(huán)示例詳解
相關(guān)文章
VUE 實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板的兩種方法
這篇文章主要介紹了VUE 實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板功能,本文通過(guò)兩種方法,給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-04-04Vue項(xiàng)目中如何使用Axios封裝http請(qǐng)求詳解
這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中如何使用Axios封裝http請(qǐng)求的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10axios?發(fā)?post?請(qǐng)求,后端接收不到參數(shù)的完美解決方案
這篇文章主要介紹了axios?發(fā)?post?請(qǐng)求,后端接收不到參數(shù)的解決方案,場(chǎng)景很簡(jiǎn)單,就是一個(gè)正常 axios post 請(qǐng)求,本文給大家分享問(wèn)題原因分析及解決方案需要的朋友可以參考下2022-12-12vue中優(yōu)雅實(shí)現(xiàn)數(shù)字遞增特效的詳細(xì)過(guò)程
項(xiàng)目中需要做數(shù)字滾動(dòng)增加的效果,一開(kāi)始很懵,研究了一下原理,發(fā)現(xiàn)很簡(jiǎn)單,下面這篇文章主要給大家介紹了關(guān)于vue中優(yōu)雅實(shí)現(xiàn)數(shù)字遞增特效的詳細(xì)過(guò)程,需要的朋友可以參考下2022-12-12vue2.x中monaco-editor的使用說(shuō)明
這篇文章主要介紹了vue2.x中monaco-editor的使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08Vue.js項(xiàng)目實(shí)戰(zhàn)之多語(yǔ)種網(wǎng)站的功能實(shí)現(xiàn)(租車)
這篇文章主要介紹了Vue.js項(xiàng)目實(shí)戰(zhàn)之多語(yǔ)種網(wǎng)站(租車)的功能實(shí)現(xiàn) ,需要的朋友可以參考下2019-08-08使用vue-print-nb打印el-table問(wèn)題總結(jié)
這篇文章主要介紹了使用vue-print-nb打印el-table問(wèn)題總結(jié),通過(guò)實(shí)例代碼介紹了vue-print-nb 打印功能,本文結(jié)合實(shí)例代碼講解的非常詳細(xì),感興趣的朋友一起看看吧2024-01-01