前言
嗯,偶爾看看學習Vue 3技能啦,此前用過Vue 2做過一點東西,Vue 3已面世一段時間,于是乎,我來看看所遇到的問題是否在Vue 3中得到解決,首先,我們來講講一個例子在Vue 2中的實作,舉個栗子吧,開發過程中我們隻會用到省、市、區,這裡的區也可以看做是三、四線城市中的縣,若我們想要基于縣動态建立鎮、村,更有甚者,在全國各地在鎮下還劃分不同的區域,我們通過Vue結合ElementUI來實作此例子
Vue 2 + ElementUI
由于示例代碼比較多,這裡我們首先直接看效果,如下:

具體代碼如下所示,太多?忽略不看,我們隻講解核心問題
<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">添加鎮</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)">移除鎮</el-button>
</el-col>
</el-row>
<el-row style="margin:20px 0 20px 0;">
<el-col :span="4">
鎮名稱
</el-col>
<el-col :span="19">
<el-input maxlength="30" v-model="town.townName" placeholder="請輸入鎮名稱"></el-input>
</el-col>
</el-row>
<el-row style="margin-bottom:20px;">
<el-col :span="4">
區域、村
</el-col>
<el-col :span="20">
<el-radio-group v-model="town.option">
<el-radio @change="dynamicAddRegion(tindex)" label="添加區域"></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="請輸入區域名稱"></el-input>
</el-col>
<el-col :span="5" style="margin-right:20px;">
<el-tooltip class="item" effect="dark" content="輸入村名稱并回車,即可連續添加" placement="top">
<el-input size="small" maxlength="30" v-model="region.villageName" @keyup.enter.native="getVillage(tindex, rindex)" placeholder="請輸入村名稱"></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)">追加區域</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)">移除區域</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>
直接看如下定義資料結構可得知,存在三層周遊,第一層周遊從鎮開始,第二層周遊從鎮下區域開始,最後一層周遊則是區域下的村(即上述标簽)
form: {
areaId: 0,
towns: [
{
townName: '',
regions: [{
regionTitle: '',
regionName: '',
villageName: '',
tags: []
}]
}
]}
在Vue 2中一直存在的問題則是無法監聽數組,若我沒記錯的話,Vue 2是通過Object.defineProperty()來監聽對象,也就是背景語言中對應的屬性get和set方法。結合上述示例圖和代碼,當我們輸入村名稱時,然後回車,則将村名稱添加到村數組中去,然後通過el-tag标簽進行周遊渲染
接下來問題來了,此時我們想要删除村,是以點選村标簽的删除圖示,毫無疑問直接将區域下的村數組通過索引将其移除即可,但是,但是,根本無法移除,因為此時區域下的村是一個數組,Vue 2無法監聽得到,也就是我們在數組中給對應村移除時,但頁面上無法同步删除,移除方法如下:
handleClose (tindex, rindex, tagindex) {
let self = this
let region = self.form.towns[tindex].regions[rindex]
region.tags.splice(tagindex, 1)
}
那麼在Vue 2中如何解決這個問題呢?根據我們的示例來看,我們将輸入的村名稱即文本框綁定回車事件,然後将文本框綁定的模型資料添加到村數組中去,是以此時我們假裝先再次在文本框上綁定一個“占位符”,然後緊接着将其置空,給Vue 2一種“錯覺”剛才的資料沒綁定上,是以上述删除标簽方法,變成如下即可解決:
handleClose (tindex, rindex, tagindex) {
let self = this
let region = self.form.towns[tindex].regions[rindex]
region.tags.splice(tagindex, 1)
// 添加文本準備添加“一個占位符”,以便于頁面上能删除标簽
region.villageName = '占位符'
region.villageName = ''
}
Vue 3 + ElementPlus
空閑之餘,試了試Vue 3結合ElementPlus,這個問題得到了解決,在Vue 3中通過proxy(代理)方式監聽所有屬性,當然也就包括數組,然後在Vue 3中相關鍵盤事件等,比如回車,都已認證v-on:key.enter來綁定事件實作
總結
本文也是做做小demo遇到的問題,特此記錄下,其他倒沒什麼可以說的了,再會~~~~
你所看到的并非事物本身,而是經過诠釋後所賦予的意義