基于 vue 封装 横向滑动 tab栏 组件
基于vue封装的横向滚动tab栏组件
知识点:1,父子组件传值 ,2,vue如何获取dom元素(ref,$refs),3,点击高亮,4,获取屏幕宽度(window.innerWidth),5,左偏移量(offsetLeft),6,当前元素宽度(offsetWidth),7,左滚动(scrollLeft);
有两种写法:一,逻辑代码在父组件中实现(本篇);二,逻辑代码在子组件中实现(第二篇博客中); 如果一个项目中多次使用,建议采用第二种。
界面效果 (可横向滑动)
父组件
<template> <div class="home"> <header-tab :listArray="list" :current="current" @change="changeTab" ref="tab" > <img :src="imgSrc" alt="" slot="header_tab_img" /> </header-tab> </div> </template> <script> import HeaderTab from "../components/HeaderTab"; export default { name: "home", components: { HeaderTab, }, data() { return { list:[], current: 1, imgSrc: "", }; }, created() { this.getlist(); this.imgSrc = require("../assets/img/search.png"); }, methods: { getlist() { this.list = [ { id: 1, name: "关注" }, { id: 2, name: "推荐" }, { id: 3, name: "科技" }, { id: 4, name: "财经" }, { id: 5, name: "生活" }, { id: 6, name: "职场" }, { id: 7, name: "时尚" }, { id: 8, name: "汽车" }, { id: 9, name: "娱乐" }, ]; }, changeTab(index, e) { this.current = index; // 高亮当前 let tab = this.$refs.tab.$refs.headertab; // 包裹 ul的 div let tabitem = this.$refs.tab.$refs.tabitem; // 包裹 li的 ul let winWidth = window.innerWidth; // 当前屏幕的宽度 let liList = e.target; // 当前点击的li if (liList) { // 当前li左偏移, li的宽度, 中间值(当前屏幕的宽度 - li的宽度) /2, 目标值 (中间值 - 当前li左偏移), 整个ul的宽度 let liLeft = liList.offsetLeft, liWidth = liList.offsetWidth, liCenter = (winWidth - liWidth) / 2, liTarget = liLeft - liCenter; let ulWidth = tabitem.offsetWidth; if (liTarget < 0) { tab.scrollLeft = 0; return; } // winWidth(375) - ulWidth(436) = -61 if (liTarget < winWidth - ulWidth) { tab.scrollLeft = -(winWidth - ulWidth) + liWidth; return; } tab.scrollLeft = liTarget; } }, }, }; </script> <style lang="less"></style>
子组件
<template> <div class="header"> <div class="header_tab" ref="headertab"> <ul ref="tabitem"> <li v-for="(item, index) in listArray" :key="index" :class="index == current ? 'activeheader' : ''" @click="getTab(index, $event)" > {{ item.name }} </li> </ul> </div> <div class="header_search"> <slot name="header_tab_img"></slot> </div> </div> </template> <script> export default { name: "HeaderTab", props: { listArray: { type: Array, }, current:{ type:Number, default:1, } }, data() { return { }; }, methods: { getTab(index, e) { this.$emit('change',index,e) }, }, }; </script> <style lang="less"> .header { width: 100%; height: 45px; background-color: #fff; display: flex; } .header_tab { width: 90%; height: 45px; display: flex; flex-wrap: nowrap; overflow: scroll; } .header_tab::-webkit-scrollbar { display: none; } ul { display: inline-block; white-space: nowrap; } li { display: inline-block; line-height: 45px; padding: 0px 10px; font-size: 14px; color: #333; // 点击高亮某一项时,将原来的字体变大,会导致没有高亮的元素距离上面有空隙,会出现纵向滚动条 margin-top: -1px; } .activeheader { font-size: 16px; font-weight: 700; position: relative; } .activeheader:after { position: absolute; content: ""; width: 35%; height: 2px; bottom: 0; left: 15px; background-color: #333; border-radius: 50px; } .header_search { width: 10%; height: 45px; position: relative; } .header_search img { position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; } </style>