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