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

關(guān)于實(shí)現(xiàn)Vue3版抖音滑動(dòng)插件踩坑指南

 更新時(shí)間:2022年02月16日 09:02:07   作者:好學(xué)習(xí)吧丶  
這篇文章主要給大家介紹了關(guān)于實(shí)現(xiàn)Vue3版抖音滑動(dòng)插件踩坑指南,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue3具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

起步

年前單位需要搞一個(gè)類似抖音的需求,這本應(yīng)是客戶端的任務(wù),然而,不知天高地厚的我卻接了下來(lái),然而下細(xì)致調(diào)研之下,發(fā)現(xiàn)網(wǎng)上并沒(méi)有成熟的方案,但是卻又很多需求,各大論壇全是提問(wèn)的帖子,卻少有人回答和解決。

這一瞬間,俺慌了,畢竟單位的活,排期都是定死的,這時(shí)候臨陣退縮,實(shí)乃下下策。于是只能擼起袖子加油干。畢竟自己攬的事,含著淚也要干完,這就是男人,一個(gè)吐沫一個(gè)釘!

調(diào)研

大家知道,web端比起客戶端的劣勢(shì)有幾點(diǎn),想要做出類似客戶端的復(fù)雜的交互效果,需要考慮幾個(gè)問(wèn)題:

  • 1、性能--怎樣能達(dá)到最優(yōu)(當(dāng)然想要跟客戶端比肩這是不可能的)
  • 2、體驗(yàn)--怎樣達(dá)到客戶端的優(yōu)秀體驗(yàn),比如視頻緩沖怎么處理,初始化怎么處理,要不要視頻預(yù)加載
  • 3、兼容--ios 和安卓的設(shè)備以及他們各個(gè)版本之間的瀏覽器的實(shí)現(xiàn)都略有不同

而在我調(diào)研了抖音的web端、git上的一些開(kāi)源的相關(guān)項(xiàng)目、以及一些零零散散的回答之后,發(fā)現(xiàn)都不太匹配 他們?cè)趯?shí)現(xiàn)上,那么只能集幾百家之長(zhǎng)自己來(lái)了,既然自己來(lái)就需要針對(duì)當(dāng)前三個(gè)問(wèn)題來(lái)尋找既能解決問(wèn)題,又能快速實(shí)現(xiàn)的方案(畢竟有排期)

實(shí)現(xiàn)思路

在實(shí)現(xiàn)的初步設(shè)想中,我們不只需要解決問(wèn)題,其實(shí)也需要考慮一些架構(gòu)設(shè)計(jì),也就是你怎樣去將關(guān)注度分離,怎樣將組件的顆粒度拆的細(xì)致,能將每一個(gè)組件獨(dú)立出來(lái),外部單獨(dú)引用,怎樣將每一個(gè)組件做通用,方便日后維護(hù),并且還能快速開(kāi)發(fā),不耽誤排期,這其實(shí)就是你在這做也無(wú)需求之初需要去想的一些問(wèn)題,總結(jié)如下

  • 首先來(lái)說(shuō)毋庸置疑的是:要想實(shí)現(xiàn)滑動(dòng)的效果,現(xiàn)成的方案最快的就是swiper,swiper在web端的地位也是不可動(dòng)搖。
  • 其次原生video標(biāo)簽體驗(yàn)大家也都知道,一塌糊涂,那么這一塊也就需要自己實(shí)現(xiàn),比如進(jìn)度條,拖動(dòng),暫停播放,緩沖中等等內(nèi)容。并且類似抖音中的視頻上方的一些元素,比如點(diǎn)贊,分享等功能需要外部傳入,讓別的開(kāi)發(fā)者在使用時(shí)自己定制
  • 怎樣將組件的的結(jié)構(gòu)拆分出來(lái),能單獨(dú)打包上傳npm 供大家使用

組件設(shè)計(jì)的設(shè)想俺才疏學(xué)淺也就能想到這了,接下來(lái)就該解決在調(diào)研中發(fā)現(xiàn)的三個(gè)問(wèn)題:

  • 最容易解決的問(wèn)題就是兼容問(wèn)題,babel完美解決,cli工具命令行直接生成,swiper 在能實(shí)現(xiàn)功能的情況下盡量使用老的版本
  • 性能問(wèn)題是最難解決,如果渲染到很多視頻之后,難免會(huì)有很多的video存在于dom中,這里我們采用了web抖音的方案,在整個(gè)dom中只渲染一個(gè)活動(dòng)sidle的video其他的slide中渲染空節(jié)點(diǎn),這樣就能大大減少dom的數(shù)量,再配合vue的diff 能提供一個(gè)還算過(guò)得去的性能
  • 體驗(yàn)問(wèn)題雖然不難,但是僅僅靠前端是無(wú)法解決的,需要多方配合,他需要壓縮視頻大小,提供封面圖,增加緩沖效果,等等,而且不同的設(shè)備不同系統(tǒng)不同版本在video的表現(xiàn)差異還非常大,這其實(shí)是一個(gè)不可用技術(shù)解決的兼容問(wèn)題,那么,我們只能從交互上來(lái)解決問(wèn)題。

工程構(gòu)建

工程構(gòu)建為了裝逼上了最新的vite ,體驗(yàn)了一把,開(kāi)發(fā)體驗(yàn)確實(shí)是絲滑快速。由于vite天生支持庫(kù)的開(kāi)發(fā),只需要在vite.config.ts 添加build內(nèi)容即可

build: {
    lib: {
      entry: path.resolve(__dirname, 'src/components/index.ts'),
      name: 'videoSlide',
      fileName: (format) => `index.${format}.js`
    },
    rollupOptions: {
      // 確保外部化處理那些你不想打包進(jìn)庫(kù)的依賴
      external: ['vue'],
      output: {
        // 在 UMD 構(gòu)建模式下為這些外部化的依賴提供一個(gè)全局變量
        globals: {
          vue: 'Vue'
        }
      }
    }
  },

由于庫(kù)可能給ts大佬使用,需要安裝vite-plugin-dts 插件,來(lái)生成d.ts文件

代碼實(shí)現(xiàn)

由于視頻內(nèi)容和輪播部分的處理是兩個(gè)獨(dú)立的邏輯,所以將代碼拆分為兩個(gè)組件video.vue以及slide.vue

video實(shí)現(xiàn)

video的實(shí)現(xiàn)的基本思路就是重寫(xiě)原生video 標(biāo)簽?zāi)J(rèn)ui來(lái)達(dá)到自定義的目的,樣式就不在贅述,主要就是video提供的一些事件重寫(xiě)video默認(rèn)行為,這里簡(jiǎn)述下重點(diǎn)的函數(shù)

// vue
 <video
     
      playsinline="true"
      webkit-playsinline="true"
      mediatype="video"
      :poster="poster"
      @progress="progress"
      @durationchange="durationchange"
      @loadeddata="loadeddata"
      @playing="playing"
      @waiting="waiting"
      @timeupdate="timeupdate"
      @canplay="playing"
      @ended="ended"
    >
      <source :src="src" type="video/mp4" />
    </video>
    //js
    
   setup({ autoplay }) {
    // 是否是暫停狀態(tài)
    const paused = ref(true);
    // 視頻總時(shí)間
    const endTime = ref(second(0));
    //播放的時(shí)間
    const startTime = ref(second(0));
    // 是否是按下?tīng)顟B(tài)
    const isPress = ref(false);
    //緩沖進(jìn)度
    const percentageBuffer = ref(0);
    // 播放進(jìn)度
    const percentage = ref(0);
    // 保存計(jì)算后的播放時(shí)間
    const calculationTime = ref(0);
    // 拿到video 實(shí)例
    const video = ref(null);
    // 是否展示封面圖
    const showImg = ref(true);
    // 是否處于緩沖中
    const loading = ref(false);
    // 播放
    function play() {
      video.value.play();
      paused.value = false;
    }
    // 暫停
    function pause() {
      if (paused.value) return;
      video.value.pause();
      paused.value = true;
      loading.value = false;
    }
    // 獲取緩沖進(jìn)度
    function progress() {
      if (!video.value) return;
      percentageBuffer.value = Math.floor(
        (video.value.buffered.length
          ? video.value.buffered.end(video.value.buffered.length - 1) /
            video.value.duration
          : 0) * 100
      );
    }
    // 時(shí)間改變
    function durationchange() {
      endTime.value = second(video.value.duration);
      console.log("時(shí)間改變觸發(fā)");
    }
    // 首幀加載觸發(fā),為了獲取視頻時(shí)長(zhǎng)
    function loadeddata() {
      console.log("首幀渲染觸發(fā)");
      showImg.value = false;
      autoplay && play();
    }
    //當(dāng)播放準(zhǔn)備開(kāi)始時(shí)(之前被暫停或者由于數(shù)據(jù)缺乏被暫緩)被觸發(fā)
    function playing() {
      console.log("緩沖結(jié)束");
      loading.value = false;
    }
    //緩沖的時(shí)候觸發(fā)
    function waiting() {
      console.log("處于緩沖中");
      loading.value = true;
    }
    // 時(shí)間改變觸發(fā)
    function timeupdate() {
      // 如果是按下?tīng)顟B(tài)不能走進(jìn)度,表示需要執(zhí)行拖動(dòng)
      if (isPress.value || !video.value) return;
      startTime.value = second(Math.floor(video.value.currentTime));
      percentage.value = Math.floor(
        (video.value.currentTime / video.value.duration) * 100
      );
    }
    // 按下開(kāi)始觸發(fā)
    function touchstart() {
      isPress.value = true;
    }
    //松開(kāi)按鈕觸發(fā)
    function touchend() {
      isPress.value = false;
      video.value.currentTime = calculationTime.value;
    }
    // 拖動(dòng)的時(shí)候觸發(fā)
    function touchmove(e) {
      const width = window.screen.width;
      const tx = e.clientX || e.changedTouches[0].clientX;
      if (tx < 0 || tx > width) {
        return;
      }
      calculationTime.value = video.value.duration * (tx / width);
      startTime.value = second(Math.floor(calculationTime.value));
      percentage.value = Math.floor((tx / width) * 100);
    }
    //點(diǎn)擊進(jìn)度條觸發(fā)
    function handleProgress(e) {
      touchmove(e);
      touchend();
    }
    // 播放結(jié)束時(shí)觸發(fā)
    function ended() {
      play();
    }
    onMounted(() => {});
    return {
      video,
      paused,
      pause,
      play,
      progress,
      durationchange,
      loadeddata,
      endTime,
      startTime,
      playing,
      percentage,
      waiting,
      timeupdate,
      percentageBuffer,
      touchstart,
      touchend,
      touchmove,
      isPress,
      ended,
      handleProgress,
      loading,
      showImg,
    };
  },

需要注意的是,需要自定義內(nèi)容交給了使用者去自定義,全部通過(guò)插槽傳入當(dāng)前組件,這樣就方便了根據(jù)內(nèi)容自定義樣式了

slide.vue

slide.vue 就是處理滑動(dòng)內(nèi)容的組件,他包含了常用的上拉刷新,預(yù)加載等內(nèi)容核心代碼如下:

// vue
  <swiper
    direction="vertical"
    @transitionStart="transitionStart"
  >
    <swiper-slide class="slide-box" v-for="(item, index) in list" :key="index">
      <slot
        :item="item"
        :index="index"
        :activeIndex="activeIndex"
        v-if="activeIndex >= index - 1 && activeIndex <= index + 1"
      ></slot>
    </swiper-slide>
  </swiper>
  //js
   setup({ list }, { emit }) {
    const activeIndex = ref(0);
    function transitionStart(swiper) {
      //表示沒(méi)有滑動(dòng),不做處理
      if (activeIndex.value === swiper.activeIndex) {
        // 表示是第一個(gè)輪播圖
        if (swiper.swipeDirection === "prev" && swiper.activeIndex === 0) {
        // 表示上拉刷新
          emit("refresh");
        } else if (
          swiper.swipeDirection === "next" &&
          swiper.activeIndex === list.length - 1
        ) {
          // 滑動(dòng)到底部
         emit("toBottom");
        }
      } else {
        activeIndex.value = swiper.activeIndex;
        // 為了預(yù)加載視頻,提前l(fā)oad 數(shù)據(jù)
        if (swiper.activeIndex === list.length - 1) {
          emit("load");
        }
      }
    }
    return {
      transitionStart,
      activeIndex,
    };
  },

需要注意的是有兩點(diǎn)

  • 為了預(yù)加載數(shù)據(jù)會(huì)在滑動(dòng)到最后一幀的時(shí)候去請(qǐng)求數(shù)據(jù),但是由于請(qǐng)求是異步的,如果在滑動(dòng)到最后一個(gè)視頻的時(shí)候在快速下滑會(huì)觸發(fā)滑動(dòng)到底部的事件,這時(shí)候其實(shí)新數(shù)據(jù)請(qǐng)求回來(lái)之后便又不是底部了,這時(shí)候則需要你去做個(gè)判斷,如果正在請(qǐng)求中滑動(dòng)到底部不去處理你的邏輯

  • 為了性能考慮,只渲染了active 、prev、next內(nèi)容,其他一律渲染空節(jié)點(diǎn),并且為了防止頁(yè)面中出現(xiàn)多個(gè)vidoe標(biāo)簽,prev 和next 只渲染默認(rèn)圖內(nèi)容

組合使用

組合使用其實(shí)就非常簡(jiǎn)單了:

//vue
 <Yslide
      :list="data"
      v-slot="{ item, index, activeIndex }"
      @refresh="refresh"
      @toBottom="toBottom"
      @load="load"
    >
      <Yvideo
        :src="item.entStoreVO.video"
        :poster="item.entStoreVO.videoImg"
        :index="index"
        :activeIndex="activeIndex"
        autoplay
      >
        <div class="mantle">
          <div class="right" @click.stop="">
            <div class="right-btn fabulous" @click="fabulous">點(diǎn)贊</div>
            <div class="right-btn comment" @click="comment">評(píng)論</div>
            <div class="right-btn collection" @click="collection">收藏</div>
            <div class="right-btn share" @click="share">分享</div>
          </div>
        </div>
      </Yvideo>
    </Yslide>

在組合使用中,我將video通過(guò)插槽的方式傳入silide內(nèi)部,這樣做的原因是,為了用戶能自定義傳入內(nèi)容,這也是很多插件庫(kù)慣用的伎倆,增加了組件的靈活性,又增加了組件的獨(dú)立性

視頻自動(dòng)播放問(wèn)題

在web瀏覽器中你經(jīng)常會(huì)看到DOMException: play() failed because the user didn't interact with the document first 這個(gè)問(wèn)題,

首先可以肯定的是在web瀏覽器中在與瀏覽器沒(méi)有交互的情況下是不允許自動(dòng)播放的,目前暫時(shí)還無(wú)法突破這個(gè)限制

如果你要嵌入app中,webview 可以突破,具體方法大家可自行查詢,網(wǎng)上教程數(shù)不勝數(shù)。

git地址

將插件地址奉上,供大佬們參考,如有需求可直接引用,也可,克隆下來(lái)自行修改,如有問(wèn)題請(qǐng)?zhí)醝ssues github.com/yixinagqing

總結(jié)

到此這篇關(guān)于實(shí)現(xiàn)Vue3版抖音滑動(dòng)插件踩坑指南的文章就介紹到這了,更多相關(guān)Vue3版抖音滑動(dòng)插件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue cli 全面解析

    vue cli 全面解析

    vue是一套構(gòu)建用戶界面的漸進(jìn)式框架。這篇文章主要介紹了vue cli的相關(guān)知識(shí),本文給大家及時(shí)的非常全面,需要的朋友可以參考下
    2018-02-02
  • vue使用echarts實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)的示例詳解

    vue使用echarts實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)的示例詳解

    這篇文章主要為大家詳細(xì)介紹了vue如何使用echarts實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù),文中的示例講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • vue使用keep-alive后從部分頁(yè)面進(jìn)入不緩存示例詳解

    vue使用keep-alive后從部分頁(yè)面進(jìn)入不緩存示例詳解

    這篇文章主要給大家介紹了關(guān)于vue使用keep-alive后從部分頁(yè)面進(jìn)入不緩存的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-03-03
  • vue3常用響應(yīng)式對(duì)象的api,你全用過(guò)了嗎

    vue3常用響應(yīng)式對(duì)象的api,你全用過(guò)了嗎

    這篇文章主要給大家介紹了關(guān)于vue3常用響應(yīng)式對(duì)象api的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue3具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-02-02
  • vue3+element 分片上傳與分片下載功能實(shí)現(xiàn)方法詳解

    vue3+element 分片上傳與分片下載功能實(shí)現(xiàn)方法詳解

    這篇文章主要介紹了vue3+element 分片上傳與分片下載功能實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了vue3+element 分片上傳與下載相關(guān)實(shí)現(xiàn)技巧與操作注意事項(xiàng),需要的朋友可以參考下
    2023-06-06
  • 詳解vuex持久化插件解決瀏覽器刷新數(shù)據(jù)消失問(wèn)題

    詳解vuex持久化插件解決瀏覽器刷新數(shù)據(jù)消失問(wèn)題

    這篇文章主要介紹了詳解vuex持久化插件解決瀏覽器刷新數(shù)據(jù)消失問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-04-04
  • Vue中的無(wú)限加載vue-infinite-loading的方法

    Vue中的無(wú)限加載vue-infinite-loading的方法

    本篇文章主要介紹了Vue中的無(wú)限加載vue-infinite-loading的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • Vue3?攜手?TypeScript?搭建完整項(xiàng)目結(jié)構(gòu)

    Vue3?攜手?TypeScript?搭建完整項(xiàng)目結(jié)構(gòu)

    TypeScript 是JS的一個(gè)超級(jí),主要提供了類型系統(tǒng)和對(duì)ES6的支持,使用 TypeScript 可以增加代碼的可讀性和可維護(hù)性,在 react 和 vue 社區(qū)中也越來(lái)越多人開(kāi)始使用TypeScript,這篇文章主要介紹了Vue3?攜手?TypeScript?搭建完整項(xiàng)目結(jié)構(gòu),需要的朋友可以參考下
    2022-04-04
  • vue項(xiàng)目中mock.js的使用及基本用法

    vue項(xiàng)目中mock.js的使用及基本用法

    mockjs是用來(lái)模擬產(chǎn)生一些虛擬的數(shù)據(jù),可以讓前端在后端接口還沒(méi)有開(kāi)發(fā)出來(lái)時(shí)獨(dú)立開(kāi)發(fā)。這篇文章主要介紹了vue項(xiàng)目中mock.js的使用,需要的朋友可以參考下
    2019-05-05
  • vue實(shí)現(xiàn)手機(jī)號(hào)碼的校驗(yàn)實(shí)例代碼(防抖函數(shù)的應(yīng)用場(chǎng)景)

    vue實(shí)現(xiàn)手機(jī)號(hào)碼的校驗(yàn)實(shí)例代碼(防抖函數(shù)的應(yīng)用場(chǎng)景)

    這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)手機(jī)號(hào)碼的校驗(yàn)的相關(guān)資料,主要是防抖函數(shù)的應(yīng)用場(chǎng)景,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09

最新評(píng)論