标题动态滑块的设计与实现逻辑vue3+tailwindcss

662 阅读1分钟

实现如图的一个滑块效果:

vmgqe-cxkln.gif

先讲思路:

整体的思路就是,两个图层上面一个是标题列表图层、下面一个是滑块的图层,当点击事件发生的时候滑块移动到对应标题下面

这里面有2个问题,我们怎么知道滑块应该移动到的对应文字的距离,还有就是怎么知道滑块的宽度的大小

实现步骤:

  • 用v-for渲染出标题List
  • 选中item的下标
  • 所有的item元素
  • ul的横向滚动偏移量
  • 最后点击事件发生改变时候,获取循环列表的下标元素的left和width,以及来计算滑块位置和宽度

1、构建dom结构(注意!我这里是tailwindCss来构建css样式)

<div class="bg-white sticky top-0 left-0 z-10">
<ul
  ref="ulTarget" //获取ul的dom结构后面来计算偏移量
  class="relative flex overflow-auto p-2 pr-10 text-md text-zinc-800"
>

    //背景滑块
  <li
    :style="sliderStyle" //动态绑定滑块的样式用来设置滑块的动态宽度和过度平移位置class="h-[24px] top-2.5 rounded-3xl transition absolute bg-black duration-400"
  ></li>
  
  //循环出标题列表
  <li
    :ref="sliderTarget"
    v-for="(item, index) in home.categoryList"
    :key="index"
    class="shrink-0 px-2 py-0.5 z-10 mx-2 cursor-default"
    @click="changeAction(index)"//点击事件用来确定点击的是那个标签
    :class="action === index ? 'text-white duration-500' : ' '"//标签激活状态
  >
    {{ item.title }}
  </li>
</ul>
</div>

2、用js来控制变化

//设置active当点击事件changeAction触发的时候,渲染对应的样式
let action = ref(0);
const changeAction = (index) => {
  action.value = index;
};

//初始化滑块的样式
const sliderStyle = ref({
  transform: "translateX(2px)",
  width: "60px",
});

//存储将li存储到一个空数组里面
let itemRef = [];
const sliderTarget = (el) => {
  if (el) {
    itemRef.push(el);
  }
};
onBeforeUpdate(() => {
  itemRef = [];
});

const ulTarget = ref(null);
//可以获取ul标签的滚动偏移量位置,
//这个useScroll函数是vueuse的一个hook可以多学习一下很有效率
const { x } = useScroll(ulTarget);
//监听action变化
watch(action, (val) => {
//getBoundingClientRect方法返回一个 [`DOMRect`]对象,其提供了元素的大小及其相对于[视口]的位置。
  const { left, width } = itemRef[val].getBoundingClientRect();
  const res = itemRef[val].getBoundingClientRect();
  sliderStyle.value = {
    transform: `translateX(${x.value + left - 14}px)`,//计算偏移量
    width: `${width + 12}px`,//计算宽度
  };
});