最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用vue封裝一個自定義樣式的滾動條

 更新時間:2023年10月24日 08:25:15   作者:冂島  
眾所周知,當(dāng)容器高度固定而內(nèi)容部分高度超出容器高度時,瀏覽器會渲染出一個可以滾動并用于顯示剩余界面的條 -- 滾動條,它可以簡單的樣式修改,但是位置是固定的,無法移動,而我們需要改變位置的時候,它就不能滿足我們的需求了,這時我們可以自己手寫一個

話不多說,步入正題,先創(chuàng)建測試文件,測試手寫滾動條是否可用

// test.vue
<template>
    <div class="scrollLayout">
        <!-- 內(nèi)容 -->
        <div class="content" ref="content" @scroll="scroll">
            <template v-for="i in 30">
                <div style="width: 10rem; text-align: center">{{ i }}</div>
          </template>
        </div>
        <!-- 滾動條 -->
        <div class="scrollBar" ref="scrollBar">
            <div class="slider" :style="sliderStyle"></div>
        </div>
    </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const content = ref(null); // ref綁定的內(nèi)容元素
const scrollBar = ref(null); // ref綁定的手寫滾動條

const sliderHeight = ref(0); // 滑塊高度
const position = ref(0); // 手寫滾動條的位置
const sliderStyle = ref(`height:${sliderHeight}%;margin-top:${position}px;`);

const contentCH = ref(0); // content盒子高度
const contentSH = ref(0); // content內(nèi)容高度
const scrollBarCH = ref(0); // 滾動條高度
const activeScrollDistance = ref(0); // 內(nèi)容滾動的距離
const contentScrollDistance = ref(0); // 內(nèi)容滾動的距離

onMounted(() => {
  const { clientHeight, scrollHeight } = content.value;
  contentCH.value = clientHeight;
  contentSH.value = scrollHeight;
  scrollBarCH.value = scrollBar.value.clientHeight;
  sliderHeight.value = (clientHeight / scrollHeight) * 100;
  activeScrollDistance.value = scrollBarCH.value - scrollBarCH.value * (sliderHeight.value / 100);
  contentScrollDistance.value = contentSH.value - contentCH.value;
})
// 內(nèi)容滾動時
const scroll = () => {
  const { scrollTop } = content.value;
  position.value = (scrollTop * activeScrollDistance.value) / contentScrollDistance.value; // 滑塊需要滑動的距離
};
</script>

<style scoped>
.scrollLayout {
    position: relative;
    padding: 1rem;
    font-size: 1rem;
}

.content {
    height: 20rem;
    overflow: auto;
    background: skyblue;
}

.scrollBar {
    position: absolute;
    top: 0;
    right: 1rem;
    width: 5px; /* 滾動條的寬度 */
    height: 18rem; /* 滾動條的高度 */
    background-color: pink; /* 滾動條的顏色 */

}
.slider {
    width: 100%;
    background-color: palevioletred; /* 滑塊的顏色 */
    border-radius: 0.5rem; /* 滑塊圓角 */
}
</style>

獲取元素的 clientHeightscrollHeight 來計算滑塊的高度以及可滾動距離,通過scrollTop獲取滾動的距離通過 scroll 事件來監(jiān)聽內(nèi)容的滾動,從而實(shí)現(xiàn)一個簡單的手搓滾動條,下面開始封裝。

封裝前還要考慮到的問題:可否在同一頁面多次復(fù)用;內(nèi)容容器一般都是調(diào)接口數(shù)據(jù)進(jìn)行遍歷渲染,而v-for在渲染每個條目時是逐個插入到DOM中的,這說明vue會先創(chuàng)建一個空的父元素,并將每個條目插入到該父元素中,這意味著 通過用ref綁定父頁面的內(nèi)容容器provide給子組件,子組件inject到dom元素的scrollHeight 這種方法不可行。

我想了一個辦法,父頁面把內(nèi)容通過slot給子組件把接口數(shù)據(jù)父傳子,在子組件可以拿到接口數(shù)據(jù)和內(nèi)容dom的scrollHeight,然后用watch監(jiān)聽props的接口數(shù)據(jù),若發(fā)生變化,重新獲取scrollHeight即可。

父頁面使用setTimeout模擬接口:

// test.vue
<template>
  <div class="scrollLayout">
    <scroll :data="arrList">
      <template v-for="i in arrList">
        <div style="width: 10rem; text-align: center">num: {{ i.num }}</div>
      </template>
    </scroll>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import scroll from '../components/scroll.vue';

const arrList = ref([]);

setTimeout(() => {
  for (let i = 1; i <= 30; i++) {
    const obj = { num: i < 10 ? '0' + i : i };
    arrList.value.push(obj);
  }
}, 3000);
</script>

<style lang="scss" scoped>
.scrollLayout {
  height: 10rem;
  background: pink;
}
</style>

組件部分:

// scroll.vue
<template>
  <div class="scrollable">
    <div class="content" ref="content" @scroll="scroll">
      <slot></slot>
    </div>
    <div class="scrollBar" ref="scrollBar" :style="scrollBarStyle">
      <div class="slider" :style="sliderStyle"></div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, computed, watch, nextTick } from 'vue';

const props = defineProps({
  scrollColor: {
    type: String,
    default: '',
  },
  sliderColor: {
    type: String,
    default: '#000',
  },
  data: {
    type: Array,
    default: [],
  },
  right: {
    type: String,
    default: '0',
  },
});

const content = ref(null); // ref內(nèi)容
const scrollBar = ref(null); // ref滾動條

const contentCH = ref(0); // content盒子高度
const contentSH = ref(0); // content內(nèi)容高度
const scrollBarCH = ref(0); // 滾動條高度
const activeScrollDistance = ref(0); // 內(nèi)容滾動的距離
const contentScrollDistance = ref(0); // 內(nèi)容滾動的距離
const sliderHeight = ref(0); // 滑塊高度
const position = ref(0); // 滾動條滑動距離
const scrollBarStyle = computed(() => `right:${props.right}px;background:${props.scrollColor};`);
const sliderStyle = computed(() => `height:${sliderHeight.value}%;margin-top:${position.value}px;background:${props.sliderColor};`);

onMounted(() => {
  watch(
    () => props.data,
    () => {
      // nextTick確保在DOM更新完畢后再執(zhí)行
      nextTick(() => {
        const { clientHeight, scrollHeight } = content.value;
        console.log('容器的高度:', clientHeight, '內(nèi)容高度:', scrollHeight);
        contentCH.value = clientHeight;
        contentSH.value = scrollHeight;
        scrollBarCH.value = scrollBar.value.clientHeight;
        sliderHeight.value = (clientHeight / scrollHeight) * 100;
        activeScrollDistance.value = scrollBarCH.value - scrollBarCH.value * (sliderHeight.value / 100);
        contentScrollDistance.value = contentSH.value - contentCH.value;
      });
    },
    { immediate: true, deep: true }
  );
});
// 監(jiān)聽滾動
const scroll = () => {
  const { scrollTop } = content.value;
  position.value = (scrollTop * activeScrollDistance.value) / contentScrollDistance.value;
};
</script>

<style lang="scss" scoped>
.scrollable {
  position: relative;
  display: flex;
  height: 100%;
  overflow: hidden;
}

.content {
  height: 100%;
  overflow: auto;

  &::-webkit-scrollbar {
    display: none;
  }
}
.scrollBar {
  position: absolute;
  top: 0;
  width: 5px;
  height: 100%;
  border-radius: 5px;

  .slider {
    width: 100%;
    border-radius: 3px;
  }
}
</style>

這樣就可以解決初始獲取的scrollHeight是內(nèi)容插入前的高度——即容器高度。

以上就是使用vue封裝一個自定義樣式的滾動條的詳細(xì)內(nèi)容,更多關(guān)于vue封裝滾動條的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 由淺入深講解vue2和vue3的區(qū)別

    由淺入深講解vue2和vue3的區(qū)別

    最近發(fā)現(xiàn)很多要求Vue3的技術(shù)了,不得不說it技術(shù)的更新真的太快了,作為vue2老用戶,我們在學(xué)習(xí)Vue3前應(yīng)該了解他們的區(qū)別以及背后的原因,下面這篇文章主要給大家介紹了關(guān)于vue2和vue3區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • vue3使用vuedraggable實(shí)現(xiàn)拖拽功能

    vue3使用vuedraggable實(shí)現(xiàn)拖拽功能

    這篇文章主要為大家詳細(xì)介紹了vue3使用vuedraggable實(shí)現(xiàn)拖拽功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 詳解Vue.js分發(fā)之作用域槽

    詳解Vue.js分發(fā)之作用域槽

    本篇文章主要介紹了詳解Vue.js分發(fā)之作用域槽,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • vue3實(shí)現(xiàn)v-model原理詳解

    vue3實(shí)現(xiàn)v-model原理詳解

    這篇文章主要介紹了vue3實(shí)現(xiàn)v-model原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • vue 虛擬dom的patch源碼分析

    vue 虛擬dom的patch源碼分析

    這篇文章主要介紹了vue 虛擬dom的patch源碼分析,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Vue?仿QQ左滑刪除組件功能

    Vue?仿QQ左滑刪除組件功能

    前幾天朋友在做vue項(xiàng)目開發(fā)時,有人反映?IOS?上面的滑動點(diǎn)擊有點(diǎn)問題,讓我們來幫忙解決,于是我就重寫了代碼,下面把vue仿qq左滑刪除組件功能分享到腳本之家平臺,需要的朋友參考下吧
    2018-03-03
  • vue實(shí)現(xiàn)前端展示后端實(shí)時日志帶顏色示例詳解

    vue實(shí)現(xiàn)前端展示后端實(shí)時日志帶顏色示例詳解

    這篇文章主要為大家介紹了vue實(shí)現(xiàn)前端展示后端實(shí)時日志帶顏色示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • vue自定義指令實(shí)現(xiàn)懶加載的優(yōu)化指南

    vue自定義指令實(shí)現(xiàn)懶加載的優(yōu)化指南

    這篇文章主要為大家詳細(xì)介紹了vue如何通過自定義指令實(shí)現(xiàn)懶加載并進(jìn)行相關(guān)優(yōu)化,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-07-07
  • 如何將iconfont圖標(biāo)引入到vant的Tabbar標(biāo)簽欄里邊

    如何將iconfont圖標(biāo)引入到vant的Tabbar標(biāo)簽欄里邊

    這篇文章主要介紹了如何將iconfont圖標(biāo)引入到vant的Tabbar標(biāo)簽欄里邊,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue中CSS動畫原理的實(shí)現(xiàn)

    Vue中CSS動畫原理的實(shí)現(xiàn)

    這篇文章主要介紹了Vue中CSS動畫原理的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02

最新評論

姜堰市| 师宗县| 政和县| 招远市| 西城区| 漯河市| 定西市| 仙桃市| 什邡市| 华坪县| 望谟县| 荔浦县| 万山特区| 鄂托克前旗| 雷波县| 仁怀市| 木里| 轮台县| 屯昌县| 北安市| 长丰县| 河间市| 乐山市| 景谷| 汶川县| 奉新县| 漳浦县| 德清县| 云龙县| 建德市| 定安县| 西乡县| 县级市| 张家港市| 乐都县| 重庆市| 仲巴县| 无棣县| 朔州市| 同江市| 丹棱县|