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

Vue實現(xiàn)輪播圖組件的封裝

 更新時間:2023年04月20日 11:14:11   作者:itpeilibo  
Vue輪播圖組件的封裝可通過封裝組件、使用插件、配置化等方式實現(xiàn),主要包括圖片預(yù)加載、定時輪播、無限滾動、手勢滑動、響應(yīng)式布局等功能,實現(xiàn)方式可使用Vue的生命周期函數(shù)、自定義事件、計算屬性等技術(shù)

輪播圖功能-獲取數(shù)據(jù)

目標(biāo): 基于pinia獲取輪播圖數(shù)據(jù)

核心代碼:

(1)在types/data.d.ts文件中定義輪播圖數(shù)據(jù)的類型聲明

// 所有接口的通用類型
export type ApiRes <T> = {
    code: string,
    msg: string,
    result: T
}
// 輪播圖類型
export type BannerItem = {
  hrefUrl: string
  id: string
  imgUrl: string
  type: string
}

(2)在store/home.ts文件中封裝接口,用于獲取輪播圖數(shù)據(jù)

import { ApiRes, BannerItem } from '@/types/data'
import request from '@/utils/request'
import { defineStore } from 'pinia'
export default defineStore('home', {
  state: () => ({
    bannerList: [] as BannerItem[],
  }),
  actions: {
    async getBannerList() {
      const {data: res} = await request.get<ApiRes<BannerItem[]>>('/home/banner')
      this.bannerList = res.result
    },
  },
})

(3)在store/index.ts中導(dǎo)入

import useCategoryStore from './modules/category'
import useHomeStore from './modules/home'
export default function useStore() {
  return {
    category: useCategoryStore(),
    home: useHomeStore(),
  }
}

(4)通過開發(fā)者工具查看數(shù)據(jù)

<script lang="ts" setup>
import useStore from '@/store'
const { home } = useStore()
home.getBannerList()
</script>

輪播圖-通用輪播圖組件

項目中會多次使用到輪播圖組件,但是輪播圖渲染的數(shù)據(jù)是不一樣的。

但是輪播圖的基本功能都是一樣的,比如圖片切換,自動播放等等。

因此需要封裝一個通用的輪播圖組件。

(1)通用輪播圖的基本結(jié)構(gòu)src/components/carousel/index.vue

fade 類:用于控制圖片的顯示和隱藏

active 類:用于控制小圓點高亮

<script lang="ts" setup name="Carousel">
defineProps()
</script>
<template>
  <div class="carousel">
    <ul class="carousel-body">
      <li class="carousel-item fade">
        <RouterLink to="/">
          <img
            src="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/1ba86bcc-ae71-42a3-bc3e-37b662f7f07e.jpg"
            alt=""
          />
        </RouterLink>
      </li>
      <li class="carousel-item">
        <RouterLink to="/">
          <img
            src="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/1ba86bcc-ae71-42a3-bc3e-37b662f7f07e.jpg"
            alt=""
          />
        </RouterLink>
      </li>
      <li class="carousel-item">
        <RouterLink to="/">
          <img
            src="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-15/1ba86bcc-ae71-42a3-bc3e-37b662f7f07e.jpg"
            alt=""
          />
        </RouterLink>
      </li>
    </ul>
    <a href="javascript:;" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  class="carousel-btn prev"
      ><i class="iconfont icon-angle-left"></i
    ></a>
    <a href="javascript:;" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  class="carousel-btn next"
      ><i class="iconfont icon-angle-right"></i
    ></a>
    <div class="carousel-indicator">
      <span class="active"></span>
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </div>
  </div>
</template>
<style scoped lang="less">
.xtxcarousel {
  width: 100%;
  height: 100%;
  min-width: 300px;
  min-height: 150px;
  position: relative;
  .carousel {
    &-body {
      width: 100%;
      height: 100%;
    }
    &-item {
      width: 100%;
      height: 100%;
      position: absolute;
      left: 0;
      top: 0;
      opacity: 0;
      transition: opacity 0.5s linear;
      &.fade {
        opacity: 1;
        z-index: 1;
      }
      img {
        width: 100%;
        height: 100%;
      }
    }
    &-indicator {
      position: absolute;
      left: 0;
      bottom: 20px;
      z-index: 2;
      width: 100%;
      text-align: center;
      span {
        display: inline-block;
        width: 12px;
        height: 12px;
        background: rgba(0, 0, 0, 0.2);
        border-radius: 50%;
        cursor: pointer;
        ~ span {
          margin-left: 12px;
        }
        &.active {
          background: #fff;
        }
      }
    }
    &-btn {
      width: 44px;
      height: 44px;
      background: rgba(0, 0, 0, 0.2);
      color: #fff;
      border-radius: 50%;
      position: absolute;
      top: 228px;
      z-index: 2;
      text-align: center;
      line-height: 44px;
      opacity: 0;
      transition: all 0.5s;
      &.prev {
        left: 20px;
      }
      &.next {
        right: 20px;
      }
    }
  }
  &:hover {
    .carousel-btn {
      opacity: 1;
    }
  }
}
</style>

(2)全局注冊通用輪播圖 src/components/index.ts

import type { App } from 'vue'
import skelecton from './skeleton/index.vue'
+import Carousel from './carousel/index.vue'
export default {
  install(app: App) {
    app.component(skelecton.name, skelecton)
+    app.component(Carousel.name, Carousel)
  },
}

(3)在廣告組件中使用src/views/home/components/home-banner.vue

<template>
  <div class="home-banner">
    <!-- 輪播圖 -->
    <Carousel></XtxCarousel>
  </div>
</template>

(4)覆蓋樣式,控制箭頭和小圓點的位置src/views/home/components/home-banner.vue

:deep(.carousel-btn.prev) {
  left: 270px!important;
}
:deep(.carousel-indicator) {
  padding-left: 250px;
}

(5)查看效果

輪播圖-數(shù)據(jù)渲染

目的

home-banner組件把數(shù)據(jù)傳遞給Carousel組件進(jìn)行渲染

(1)父傳子的方式將數(shù)據(jù)傳給通用輪播圖組件src/views/home/components/home-banner.vue

<Carousel :slides="home.bannerList"></Carousel>

(2)子組件接收數(shù)據(jù)src/components/carousel/index.vue

了解寫法:如果通過js的方法定義類型,需要單獨引入PropType進(jìn)行編寫

<script lang="ts" setup name="Carousel">
import { BannerItem } from '@/types/data'
// import { PropType } from 'vue'
// defineProps({
//   slides: {
//     type: Array as PropType<BannerItem[]>,
//     required: true,
//   },
// })
defineProps<{
  slides: BannerItem[]
}>()
</script>

(3)渲染輪播圖數(shù)據(jù)src/components/carousel/index.vue

<template>
  <div class="carousel">
    <ul class="carousel-body">
      <li class="carousel-item fade" v-for="item in slides" :key="item.id">
        <RouterLink :to="item.hrefUrl">
          <img :src="item.imgUrl" alt="" />
        </RouterLink>
      </li>
    </ul>
    <a href="javascript:;" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  class="carousel-btn prev">
      <i class="iconfont icon-angle-left"></i>
    </a>
    <a href="javascript:;" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  class="carousel-btn next">
      <i class="iconfont icon-angle-right"></i>
    </a>
    <div class="carousel-indicator">
      <span v-for="item in slides" :key="item.id" class="active"></span>
    </div>
  </div>
</template>

(4)控制高亮的下標(biāo)

<script lang="ts" setup name="Carousel">
const active = ref(0)
</script>

(5)高亮渲染

  • 添加的fade的圖片才會展示,所以根據(jù)當(dāng)前索引號進(jìn)行判斷,索引號等于active的才進(jìn)行展示
  • 添加了active類名的小圓點才會高亮,高亮邏輯跟圖片一致
<template>
  <div class="carousel">
    <ul class="carousel-body">
      <li
        class="carousel-item"
+        :class="{ fade: active === index }"
+        v-for="(item, index) in slides"
        :key="item.id"
      >
        <RouterLink :to="item.hrefUrl">
          <img :src="item.imgUrl" alt="" />
        </RouterLink>
      </li>
    </ul>
    <a href="javascript:;" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  class="carousel-btn prev">
      <i class="iconfont icon-angle-left"></i>
    </a>
    <a href="javascript:;" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  class="carousel-btn next">
      <i class="iconfont icon-angle-right"></i>
    </a>
    <div class="carousel-indicator">
      <span
+        v-for="(item, index) in slides"
        :key="item.id"
+        :class="{ active: active === index }"
      ></span>
    </div>
  </div>
</template>

輪播圖-邏輯封裝

實現(xiàn)需求:

輪播圖里面的圖片需要從父組件傳入(因為輪播組件可以復(fù)用)

父組件需要控制輪播圖的是否自動播放、動畫時間(處理默認(rèn)值邏輯)

是否自動播放和動畫時間都是需要默認(rèn)值的(如果不傳就可以使用輪播組件自己提供的默認(rèn)值)

播放邏輯

  • 點擊小圓點可以切換圖片
  • 點擊prev和next按鈕可以播放指定圖片(根據(jù)圖片個數(shù)判斷播放的循環(huán))
  • 如果父組件配置了自動播放,則需要定時播放圖片
  • 鼠標(biāo)進(jìn)入輪播圖,暫停輪播
  • 鼠標(biāo)離開輪播圖,繼續(xù)輪播
  • 注意點:組件卸載的時候需要清除定時輪播效果(不然組件重新加載的時候會導(dǎo)致多個定時器開啟)

(1)父組件傳值給輪播圖src/views/home/components/home-banner.vue

<template>
  <div class="home-banner">
    <!-- 輪播圖 -->
    <Carousel :slides="slides" autoPlay :duration="3000"></XtxCarousel>
  </div>
</template>

(2)props接收src/components/Carousel.vue

<script lang="ts" setup name="Carousel">
import { BannerItem } from '@/types/data'
import { ref, PropType } from 'vue'
defineProps({
  slides: {
    type: Array as PropType<BannerItem[]>,
    required: true,
  },
  autoPlay: {
    type: Boolean,
    default: false,
  },
  duration: {
    type: Number,
    default: 3000,
  },
})
const active = ref(0)
</script>

(3)輪播圖的播放邏輯

<script lang="ts" setup name="Carousel">
import { BannerItem } from '@/types/data'
import { onMounted, onUnmounted, PropType, ref } from 'vue'
// import { PropType } from 'vue'
const props = defineProps({
  slides: {
    type: Array as PropType<BannerItem[]>,
    required: true,
  },
  duration: {
    type: Number,
    default: 3000,
  },
  autoPlay: {
    type: Boolean,
    default: false,
  },
})
// const props = defineProps<{
//   slides: BannerItem[]
// }>()
// 控制高亮
const active = ref(0)
const prev = () => {
  if (active.value <= 0) {
    active.value = props.slides.length - 1
  } else {
    active.value--
  }
}
const next = () => {
  if (active.value >= props.slides.length - 1) {
    active.value = 0
  } else {
    active.value++
  }
}
const play = () => {
  // 如果沒有自動播放
  if (!props.autoPlay) return
  // 在ts中,使用定時器,window.setInterval
  timer = window.setInterval(() => {
    next()
  }, props.duration)
}
const stop = () => {
  clearInterval(timer)
}
let timer = -1
// 自動播放
onMounted(() => {
  play()
})
onUnmounted(() => {
  stop()
})
</script>

(4)鼠標(biāo)進(jìn)入和離開操作

<div class="carousel" @mouseenter="stop" @mouseleave="play">

(5)鼠標(biāo)經(jīng)過小圓點切換

<span
  v-for="(item, index) in slides"
  :key="item.id"
  :class="{ active: active === index }"
  @mouseenter="active = index"
></span>

(6)點擊左右箭頭切換

const prev = () => {
  if (active.value === 0) {
    active.value = props.slides.length - 1
  } else {
    active.value--
  }
}
const next = () => {
  if (active.value === props.slides.length - 1) {
    active.value = 0
  } else {
    active.value++
  }
}
// 注冊事件
<a href="javascript:;" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  class="carousel-btn prev" @click="prev">
  <i class="iconfont icon-angle-left"></i>
</a>
<a href="javascript:;" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  class="carousel-btn next" @click="next">
  <i class="iconfont icon-angle-right"></i>
</a>
vascript
const prev = () => {
  if (active.value === 0) {
    active.value = props.slides.length - 1
  } else {
    active.value--
  }
}
const next = () => {
  if (active.value === props.slides.length - 1) {
    active.value = 0
  } else {
    active.value++
  }
}
// 注冊事件
<a href="javascript:;" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  class="carousel-btn prev" @click="prev">
  <i class="iconfont icon-angle-left"></i>
</a>
<a href="javascript:;" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  class="carousel-btn next" @click="next">
  <i class="iconfont icon-angle-right"></i>
</a>

到此這篇關(guān)于Vue實現(xiàn)輪播圖組件的封裝的文章就介紹到這了,更多相關(guān)Vue輪播圖組件封裝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vuex的使用及持久化state的方式詳解

    vuex的使用及持久化state的方式詳解

    這篇文章主要介紹了vuex的使用及持久化state的方式詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • 一文教會你如何在npm上傳自己的包

    一文教會你如何在npm上傳自己的包

    作為一個前端開發(fā)者,我們要學(xué)會自己編寫一些開發(fā)工具模塊,也可以自己編寫一些組件,甚至可以通過自己的能力編寫一個框架出來,這都需要我們能夠靈活的管理我們的包,下面這篇文章主要給大家介紹了關(guān)于如何通過一文教會你在npm上傳自己的包的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • 使用vue-cli(vue腳手架)快速搭建項目的方法

    使用vue-cli(vue腳手架)快速搭建項目的方法

    本篇文章主要介紹了使用vue-cli(vue腳手架)快速搭建項目的方法,vue-cli 是一個官方發(fā)布 vue.js 項目腳手架,使用 vue-cli 可以快速創(chuàng)建 vue 項目,感興趣的小伙伴們可以參考一下
    2018-05-05
  • vue v-for 點擊當(dāng)前行,獲取當(dāng)前行數(shù)據(jù)及event當(dāng)前事件對象的操作

    vue v-for 點擊當(dāng)前行,獲取當(dāng)前行數(shù)據(jù)及event當(dāng)前事件對象的操作

    這篇文章主要介紹了vue v-for 點擊當(dāng)前行,獲取當(dāng)前行數(shù)據(jù)及event當(dāng)前事件對象的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Vue 2.0 中依賴注入 provide/inject組合實戰(zhàn)

    Vue 2.0 中依賴注入 provide/inject組合實戰(zhàn)

    這篇文章主要介紹了Vue 2.0 依賴注入 provide/inject組合,本文通過實例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2019-06-06
  • vue-loader教程介紹

    vue-loader教程介紹

    本篇文章主要介紹了vue-loader教程介紹,vue-loader就是告訴webpack如何將vue格式的文件轉(zhuǎn)換成js。有興趣的可以了解一下
    2017-06-06
  • 解決Vue 刷新頁面導(dǎo)航顯示高亮位置不對問題

    解決Vue 刷新頁面導(dǎo)航顯示高亮位置不對問題

    這篇文章主要介紹了解決Vue 刷新頁面導(dǎo)航顯示高亮位置不對問題,本文圖文實例相結(jié)合給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-12-12
  • vant組件庫之tag漸變色不起作用的原因及解決

    vant組件庫之tag漸變色不起作用的原因及解決

    這篇文章主要介紹了vant組件庫之tag漸變色不起作用的原因及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vuex狀態(tài)管理數(shù)據(jù)狀態(tài)查詢與更改方式

    vuex狀態(tài)管理數(shù)據(jù)狀態(tài)查詢與更改方式

    這篇文章主要介紹了vuex狀態(tài)管理數(shù)據(jù)狀態(tài)查詢與更改方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue中的mvvm模式講解

    vue中的mvvm模式講解

    今天小編就為大家分享一篇關(guān)于vue中的mvvm模式講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01

最新評論

菏泽市| 登封市| 宁河县| 仁寿县| 平谷区| 宜君县| 遂川县| 滦南县| 米泉市| 二连浩特市| 清丰县| 乌鲁木齐县| 平阴县| 西畴县| 越西县| 滨州市| 雷山县| 兰西县| 上饶县| 玛曲县| 彝良县| 漳浦县| 高密市| 台东市| 定南县| 南涧| 武清区| 年辖:市辖区| 海淀区| 五家渠市| 湘阴县| 合江县| 花莲县| 高青县| 射洪县| 灌云县| 遂平县| 南华县| 大方县| 平凉市| 乐清市|