欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue實現(xiàn)無限輪播效果時動態(tài)綁定style失效的解決方法

 更新時間:2024年08月06日 08:30:07   作者:尖椒土豆sss  
最近在開發(fā)中遇到了一個新需求:列表輪播滾動,實現(xiàn)方式也有很多,比如使用第三方插件,但是由于不想依賴第三方插件,想自己實現(xiàn),于是我開始了嘗試,但是在這個過程中遇到了動態(tài)綁定style樣式不生效,所以本文介紹了Vue實現(xiàn)無限輪播效果時動態(tài)綁定style失效的解決方法

前言

最近在開發(fā)中遇到了一個新需求:列表輪播滾動;這個需求其實是比較常見的,實現(xiàn)方式也有很多,比如使用第三方插件:vue-seamless-scroll,但是由于不想依賴第三方插件,想自己實現(xiàn),于是我開始了嘗試,但是在這個過程中遇到了動態(tài)綁定style樣式不生效、綁定值與渲染值不一致等問題。謹以此篇記錄自己的學(xué)習(xí)過程,也希望可以幫助到其他同學(xué)。

基礎(chǔ)代碼如下

創(chuàng)建一個 scroll.vue 組件,內(nèi)容如下:

  • html
<div class="domScroll">
 <div
      :class="['scroll-content', rollClass]">
      <slot></slot>
      <slot></slot>
 </div>
</div>
  • js
 export default {
  data() {
    return {
      rollClass: ""
    };
  }
 }
  • css樣式
<style lang="less" scoped>
.domScroll {
  overflow: hidden;
}
</style>

實現(xiàn)方式1(不推薦)

tableScroll() {
  this.$nextTick(() => {
    const tabDom = this.$el.querySelector(".scroll-content");
    const rowOffsetHeight = this.$el.querySelector(".row-item")
          .offsetHeight;;
    setInterval(() => {
      const shift = this.data[0];
        setTimeout(() => {
          this.data.push(shift);
          tabDom.style.transition = "all .5s";
          tabDom.style.marginTop = `-${rowOffsetHeight}px`;
        }, 500);
        setTimeout(() => {
          this.data.splice(0, 1);
          tabDom.style.transition = "all 0s ease 0s";
          tabDom.style.marginTop = "0";
        }, 1000);
    }, 1500);
  });
}

代碼分析

  • rowOffsetHeight:獲取列表 item 高度,這通常是單行的高度,用于后續(xù)計算滾動的位移。

  • 獲取 data 數(shù)組中的第一個元素,這個元素將在滾動時移動到列表的底部

  • 第一個setTimeout

    延遲 500 毫秒后執(zhí)行以下操作:

    • this.data.push(shift) :將第一個元素添加到 data 數(shù)組的末尾,模擬循環(huán)移動。
    • tabDom.style.transition = "all .5s" :設(shè)置過渡效果為 0.5 秒,表示 marginTop 的變化將有動畫效果。
    • tabDom.style.marginTop = -${rowOffsetHeight}px`` :將 tabDom 的上邊距設(shè)置為負的行高度,造成看似向上滾動的效果。
  • 第二個 setTimeout延遲 1000 毫秒后執(zhí)行以下操作:

    • this.data.splice(0, 1) :移除 data 數(shù)組中的第一個元素,完成滾動。
    • tabDom.style.transition = "all 0s ease 0s" :取消過渡效果,確保下次滾動時沒有延遲。
    • tabDom.style.marginTop = "0" :將 marginTop 重置為 0,以準(zhǔn)備下一次滾動。

主要是通過不停的將第一條數(shù)據(jù)添加到數(shù)組末尾、然后刪除當(dāng)前第一條數(shù)據(jù),同時添加刪除動畫樣式來實現(xiàn)滾動效果。這種方式添加刪除時會出現(xiàn)停頓卡頓的現(xiàn)象。

實現(xiàn)方式2(推薦)

初始化方法

    init() {
      const scrollContent = this.$el.querySelector(".scroll-content");
      if (scrollContent) {
        const offsetHeight = scrollContent.offsetHeight;
        const scrollClass = this.setScrollClass(offsetHeight / 2, this.speed);
        this.rollClass = scrollClass;
      }
    },

首先通過 this.$el.querySelector(".scroll-content"); 獲取到目標(biāo)dom元素,如果該dom存在,獲取其 offsetHeight值。

然后調(diào)用 setScrollClass方法傳參:

  • offsetHeight / 2是dom的一半高度
  • speed 輪播速度

最后將返回值設(shè)置給全局變量 rollClass

setScrollClass方法

    setScrollClass(offsetHeight, speed) {
      const uid = Math.random().toString(36).substring(2, 5);
      const style = document.createElement("style");
      style.innerHTML = `
        @keyframes listRowup${uid} {
          0% {
            -webkit-transform: translate3d(0, 0, 0);
            transform: translate3d(0, 0, 0);
          }
          100% {
            -webkit-transform: translate3d(0, -50%, 0);
            transform: translate3d(0, -50%, 0);
          }
        }
        .rowup-${uid} {
          -webkit-animation: ${Math.floor(
            (offsetHeight * 1000) / speed
          )}ms listRowup${uid} linear infinite normal;
          animation: ${Math.floor(
            (offsetHeight * 1000) / speed
          )}ms listRowup${uid} linear infinite normal;
        }
      `;
      document.getElementsByTagName("head")[0].appendChild(style);
      return `rowup-${uid}`;
    }

該函數(shù)主要職責(zé):

  • 使用document.createElement("style")方法創(chuàng)建一個style標(biāo)簽并插入@keyframes動畫、class
  • 最終獲取 head 標(biāo)簽將生成的 style 標(biāo)簽插入
  • 返回生成的好的動畫class類名

組件使用

在主文件引入 scroll.vue

  • html
<Domscroll :height="140">
    <div class="listBox flex">
      <div
        v-for="item in scrollList"
        :key="item"
        class="item"
      >
        {{ item }}
      </div>
    </div>
</Domscroll>
  • js
computed: {
scrollList() {
  return [...this.list1,...this.list1]
}, 
data() {
return {
 list1: [
      "機構(gòu)類",
      "區(qū)域類",
      "國家類",
      "證照文書類",
      "業(yè)務(wù)對象類",
      "人員類",
      "法律法規(guī)類型",
      "金融類"
    ]
  }
}
  

需要注意的是這里需要將原數(shù)據(jù)拷貝成兩份數(shù)據(jù),我這里使用計算屬性+ 擴展運算符實現(xiàn) scrollList 方法返回雙份數(shù)據(jù)。

開始優(yōu)化

在上面方式1中的代碼已經(jīng)可以實現(xiàn)dom列表的無限滾動效果;但是可以看出來該代碼有優(yōu)化的空間。

  • 動態(tài)插入css動畫
  • 動態(tài)創(chuàng)建標(biāo)簽插入style

修改基礎(chǔ)代碼

添加: ref="scrollContent"

  • html
<div class="domScroll">
 <div
      ref="scrollContent"
      :class="['scroll-content']"
      :style="scrollSty">
      <slot></slot>
      <slot></slot>
 </div>
</div>

添加:scrollSty變量

  • js
 export default {
  data() {
    return {
      scrollSty: {
        animation: ""
      }
    };
  }
 }

將css動畫添加到css中

  • css樣式
<style lang="less" scoped>
.domScroll {
  overflow: hidden;
  @keyframes rowup {
    0% {
      -webkit-transform: translate(0, 0);
      transform: translate(0, 0);
    }
    100% {
      -webkit-transform: translate(0, -50%);
      transform: translate(0, -50%);
    }
  }
}
</style>

修改methods方法

  dynamicStyle(speed) {
      const scrollContent = this.$refs.scrollContent;
      const offsetHeight = scrollContent.offsetHeight / 2;
      const duration = Math.floor((offsetHeight * 1000) / speed);
      this.scrollSty = {
        animation: `${duration}ms listRowup linear infinite normal`,
        "-webkit-animation": `${duration}ms listRowup linear infinite normal`
      };
    },

代碼分析

  • 獲取dom
    通過 this.$refs.scrollContent 直接獲取組件的 DOM 元素

  • 計算偏移高度
    offsetHeight:獲取 scrollContent 元素的高度,并將其除以 2,計算出需要滾動的高度。這里因為動畫只需要滾動一半的內(nèi)容,因為我們的數(shù)據(jù)復(fù)制了兩份。

  • 計算動畫時間
    duration: 根據(jù) offsetHeight 和 speed 計算動畫的持續(xù)時間,公式為:

    • offsetHeight * 1000:將高度轉(zhuǎn)換為毫秒(假設(shè) speed 是以像素/秒為單位)
    • Math.floor:向下取整,確保持續(xù)時間是一個整數(shù)。

動畫參數(shù)

animation設(shè)置 CSS 動畫的屬性:

  • ${duration}ms:指定動畫持續(xù)時間(毫秒)。
  • listRowup:應(yīng)為 CSS 中定義的動畫名稱,表示動畫的具體效果。
  • linear:表示動畫的速度曲線是線性的。
  • infinite:表示動畫將無限循環(huán)。
  • normal:表示動畫的播放方向為正常方向(從開始到結(jié)束)。

遇到問題

當(dāng)在 mounted 中執(zhí)行 dynamicStyle方法時發(fā)現(xiàn)動畫沒有生效,檢查元素后發(fā)現(xiàn)確實成功綁定動畫了,但是為什么不生效呢?

于是將結(jié)果值與dom元素打印出來做對比:

發(fā)現(xiàn)動態(tài)綁定的style animation的屬性結(jié)果與預(yù)期(函數(shù)設(shè)置的style)綁定的值竟然不同! 我一臉懵逼,反復(fù)查看代碼發(fā)現(xiàn)沒有錯誤?。?/p>

嘗試解決

  • mounted 中使用 $nextTick(function(){})方法無效

  • 修改@keyframes動畫名稱無效

最終解決

  • 動畫css單獨寫一個style標(biāo)簽,不添加scoped
<style lang="less" scoped>
.domScroll {
  overflow: hidden;
}
</style>

<style>
 @keyframes rowup {
    0% {
      -webkit-transform: translate(0, 0);
      transform: translate(0, 0);
    }
    100% {
      -webkit-transform: translate(0, -50%);
      transform: translate(0, -50%);
    }
  }

</style>

經(jīng)過查資料分析發(fā)現(xiàn)原來是因為 style 標(biāo)簽的 scoped 屬性導(dǎo)致的動畫樣式的選擇器不匹配

scoped 樣式中生成的類名會自動生成唯一標(biāo)識符,瀏覽器無法找到這些動畫的定義,導(dǎo)致動畫效果無法生效!

比較推薦的方法就是將動畫樣式定義在全局樣式文件中,這樣可以確保 @keyframes 能夠被任何元素正確的引用使用。

以上就是Vue實現(xiàn)無限輪播效果時動態(tài)綁定style失效的解決方法的詳細內(nèi)容,更多關(guān)于Vue動態(tài)綁定style失效的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue之moment的使用方式

    vue之moment的使用方式

    這篇文章主要介紹了vue之moment的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • 詳解uniapp如何解決H5頁面雙標(biāo)題

    詳解uniapp如何解決H5頁面雙標(biāo)題

    Uniapp打包到線上,會出現(xiàn)雙標(biāo)題問題,原因是:通過地址鏈接訪問時,會有個瀏覽器自身的標(biāo)題,和uniapp自身的導(dǎo)航欄標(biāo)題重復(fù),本文給大家介紹了uniapp如何解決H5頁面雙標(biāo)題,需要的朋友可以參考下
    2024-10-10
  • Vue項目中引入字體文件的幾種方法總結(jié)

    Vue項目中引入字體文件的幾種方法總結(jié)

    在 Vue 項目中引入自定義字體文件,可以通過多種方式實現(xiàn),這取決于你的項目結(jié)構(gòu)、構(gòu)建工具以及字體文件的來源,本文將詳細介紹如何通過不同方法引入本地字體文件以及從外部引入字體,需要的朋友可以參考下
    2024-10-10
  • vue中實現(xiàn)點擊變成全屏及縮放功能

    vue中實現(xiàn)點擊變成全屏及縮放功能

    這篇文章主要介紹了vue中實現(xiàn)點擊變成全屏及縮放功能,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Vue中過濾器定義以及使用方法實例

    Vue中過濾器定義以及使用方法實例

    過濾器的功能是對要顯示的數(shù)據(jù)進行格式化后再顯示,其并沒有改變原本的數(shù)據(jù),只是產(chǎn)生新的對應(yīng)的數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于Vue中過濾器定義以及使用方法的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • Vue深入理解之v-for中key的真正作用

    Vue深入理解之v-for中key的真正作用

    為了給Vue一個提示,以便它能跟蹤每個節(jié)點的身份,從而重用和重新排序現(xiàn)有元素,你需要為每項提供一個唯一key屬性,下面這篇文章主要給大家介紹了關(guān)于Vue深入理解之v-for中key的真正作用,需要的朋友可以參考下
    2022-05-05
  • 詳解Vue的監(jiān)聽屬性

    詳解Vue的監(jiān)聽屬性

    這篇文章主要為大家介紹了Vue的監(jiān)聽屬性,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • vue項目實現(xiàn)圖形驗證碼

    vue項目實現(xiàn)圖形驗證碼

    這篇文章主要為大家詳細介紹了vue項目實現(xiàn)圖形驗證碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • vue代碼分割的實現(xiàn)(codesplit)

    vue代碼分割的實現(xiàn)(codesplit)

    這篇文章主要介紹了vue代碼分割的實現(xiàn)(codesplit),做了代碼分割后,會將代碼分離到不同的bundle中,然后進行按需加載這些文件,需要的朋友可以參考下
    2018-11-11
  • 從零實現(xiàn)一個vue文件解析器

    從零實現(xiàn)一個vue文件解析器

    本文就討論下怎么實現(xiàn)一個處理.vue文件的loader,以及用loader處理完.vue文件怎么把內(nèi)容渲染在瀏覽器上并實現(xiàn)簡單的響應(yīng)式,對vue文件解析器相關(guān)知識感興趣的朋友一起看看吧
    2022-06-06

最新評論