Vue 2升級(jí) Vue 3初探小細(xì)節(jié)
本文轉(zhuǎn)載自微信公眾號(hào)「JeffckyShare」,作者Jeffcky。轉(zhuǎn)載本文請(qǐng)聯(lián)系JeffckyShare公眾號(hào)。
首先,我們來(lái)講講一個(gè)例子在Vue 2中的實(shí)現(xiàn),舉個(gè)栗子吧,開(kāi)發(fā)過(guò)程中我們只會(huì)用到省、市、區(qū),這里的區(qū)也可以看做是三、四線城市中的縣,若我們想要基于縣動(dòng)態(tài)創(chuàng)建鎮(zhèn)、村,更有甚者,在全國(guó)各地在鎮(zhèn)下還劃分不同的區(qū)域,我們通過(guò)Vue結(jié)合ElementUI來(lái)實(shí)現(xiàn)此例子
Vue 2 + ElementUI
由于示例代碼比較多,這里我們首先直接看效果,如下:
具體代碼如下所示,太多?忽略不看,我們只講解核心問(wèn)題
- <el-dialog :modal="dialogModal" :title="townTitle" @close="closeDialog" :visible.sync="dialogVisible" :close-on-click-modal="false" width="800px" top="10vh" center>
- <el-row>
- <el-form label-width="40px" ref="form" size="mini">
- <el-form-item>
- <el-button size="small" @click="createMultipleTown" icon="el-icon-plus">添加鎮(zhèn)</el-button>
- </el-form-item>
- <el-form-item v-for="(town, tindex) in form.towns" :key="tindex" style="border: 1px dashed #AAAAAA;margin:10px 0 20px 0;">
- <el-row style="margin:20px 0 20px 0;">
- <el-col :span="19">
- <el-button type="danger" size="small" icon="el-icon-delete" @click="removeTown(tindex)">移除鎮(zhèn)</el-button>
- </el-col>
- </el-row>
- <el-row style="margin:20px 0 20px 0;">
- <el-col :span="4">
- 鎮(zhèn)名稱(chēng)
- </el-col>
- <el-col :span="19">
- <el-input maxlength="30" v-model="town.townName" placeholder="請(qǐng)輸入鎮(zhèn)名稱(chēng)"></el-input>
- </el-col>
- </el-row>
- <el-row style="margin-bottom:20px;">
- <el-col :span="4">
- 區(qū)域、村
- </el-col>
- <el-col :span="20">
- <el-radio-group v-model="town.option">
- <el-radio @change="dynamicAddRegion(tindex)" label="添加區(qū)域"></el-radio>
- <el-radio label="添加村" @change="dynamicAddVillage(tindex)"></el-radio>
- </el-radio-group>
- </el-col>
- </el-row>
- <el-row v-for="(region, rindex) in town.regions" :key="rindex" style="margin-bottom:20px;">
- <el-row>
- <el-col :span="4">
- {{region.regionTitle}}
- </el-col>
- <el-col :span="5" style="margin-right:20px;" v-show="town.townRegionVisible">
- <el-input size="small" maxlength="30" v-model="region.regionName" placeholder="請(qǐng)輸入?yún)^(qū)域名稱(chēng)"></el-input>
- </el-col>
- <el-col :span="5" style="margin-right:20px;">
- <el-tooltip class="item" effect="dark" content="輸入村名稱(chēng)并回車(chē),即可連續(xù)添加" placement="top">
- <el-input size="small" maxlength="30" v-model="region.villageName" @keyup.enter.native="getVillage(tindex, rindex)" placeholder="請(qǐng)輸入村名稱(chēng)"></el-input>
- </el-tooltip>
- </el-col>
- <el-col :span="5" v-show="!town.townRegionVillageVisible">
- <el-button size="small" icon="el-icon-plus" @click="continueAddRegion(tindex)">追加區(qū)域</el-button>
- </el-col>
- <el-col :span="3" v-show="!town.townRegionVillageVisible" style="width:100px;">
- <el-button size="small" type="danger" icon="el-icon-delete" @click="removeRegion(tindex, rindex)">移除區(qū)域</el-button>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="4">
- <span> </span>
- </el-col>
- <el-col :span="20">
- <el-tag :key="tagindex" v-for="(tag, tagindex) in region.tags" closable :disable-transitions="false" style="margin:10px 10px 0 0;" @close="handleClose(tindex, rindex, tagindex)">
- {{tag}}
- </el-tag>
- </el-col>
- </el-row>
- </el-row>
- </el-form-item>
- </el-form>
- </el-row>
- <el-row v-show="saveButtonVisible">
- <el-col :span="20">
- <span> </span>
- </el-col>
- <el-col :span="2">
- <el-button @click="save" type="primary">確定</el-button>
- </el-col>
- <el-col :span="1">
- <el-button @click="cancel">取消</el-button>
- </el-col>
- </el-row>
- </el-dialog>
直接看如下定義數(shù)據(jù)結(jié)構(gòu)可得知,存在三層遍歷,第一層遍歷從鎮(zhèn)開(kāi)始,第二層遍歷從鎮(zhèn)下區(qū)域開(kāi)始,最后一層遍歷則是區(qū)域下的村(即上述標(biāo)簽)
- form: {
- areaId: 0,
- towns: [
- {
- townName: '',
- regions: [{
- regionTitle: '',
- regionName: '',
- villageName: '',
- tags: []
- }]
- }
- ]}
在Vue 2中一直存在的問(wèn)題則是無(wú)法監(jiān)聽(tīng)數(shù)組,若我沒(méi)記錯(cuò)的話,Vue 2是通過(guò)Object.defineProperty()來(lái)監(jiān)聽(tīng)對(duì)象,也就是后臺(tái)語(yǔ)言中對(duì)應(yīng)的屬性get和set方法
結(jié)合上述示例圖和代碼,當(dāng)我們輸入村名稱(chēng)時(shí),然后回車(chē),則將村名稱(chēng)添加到村數(shù)組中去,然后通過(guò)el-tag標(biāo)簽進(jìn)行遍歷渲染
接下來(lái)問(wèn)題來(lái)了,此時(shí)我們想要?jiǎng)h除村,所以點(diǎn)擊村標(biāo)簽的刪除圖標(biāo),毫無(wú)疑問(wèn)直接將區(qū)域下的村數(shù)組通過(guò)索引將其移除即可,但是,但是,根本無(wú)法移除,因?yàn)榇藭r(shí)區(qū)域下的村是一個(gè)數(shù)組,Vue 2無(wú)法監(jiān)聽(tīng)得到,也就是我們?cè)跀?shù)組中給對(duì)應(yīng)村移除時(shí),但頁(yè)面上無(wú)法同步刪除,移除方法如下:
- handleClose (tindex, rindex, tagindex) {
- let self = this
- let region = self.form.towns[tindex].regions[rindex]
- region.tags.splice(tagindex, 1)
- },
那么在Vue 2中如何解決這個(gè)問(wèn)題呢?根據(jù)我們的示例來(lái)看,我們將輸入的村名稱(chēng)即文本框綁定回車(chē)事件,然后將文本框綁定的模型數(shù)據(jù)添加到村數(shù)組中去,所以此時(shí)我們假裝先再次在文本框上綁定一個(gè)“占位符”,然后緊接著將其置空,給Vue 2一種“錯(cuò)覺(jué)”剛才的數(shù)據(jù)沒(méi)綁定上,所以上述刪除標(biāo)簽方法,變成如下即可解決:
- handleClose (tindex, rindex, tagindex) {
- let self = this
- let region = self.form.towns[tindex].regions[rindex]
- region.tags.splice(tagindex, 1)
- // 添加文本準(zhǔn)備添加“一個(gè)占位符”,以便于頁(yè)面上能刪除標(biāo)簽
- region.villageName = '占位符'
- region.villageName = ''
- },
Vue 3 + ElementPlus
空閑之余,試了試Vue 3結(jié)合ElementPlus,這個(gè)問(wèn)題得到了解決,在Vue 3中通過(guò)proxy(代理)方式監(jiān)聽(tīng)所有屬性,當(dāng)然也就包括數(shù)組,然后在Vue 3中相關(guān)鍵盤(pán)事件等,比如回車(chē),都已通過(guò)v-on:key.enter來(lái)綁定事件實(shí)現(xiàn)