Vant 源码解析——TreeSelect

本文深入探讨Vant TreeSelect组件的实现原理,包括组件的层级结构和使用的技术,如高亮选项索引和ID。并讨论了在实际项目中遇到的用户体验问题,提出对左侧导航栏和内容滚动的优化方案,通过调整滚动位置提升交互体验。同时,提供了实现此特性的关键代码片段。文章鼓励读者提出疑问和建议,并分享了作者的GitHub和源码地址。
摘要由CSDN通过智能技术生成

概述

本篇笔者来讲解一下 tree-select 的实现原理和细节处理,结合实际场景会对其进行拓展,以及优化用户体验问题,以便满足更多的业务场景。当然笔者会结合自身的理解,已经为每个核心的方法增加了必要的注释,会尽最大努力将其中的原理讲清楚,若有不妥之处,还望不吝赐教,欢迎批评指正。

预览

优化前 优化后
tree-select-before.gif tree-select-after.gif

原理

tree-select的层级主要由 侧边导航栏内容页(Content) 组成,层级结构也非常清晰明了,业务逻辑也比较简单,主要用到技术可能就是双向绑定,比如:main-active-index 表示左侧高亮选项的索引,active-id 表示右侧高亮选项的 id。

emit(ctx, 'update:main-active-index', index);
emit(ctx, 'update:active-id', newActiveId);

拓展

tree-select在我们项目中使用的还算高频,尽管组件易用,原理简单的同时,也存在些许美中不足,其主要还是用户体验的问题,本次tree-select拓展就是优化用户体验。项目中用户反馈最多的两个问题如下:

  • 左侧导航栏和右侧内容能滚动时,点击左侧选项和点击右侧选项时,能滚动到 tree-select 的中间位置。
  • 由于移动端大多数都是keep-alive模式,当tree-select可视时,左侧高亮选项和右侧选项也得可视。

上面看似两个问题,实则是一个问题,只要我们在用户点击左侧选项和点击右侧选项,以及在activated方法中,将此选项滚动到中间位置即可。具体实现如下,大家看看代码就会一目了然。


export default createComponent({
   
  props: {
   
    max: {
   
      type: [Number, String],
      default: Infinity,
    },
    items: {
   
      type: Array,
      default: () => [],
    },
    height: {
   
      type: [Number, String],
      default: 300,
    },
    activeId: {
   
      type: [Number, String, Array],
      default: 0,
    },
    selectedIcon: {
   
      type: String,
      default: 'success',
    },
    mainActiveIndex: {
   
      type: [Number, String],
      default: 0,
    },
  },

  data() {
   
    return {
   

    }
  },

  computed: {
   
    isMultiple(){
   
      return Array.isArray(this.activeId);
    }
  },

  watch: {
   
    // 也需要监听左侧导航栏索引的变化,但是滚动时不加动画,因为此值有可能是异步设置的
    mainActiveIndex(val) {
   
      // 这种场景直接滚动
      this.scrollIntoNavView(+val, true)
    },

    // 也需要监听右侧内容栏索引的的变化,但是滚动时不加动画,因为此值有可能是异步设置的
    activeId() {
   
      // 这种场景直接滚动
      this.scrollIntoContentView(this.getCurrentContentIndex(+this.mainActiveIndex), true)
    },

    // 数据源变化了 设置一下
    items(){
   
      this.init()
    }
  },

  async mounted() {
   
    await this.$nextTick()
    // 获取滚动器
    const {
    navScroller, scroller } = this.$refs
    this.navScroller = navScroller.$el
    this.scroller = scroller

    // 滚动指定的nav和content索引
    this.scrollToView(true)
  },

  activated() {
   
    this.scrollToView(true)
  },

  methods: {
   

    async init() {
   
      // 这里要置空
      this.lastScrollActiveId = null

      await this.$nextTick()

      // 滚动指定的nav和content索引
      this.scrollToView(true)
    },

    isActiveItem(id) {
   
      return this.isMultiple
        ? this.activeId.indexOf(id) !== -1
        : this.activeId === id;
    },


    renderContent() {
   
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值