Vue 2升级 Vue 3初探小细节

前言

嗯,偶尔看看学习Vue 3技能啦,此前用过Vue 2做过一点东西,Vue 3已面世一段时间,于是乎,我来看看所遇到的问题是否在Vue 3中得到解决,首先,我们来讲讲一个例子在Vue 2中的实现,举个栗子吧,开发过程中我们只会用到省、市、区,这里的区也可以看做是三、四线城市中的县,若我们想要基于县动态创建镇、村,更有甚者,在全国各地在镇下还划分不同的区域,我们通过Vue结合ElementUI来实现此例子

Vue 2 + ElementUI

由于示例代码比较多,这里我们首先直接看效果,如下:

Vue 2升级 Vue 3初探小细节

 

具体代码如下所示,太多?忽略不看,我们只讲解核心问题

<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>&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;</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升级 Vue 3初探小细节

 

接下来问题来了,此时我们想要删除村,所以点击村标签的删除图标,毫无疑问直接将区域下的村数组通过索引将其移除即可,但是,但是,根本无法移除,因为此时区域下的村是一个数组,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遇到的问题,特此记录下,其他倒没什么可以说的了,再会~~~~

Vue 2升级 Vue 3初探小细节

上一篇:char和varchar的区别


下一篇:简易版跳板机-teleport使用