【套件筆記 - Vue】輪播 Swiper.js

更新於 發佈於 閱讀時間約 21 分鐘

Swiper.js 是一個功能齊全的輪播套件,除了輪播外,也可以客製化導航按鈕和頁碼等細項。目前支持 JS、React、Vue。我的 Vue3 專題中也有使用這套套件呈現,但因為 Swiper.js Vue 版是由 Composition API 寫成,但我當時只會 Options API,花了很多時間了解撰寫方式。今天目標就是介紹 Swiper.js 在 Vue3 Options API 的用法和元件化小撇步。

今日目標:Swiper 複用元件

今日目標:Swiper 複用元件


目標功能

  1. 網頁每次顯示 3 則,768px 以下顯示 1 則
  2. 輪播時以更新 1 則為單位
  3. 可自動播放:Autoplay(自動播放)
  4. 可使用頁碼操作:Pagination(頁碼)
  5. 可使用導航切換上下頁:Navigation(上下一則導航)
  6. 輪播至最後一筆,會自動同方向重複播放:Loop(迴圈)
  7. 輪播元件可以重複使用,並秀出不同類別內容


一、官網資源/安裝

--- 2024/04/08 更新:請裝這個 ​------
npm i swiper@10.3.1

--- 舊文請忽略 ​------
npm i swiper@8.0.0

是的沒錯~ 雖然現在 Swiper 版本已經是 11 了,但 Options API 在版本 8 才不會出錯(2024/04/08 更新:Swiper 10.3.1 也可以)。我的使用經驗是不管是否為同一個 swiper 元件,重複在同一個頁面使用沒有問題。但如果在不同頁面中使用,navigation(上/下一張)的導航就會失效,只有降版沒有問題,可能跟 Swiper 後期版本是用 Composition api 來撰寫有關。我個人是習慣各版本文件搭配著看,雖然中文翻譯版已經很舊了,但是初學時的好利器。實作時也推薦大家先從 11 的 Demos 尋找範例開始,比較好入手。



二、建立元件

1. 引入方法

建立元件文件 SwiperComponent.vue。

官網提到:By default Swiper Vue uses core version of Swiper (without any additional modules). If you want to use Navigation, Pagination and other modules, you have to install them first.

所以像是 Autoplay(自動播放)、Pagination(頁碼)、Navigation(上下一則導航)都是要額外引入的。

<script>
// import Swiper js
import { Swiper, SwiperSlide } from 'swiper/vue'
// Swiper 8 這樣寫 ↓
import { Autoplay, Pagination, Navigation } from 'swiper'
// Swiper 10 這樣寫 ↓
import { Navigation, Pagination, Autoplay } from 'swiper/modules'

// Import Swiper stylesimport 'swiper/css'
import 'swiper/css/pagination'
import 'swiper/css/navigation'

export default{
data () {
return {
data: ..., // 你要渲染的資料
modules: [Autoplay, Pagination, Navigation] // 額外引入的 modules
}
},
components: {
Swiper,
SwiperSlide
}
}
</script>

2. 撰寫 HTML

// swiper 輪播主體,設置都要在 Swiper 標籤範圍內才會生效​
<Swiper
:slidesPerView="1"
:breakpoints="{
768: {slidesPerView: 3}
}"
:spaceBetween="30"
:pagination="{clickable: true,}"
:navigation="true"
:loop="true"
:autoplay="{
delay: 2500,
disableOnInteraction: false
}"
:modules="modules"
> 

// 在 swiper-slide 裡面放入要呈現的圖片和標題,每個 swiper-slide 都是獨立的區塊
<swiper-slide v-for="item in data" :key="item">
<img :src="item.img" alt="item.title">
<h3>{{item.title}}</h3>
</swiper-slide>

</Swiper>
raw-image

屬性說明

  • slidesPerView:每次輪播更換則數。
  • breakpoints:RWD 響應式斷點,但是請注意只有文件中提到的屬性才能用 RWD,其他操作只能用 CSS 或 JS 實現。在這裡的設定是 slidesPerView 在 768px 以上顯示 3 則,以下顯示 1 則。
  • spaceBetween:每則輪播間距,如果想做文字跑馬燈,也可以設定成 auto,讓他自動計算。
  • pagination:在此設定為可以使用點選操作的,pagination 還有外觀選項
  • navigation:上下一則導航,如果要使用則設為 true,文章後面會再介紹如何客製化樣式。
  • loop:播放至最後一筆時,能維持同一方向從第一筆繼續播放。如果不設定,則整個 swiper 會先逆向回到第一筆,才開始輪播。
  • autoplay:自動輪播,在此設定 2500 毫秒輪播,滑鼠互動時,輪播不會暫停計秒。

詳細可以參考官方文件,內容有每個屬性的預設值和調整方法。

3. 在父元件使用

<template>
<div class="container"> // swiper 必須設定顯示區域尺寸
<SwiperComponent></SwiperComponent>
</div>
</template>

<script>
// 引入 swiper 元件​
import SwiperComponent from '@/components/SwiperComponent.vue'

export default {
components: {
SwiperComponent
}
}
</script>

完成到這裡就可以使用啦!很方便又快速~



三、元件複用

1. 元件複用的好處

  • 減少重複程式碼
  • 調整只需要更動元件,避免修改四散的程式碼,較好維護

2. 實作方法

Vue 元件使用的資料可以由內部生成外部傳入,我們要同時運用這兩個技巧。
  1. 先在 SwiperComponent.vue 中建立我們要顯示資料的欄位,以本文目標範例圖來說,首先是每個 swiper 區塊的標題。
    我們先從父元件輸入外部資料試試看,於元件引用處上建立外部屬性 adCategoryTitle,並寫入要呈現的字串標題。
// 父元件​
<template>
<div class="container">
<SwiperComponent adCategoryTitle="猜你喜歡吃甜甜"></SwiperComponent>
<SwiperComponent adCategoryTitle="邀請你來嚐口感"></SwiperComponent>
<SwiperComponent adCategoryTitle="美味氣氛隨你加"></SwiperComponent>
</div>
</template>
  1. 回到 swiper 元件,將剛才設定的外部屬性名稱填入,就完成了。
// SwiperComponent.vue​
<template>
<div>
<h2>{{ adCategoryTitle }}</h2> // 使用資料
<Swiper...</Swiper>
</div>
</template>

<script>
export default {
... 略​
props: ['adCategoryTitle'] // 由 props 接收外部傳入資料
}
</sctipt>
  1. 但通常複用元件不僅只有標題變化,輪播內容也要不同,所以我們可以再回頭修改上面的程式碼。
    以下 swiper 元件運作邏輯是:
    .將父元件傳入的文字屬性化,從中文標題改成分類。
    .swiper 元件建立屬性對應的標題 adTitle,結合上一個步驟,就可以利用傳入資料對應獲取的中文標題了,這可以避免中文字要修改時父子元件都要更動的問題。
    .父元件渲染時,每碰到 swiper 元件都會啟動 mounted 獲取產品資料 getProducts()
    getProducts() 也是根據外部傳入資料,獲取對應要顯示的產品內容。
// 父元件
<template>
<div class="container">
<SwiperComponent adCategoryTitle="sweet"></SwiperComponent>
<SwiperComponent adCategoryTitle="taste"></SwiperComponent>
<SwiperComponent adCategoryTitle="spices"></SwiperComponent>
</div>
</template>
// SwiperComponent.vue​
export default {
props: ['adCategoryTitle'],
data () {
return {
allProducts: [],
adTitle: {
sweet: '猜你喜歡吃甜甜',
taste: '邀請你來嚐口感',
spices: '美味氣氛隨你加'
},
modules: [Autoplay, Pagination, Navigation]
}
},
methods: {
// 獲取產品
getProducts () {
if (adCategoryTitle === "sweet"){ // 根據傳入 props 獲取對應資料​
...
this.allProducts = response
}else if (adCategoryTitle === "taste"){...}
}
},
mounted () {
this.getProducts()
},
components: {
Swiper,
SwiperSlide
}
}
</script>



四、客製化 swiper 樣式

1. 客製化 navigation

swiper 本身動作就綁定在原生 CSS 樣式上,不需要額外寫 idclass 使用 DOM 綁定。以下 .swiper-button-next.swiper-button-prev 都是原生設定,藉由這兩項樣式調整 CSS,就可以客製化外觀了。

如果 navigation 要 RWD 響應式顯示,也是藉由 CSS 設定。

// SwiperComponent.vue​
// 原本我們在 <Swiper> 標籤中的設定
<Swiper :navigation="true">
<SwiperSlide>...</SwiperSlide>
</Swiper>

// 修改成以下設定​
<Swiper :navigation="{
nextEl: '.swiper-button-next', // 下一則
prevEl: '.swiper-button-prev' // 上一則
}">
<SwiperSlide>...</SwiperSlide>
// 因為要客製化 button,所以額外新增 DOM 在 <Swiper> 內,並套用原生 class 樣式
<button class="swiper-button-next"></button>
<button class="swiper-button-prev"></button>
</Swiper>
// SwiperComponent.vue​
// 請依你的專案微調 css 數值​
<style lang="scss" scoped>
// 替換成客製化 icon 的方法​
.swiper-button-next{
// 插入你想使用的 icon 即設定尺寸
background: url("...") no-repeat center;
background-size: 40px 40px;

// 隱藏原生的藍色箭頭
text-indent: 101%;
white-space: nowrap;
overflow: hidden;
width: 40px;
height: 40px;
}

// 僅替換原生箭頭顏色的方法
.swiper-button-prev {
// 使用 color 就可以更換箭頭顏色​
color: $red;
}
</style>

2. navigation 在 Swiper 元件範圍外顯示的方法

swiper 預設的 navigation 是在 .swiper 範圍內的。如果要讓 navigation(藍框)像下圖超出在 .swiper(紅框)範圍外,我們要先來釐清它的 CSS。

swiper 結構

swiper 結構

HTML 中 <Swiper> 生成的範圍就是途中右側使用 .swiper 樣式的區域範圍,它本身有 position-relativeoverflow-hidden 的設定,所以我們可以發現:

  • 查看 .swiper-button-next.swiper-button-prev,發現原生帶有 position-absolute 樣式,所以可以透過 top/right... 等方法定位。
  • 如果直接移動 navigation 位置,會發現超出 .swiper 的部分會被隱藏,所以我們要針對區域尺寸做更改。
// SwiperComponent.vue​
<Swiper class="product-swiper">  // 新增一個樣式
...
</Swiper>
<style lang="scss" scoped>
// 由於我的預設是 768px 以內不顯示 navigation 所以做了 RWD 設定
// 如果 navigation 一直存在,只要參考 @media{} 內的程式碼就好​
:deep(.product-swiper) {
margin: auto;
padding: 0;

@media (min-width: 768px) {
// 因為我的 navigation 尺寸是 40x40,我希望能凸出顯示一半,所以設定 20px
margin: 0 -20px !important;
padding: 0 20px !important;
}
}
</style>

我們可以從下圖理解 padding 和 margin 合作關係。

  • 紅框是我們要限縮內容顯示的範圍
  • padding 20px,將 .swiper overflow-hidden 的範圍左右撐開
  • margin -20px,讓輪播內容範圍內縮,如果不做這個設定,輪播範圍會跟黃框一樣
raw-image

完成區塊設定後,再設定左右 navigaiton button 的位置就完成了~

<style lang="scss" scoped>
// 因為原生 swiper navigation​ 就帶有 position-absolute 樣式,所以直接定義位置
.swiper-button-next {
top: 50%;
right: 0px;
...
}
.swiper-button-prev {
top: 50%;
left: 0px;
...
}
</style>

3. 客製化 pagination

pagination 也可以使用原生的 .swiper-pagination 修改。
例如以下做了只有 768px 以下才顯示、更改 pagination 顏色。

/* swiper 顯示區域尺寸 */
// 其實 pagination 的位置是仰賴 swiper-wrapper​ 區塊
// pagintaion 預設自動貼合 swiper-wrapper 區塊底端,所以要藉由 margin-bottom 把區塊撐大
.swiper-wrapper {
margin-bottom: 36px;

@media (min-width: 768px) {
margin-bottom: 0rem;
}
}

/*Swiper 頁碼導覽*/
.swiper-pagination {
display: inline-block;

@media (min-width: 768px) {
display: none;
}

&-bullet {
background: #787878;
}

&-bullet-active {
background: #333333;
}
}


五、結尾

  1. 當初在 swiper vue 上卡了很久,感謝 Billy 助教提供指點,告訴我要換成 swiper 8 才能避免錯誤。
  2. (2024/04/08 更新)
    感謝好同學聿凌提問 Swiper 10 能否運行,經過測試也沒問題!
    附上這位超認真同學的專題 RepoPages,這是一個南部旅遊方案電商,整個平台和 JSON Server 資料庫都是她獨力開發完成的。從 JS 直播班到 Vue 直播班,看她與專題教練的討論紀錄,很開心她克服重重困難,完成了這份專題。
avatar-img
16會員
23內容數
從藝術領域轉職到前端工程師,喜歡書寫學習歷程和技術文件,掌握經驗與隨時提取的感覺很好。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
Ann Chou的沙龍 的其他內容
分享在網路上看到的陣列題目。通常 for...of 的 value 是陣列中的每個值,那如果我們在迭代中對陣列操作會發生什麼事? 題目來源:https://x.com/_jayphelps/status/1774640511158022335?s=20
Node 對我來說一直是很似懂非懂的概念,因為沒有實際可見的數字或字串實物可以觀察中間步驟,比起其他解題抽象許多。以下解題方法來自網友與 GPT 提供的答案,我想在本文中嘗試自己做視覺化圖解,說明 CodeWars - Can you get the loop ? 的解題思路。
JavaScript 套件,頁碼 Pagination.js 搭配 axios API 請求範例
分享這套功能齊全,視覺超級可愛還有響應式變化,教學文件又很容易閱讀的套件 Evo Calendar。 當初在製作 JS side project 時,想找一個與 VCalendar 視覺相近的套件,但多半都不合意。六角學院指派的 side project 教練也幫我找了另一個純 JS 的範例,也很
不喜歡 HTML 原生的時間選擇器外型嗎?試試看 flatpickr.js 吧! 以下是使用 flatpickr 做簡單的示例,以及 flatpickr 使用注意事項。
我依舊維持著修習 JS 的步伐,但我仍然覺得自己對 JS 的熟悉度不足。在 JS 班開課後,我藉由刷題庫和做 side project 專題,填補了課前的不自信感和知識焦慮。最終我們小組在 2.5 個月內開發了一個訂閱制電商網站的前後台,我也參加了 F2E week1 完賽,獲得銀級徽章
分享在網路上看到的陣列題目。通常 for...of 的 value 是陣列中的每個值,那如果我們在迭代中對陣列操作會發生什麼事? 題目來源:https://x.com/_jayphelps/status/1774640511158022335?s=20
Node 對我來說一直是很似懂非懂的概念,因為沒有實際可見的數字或字串實物可以觀察中間步驟,比起其他解題抽象許多。以下解題方法來自網友與 GPT 提供的答案,我想在本文中嘗試自己做視覺化圖解,說明 CodeWars - Can you get the loop ? 的解題思路。
JavaScript 套件,頁碼 Pagination.js 搭配 axios API 請求範例
分享這套功能齊全,視覺超級可愛還有響應式變化,教學文件又很容易閱讀的套件 Evo Calendar。 當初在製作 JS side project 時,想找一個與 VCalendar 視覺相近的套件,但多半都不合意。六角學院指派的 side project 教練也幫我找了另一個純 JS 的範例,也很
不喜歡 HTML 原生的時間選擇器外型嗎?試試看 flatpickr.js 吧! 以下是使用 flatpickr 做簡單的示例,以及 flatpickr 使用注意事項。
我依舊維持著修習 JS 的步伐,但我仍然覺得自己對 JS 的熟悉度不足。在 JS 班開課後,我藉由刷題庫和做 side project 專題,填補了課前的不自信感和知識焦慮。最終我們小組在 2.5 個月內開發了一個訂閱制電商網站的前後台,我也參加了 F2E week1 完賽,獲得銀級徽章
你可能也想看
Google News 追蹤
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
自訂元件生成位置顧名思義就是可以指定部分HTML區塊渲染在特定的畫面上,即使在不同組件也能把A組件內的部分畫面,展現在B組件上,以下方程式舉例。
Thumbnail
Vue.js是一種基於MVVM的前端JavaScript框架,類似的框架有React、Angular等。 架設環境 安裝Visual Studio Code(https://code.visualstudio.com/) 安裝Node.js(https://nodejs.org/en/
Thumbnail
2023 Vue直播班筆記 - 動態路由Props,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
Thumbnail
Vue Router 動態路由,假設有一個賣場,裡面有 100 個商品,我們不可能針對它們創 100 對應的路由,因此我們需要一個動態路由,利用"路徑帶參數"的方式來撈取商品的資訊。
Thumbnail
Vue Router 及 具名視圖,擺脫以往切換依賴 CSS display:none 跟 display:block 互相配合,有時還得搭配 z-index 來調整層級跟 opacity 透明度的麻煩,而 Vue Router 完美的解決了這棘手的問題,且能客製頁面想要呈現的擺飾。
Thumbnail
在 Vue 中,methods和computed是用於定義元件的行為和計算屬性。本文將介紹methods和computed屬性的使用方法和區別,並通過實際範例來幫助你理解。
Thumbnail
Vue 提供了兩種不同的 API 來建立和管理組件:Option API 和 Composition API。本文將介紹這兩種 API 的特點和差異,並透過實際範例來理解它們的使用方式。
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
自訂元件生成位置顧名思義就是可以指定部分HTML區塊渲染在特定的畫面上,即使在不同組件也能把A組件內的部分畫面,展現在B組件上,以下方程式舉例。
Thumbnail
Vue.js是一種基於MVVM的前端JavaScript框架,類似的框架有React、Angular等。 架設環境 安裝Visual Studio Code(https://code.visualstudio.com/) 安裝Node.js(https://nodejs.org/en/
Thumbnail
2023 Vue直播班筆記 - 動態路由Props,接續之前的一般動態路由。分為 "寫死" 及 "彈性" 兩種。
Thumbnail
Vue Router 動態路由,假設有一個賣場,裡面有 100 個商品,我們不可能針對它們創 100 對應的路由,因此我們需要一個動態路由,利用"路徑帶參數"的方式來撈取商品的資訊。
Thumbnail
Vue Router 及 具名視圖,擺脫以往切換依賴 CSS display:none 跟 display:block 互相配合,有時還得搭配 z-index 來調整層級跟 opacity 透明度的麻煩,而 Vue Router 完美的解決了這棘手的問題,且能客製頁面想要呈現的擺飾。
Thumbnail
在 Vue 中,methods和computed是用於定義元件的行為和計算屬性。本文將介紹methods和computed屬性的使用方法和區別,並通過實際範例來幫助你理解。
Thumbnail
Vue 提供了兩種不同的 API 來建立和管理組件:Option API 和 Composition API。本文將介紹這兩種 API 的特點和差異,並透過實際範例來理解它們的使用方式。