van-tabs 组件不响应了?

简介: 本文主要讲van-tabs 组件不响应的解决方案

网络异常,图片无法展示
|


hello 大家好,🙎🏻‍♀️🙋🏻‍♀️🙆🏻‍♀️

我是一个热爱知识传递,正在学习写作的作者,ClyingDeng 凳凳!


问题阐述奇怪的。


事情是这样的:这其实是我的一个项目需求。点击导航右侧更多按钮,出现对话框,可以拖拽导航列表,更换导航栏顺序。看着是不难的,但是当拖拽完成之后,你就会发现页面上的导航栏并未发生任何变化。


网络异常,图片无法展示
|


关于项目


网络异常,图片无法展示
|


App 父组件


<van-tabs
    v-model="active"
    swipe-threshold="4"
    class="tab"
    title-active-color="#3693FF"
    color="#3693FF"
    title-inactive-color="#4A4A4A"
    @click-tab="chooseNav"
  >
    <van-tab v-for="item in navList" :key="item.name" :name="item.name" :title="item.title">
      <component :is="item.component" class="tabPanel"></component>
    </van-tab>
  </van-tabs>
</div>
<sort-nav
  :isSortNav="isSortNav"
  :list="navListClone"
  @newList="newList"
  @noSortshow="noSortshow"
></sort-nav>
// 在点击右上角触发弹框子组件时,给子组件传入`isSortNav`(控制弹框显示)、`navListClone`(拖拽列表绑定数据)


子组件


<van-popup
  v-model="isSortNav"
  round
  position="bottom"
  :style="{ height: '70%' }"
  :overlay-style="{ opacity: 0.5 }"
  :close-on-click-overlay="false"
  @click-overlay="noSortNav"
>
  <div class="sortContent">
      <div class="packUp">
        <img src="@/assets/arrowDown.png" alt="" />
      </div>
      <div class="dataTittle">
        <div>全部数据项</div>
        <div class="rightTittle">长按右侧拖拽可排序</div>
      </div>
      <div class="dataOption">
        <vue-draggable
          :list="list"
          class="list-group"
          ghost-class="ghost"
          @start="dragging = true"
          @end="dragging = false"
        >
          <div v-for="item in list" :key="item.name" class="list-group-item">
            <div class="list-item-left">
              <div class="list-item-icon">
                <img :src="require('@/assets/drag/' + item.name + '.png')" alt="" />
              </div>
              <div class="list-item-title">
                {{ item.title }}
              </div>
              <div class="list-item-annotation">
                {{ item.annotation }}
              </div>
            </div>
            <div class="list-item-drag">
              <van-icon name="wap-nav" />
            </div>
          </div>
        </vue-draggable>
      </div>
  </div>
</van-popup>


// 点击退出弹框,给父组件传入最新排序的数据
noSortNav() {
  this.$emit('noSortshow', !this.isSortNav)
  this.$emit('newList', this.list)
},


解决方案


该项目基于vue2 + vant + vuedraggable。


排查


组件通信


首先确保自己组件之间的通信是否成功,通过打印或者断点方式,查看父子组件接收和传入的参数:


网络异常,图片无法展示
|


检查后发现并没有任何问题。


tab数据绑定


接下来,检查tab导航数据是否绑定成功。 在nav导航上添加数据,查看导航绑定的数据是否成功被拖拽所更改。如下图:


网络异常,图片无法展示
|


可以看出数据是发生了变化,但是导航tab并未发生变化。


那么说明我的组件和拖拽使用的没有问题。那么可能就是vant tabs导航组件渲染的问题。


解决


既然是组件没有刷新绑定新的数据。那么我们很快就会想到,现将绑定的数据置空,然后再去赋值。 emmm。。。


实践证明该方法不可行!


那么我们可以通过强制tabs组件刷新,来重新渲染更新后的组件数据。

组件强制渲染有很多种方法:


$forceUpdate


迫使 Vue 实例重新渲染。注意它仅仅影响实例本身插入插槽内容的子组件,而不是所有子组件。


在上述情况中,使用$forceUpdate其实是无效的。因为重新渲染的是本身和插入插槽内容的子组件。而tabs组件是vant中已经封装好的,并不属于我们本身的插槽。

渲染失败!


改变key


我们看过vue内部的应该都知道,vue在重新渲染的是时候,是去对比它自身的key是否发生变化。那这样我们就会想到,给tabs组件绑定一个动态的key属性,在拖拽完成之后去改变这个key的值。


再试一下:

// van-tabs 组件绑定key为index,在父组件拿到子组件返回之后手动更新该组件的key值。
newList(val) {
  this.navList = val
  this.index++
},

网络异常,图片无法展示
|

ok,这个方法可行!


改变绑定数据


一开始赋值不行,那我等dom渲染完成之后呢?


既然想到要改变key,那么我们在拖拽完成之后,加一个nextTick是不是也可行呢? 在拖拽完成之后,置空绑定数据,再添加一个nextTick,在其内部去给绑定的数据重新赋值。


newList(val) {
  this.navList = []
  this.$nextTick(() => {
    this.navList = val
    console.log(this.active)
  })
}

网络异常,图片无法展示
|

ok,这方法也可行!


tab循环绑定index为key


需要key的改变的话,那我是不是也可以通过索引去匹配标签页呢? 当数据发生变化


<van-tabs
  v-model="active"
  swipe-threshold="4"
  class="tab"
  title-active-color="#3693FF"
  color="#3693FF"
  title-inactive-color="#4A4A4A"
  @click-tab="chooseNav"
>
  <van-tab
    v-for="(item, index) in navList"
    :key="index"
    :name="item.name"
    :title="item.title"
  >
    <component :is="item.component" class="tabPanel"></component>
  </van-tab>
</van-tabs>
<script>
newList(val) {
   this.navList = val
 },
</script>

网络异常,图片无法展示
|


ok,这方法也可行!


总结


van-tab组件对于json数组的导航数据,在内部,用唯一键标识(item.name)key值,其实在dom-diff新老节点作比较的时候,是默认其key属性是一样的。会进行头头、尾尾、头尾、尾头的比较,key值一样的时候会进行复用,导致导航栏不存在更新渲染。

vant中有这样一句话:在标签指定 name 属性的情况下,v-model 的值为当前标签的 name(此时无法通过索引值来匹配标签)。其实是比较建议绑定index的。


项目地址:github.com/ClyingDeng/…

目录
相关文章
|
索引
antd a-table表格添加序号和分页总数——基础积累
antd a-table表格添加序号和分页总数——基础积累
1315 0
|
JavaScript
vue项目获取本机局域网IP地址
局域网下获取本机 IP 地址方便访问 vue 项目
3270 0
JRebel-JVMTI [FATAL] Couldn‘t write to C:\Users\【完美解决方案】
JRebel-JVMTI [FATAL] Couldn‘t write to C:\Users\【完美解决方案】
JRebel-JVMTI [FATAL] Couldn‘t write to C:\Users\【完美解决方案】
使用Vant框架的组件van-pull-refresh搭配van-list和van-card完成上滑加载更多列表数据,下拉刷新当前列表数据(等同于翻页功能)
使用Vant框架的组件van-pull-refresh搭配van-list和van-card完成上滑加载更多列表数据,下拉刷新当前列表数据(等同于翻页功能)
|
JavaScript 前端开发 安全
VITE+TS项目中别名需要分别设置避免冲突
VITE+TS项目中别名需要分别设置避免冲突
727 1
|
JSON Dart 前端开发
鸿蒙应用开发从入门到入行 - 篇7:http网络请求
在本篇文章里,您将掌握鸿蒙开发工具DevEco的基本使用、ArkUI里的基础组件,并通过制作一个简单界面掌握使用
584 8
|
JavaScript API 开发者
关于维护vue3的响应式的那些事:unref、toRef、toRefs、toRaw、toValue
总结:Vue 3的Composition API提供的这些工具,大大增强了我们对响应式状态的操作能力,让状态管理变得更为灵活和高效。`unref`、`toRef`、`toRefs` 以及 `toRaw` 各有其用途和应用场景,灵活应用这些工具,将有助于开发出更为强大和响应式的Vue应用。在开发过程中,正确区分和使用这些API,能够有效提高开发效率以及应用的性能。
739 0
|
存储 Kubernetes 安全
Kubernetes 中的对象是如何删除的:Finalizers 字段介绍
Kubernetes 中的对象删除并不像表面上看起来那么简单,删除对象涉及一系列过程,例如对象的级联和非级联删除,在删除之前检查以确定是否可以安全删除对象等等。这些都是通过称为 `Finalizers`(终结器)的 API 对象实现的。
1428 0
Kubernetes 中的对象是如何删除的:Finalizers 字段介绍
|
JSON 小程序 前端开发
【微信小程序】-- 案例 - 自定义 tabBar(四十六)
【微信小程序】-- 案例 - 自定义 tabBar(四十六)
设置WebStorm查看本地源码文件个人修改的历史记录快捷键Alt+Shift+H、Ctrl+Shift+H(通常用于调试bug,发现文件出问题需要回溯到若干天之前)
设置WebStorm查看本地源码文件个人修改的历史记录快捷键Alt+Shift+H、Ctrl+Shift+H(通常用于调试bug,发现文件出问题需要回溯到若干天之前)