基於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>