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

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM