Vue.js學習記錄-15-Vue去哪兒網專案實戰:景點詳情頁開發-功能點概述 + Detail + Banner(通用元件:Gallery、Fade)
3. 景點詳情頁開發
-
功能點概述
- 使用者首頁點選熱銷推薦景點,即可跳轉景點詳情頁面。詳情頁面包括三部分內容:頂部圖片展示、景點門票詳情、隱藏頁面頭。(拖動至下方會出現)
- 使用者點選頂部圖片展示,進入圖片輪播區域(全屏),可左右滑動進行圖片瀏覽,點選圖片區域外進行返回景點詳情頁,過渡動畫的使用,圖片輪播區域配置首頁返回按鈕。
- 使用者向下拖動景點詳情頁,即可看見隱藏頁面頭部,同時具備返回按鈕,可以返回至首頁。
- 景點門票詳情,針對返回的多層資料,進行元件的遞迴呼叫展示。
- 使用者首頁點選熱銷推薦景點,即可跳轉景點詳情頁面。詳情頁面包括三部分內容:頂部圖片展示、景點門票詳情、隱藏頁面頭。(拖動至下方會出現)
-
Detail:城市詳情父元件
-
路由配置
在該模組中,路由採用了動態引數的形式,進行路由配置,座標/router/index.js:
import Detail from '@/pages/detail/Detail' { // 繫結動態引數 path: '/detail/:id', name: 'detail', component: Detail }
其中 :id 綁定了動態的URL引數,在元件中可以通過:this.$route.params.id 進行獲取
-
元件管理:
- 子元件引入及註冊:Banner、Header、List
-
引入
import DetailBanner from './components/Banner' import DetailHeader from './components/Header' import DetailList from './components/List'
-
註冊
components: { DetailBanner, DetailHeader, DetailList }
-
- 子元件引入及註冊:Banner、Header、List
-
元件互動:三個互動點
-
首頁熱銷推薦景點點選路由跳轉
座標:Home.Recommend,路由跳轉時,
<!-- 採用router-link進行頁面跳轉,tag標識標籤轉換為li,to攜帶引數進行頁面跳轉 --> <router-link tag="li" :to="'/detail/' + item.id" class="item border-bottom" v-for="item of list" :key="item.id"> <img class="item-img" :src="item.imgUrl" /> <div class="item-info"> <p class="item-title">{{item.title}}</p> <p class="item-desc">{{item.desc}}</p> <button class="item-button">檢視詳情</button> </div> </router-link>
-
Banner、Header點選返回按鈕路由跳轉
座標:Header,下文詳細元件中進行介紹
-
-
資料傳遞:採用axios進行資料傳遞
-
axios引入
import axios from 'axios'
-
初始化data
data() { return { sightName: '', bannerImg: '', gallaryImgs: [], list: [] } }
-
資料請求
-
觸發資料請求
//頁面渲染時觸發方法 mounted() { this.getDetailInfo() }
-
資料請求:注意請求拼裝URL的方式,前面已經提到了呼叫動態引數的方法:this.$route.params.id
methods: { getDetailInfo() { axios.get('/api/detail.json?', { params: { id: this.$route.params.id } }).then(this.handleGetDataSucc) }, handleGetDataSucc(res) { res = res.data if (res.ret && res.data) { const data = res.data this.sightName = data.sightName this.bannerImg = data.bannerImg this.gallaryImgs = data.gallaryImgs this.list = data.categoryList } } },
-
-
資料傳遞:三個資料項傳遞給Banner元件、一個數據項傳遞給List元件
<template> <div> <detail-banner :sightName="sightName" :bannerImg="bannerImg" :gallaryImgs="gallaryImgs"></detail-banner> <detail-header></detail-header> <div class="content"> <detail-list :list="list"></detail-list> </div> </div> </template>
-
-
-
Banner:景點圖片畫廊(通用元件)
寫在開頭,這一部分要實現的具體功能細節有:
1. 景點主圖片、景點名稱、畫廊圖片數目展示
2. 點選主圖片進入圖片畫廊,圖片畫廊可以左右滑動,點選非圖片區域可退回景點詳情頁
細節1實現:
根據上文可知,父元件Detail以屬性繫結的方式向Banner元件傳遞了三個資料項,分別是:
- sightName:景點名稱
- bannerImg:景點主圖片
- gallaryImgs:畫廊圖片集
資料獲取
props: { sightName: String, bannerImg: String, gallaryImgs: Array },
資料對映渲染:該DOM上綁定了點選事件:handleBannerClick,細節2中會提到。
<div class="banner" @click="handleBannerClick"> <img class="banner-img" :src="bannerImg" alt=""/> <div class="banner-info"> <div class="banner-title"> {{this.sightName}} </div> <div class="banner-number"> <span class="iconfont banner-icon"></span> {{this.gallaryImgs.length}} </div> </div> </div>
細節2實現:通用元件Gallery、Fade的使用
在該部分的實現中,將Gallery畫廊元件以及Fade簡單動畫元件做了封裝,封裝為通用元件,也方便其他元件進行呼叫。
Gallery:畫廊元件
關於畫廊元件,本質上是Swiper元件,進行了些定製化的配置。比如,鋪滿全屏,分頁器樣式,狀態檢查等。
關於Swiper元件,詳情API及使用方法見:https://3.swiper.com.cn/api/index.html
<template>:迴圈資料項、點選事件:handleGallaryClick,控制是否進入景點圖片畫廊
<template> <div class="container" @click="handleGallaryClick"> <div class="wrapper"> <swiper :options="swiperOptions"> <!-- slides --> <swiper-slide v-for="(item, index) in imgs" :key="index"> <img class="gallary-img" :src="item"> </swiper-slide> <!-- Optional controls --> <div class="swiper-pagination" slot="pagination"></div> </swiper> </div> </div> </template>
迴圈資料項:由於Gallery元件為公共元件,呼叫該元件的即為其父元件(這裡是Banner)。Banner元件將gallaryImgs陣列傳遞給Gallery元件,在模板中通過index為索引進行了遍歷輸出。
props: { imgs: { type: Array, // 預設值為空陣列 default() { return [] } } },
點選事件:handleGallaryClick,當點選區域時觸發點選事件,向父元件(Banner)觸發close事件,關閉通用畫廊元件。
methods: { handleGallaryClick() { // 關閉公共畫廊事件 this.$emit('close') } },
定製化配置:Swiper3 相關配置 https://3.swiper.com.cn/api/
data() { return { swiperOptions: { pagination: '.swiper-pagination', // 分式分頁器 paginationType: 'fraction', // 將observe應用於Swiper的父元素。當Swiper的父元素變化時,例如window.resize,Swiper更新。 observeParents: true, // 啟動動態檢查器(OB/觀眾/觀看者),當改變swiper的樣式(例如隱藏/顯示)或者修改swiper的子元素時,自動初始化swiper。 observer: true } } },
官網API說明: https://3.swiper.com.cn/api/
Fade:簡單CSS動畫元件該通用元件實質上為過渡效果的動畫元件,之前文章中也提到過,CSS簡單的動畫過渡效果,這裡同一封裝為元件方便其他元件使用。
其他元件在使用Fade元件時候,外層巢狀元件標籤即可,元件將以插槽的方式包裹在<transition>標籤內部。
<template> <transition> <slot></slot> </transition> </template> <script> export default { name: 'Fade' } </script> <style lang="stylus" scoped> .v-enter, .v-leave-to opacity: 0 .v-enter-active, .v-leave-active transition: opacity .5s </style>
我們回到Banner元件中,引入並使用這兩個通用元件。
-
引入並註冊通用元件
import CommonGallary from 'common/gallary/Gallary' import FadeAnimation from 'common/fade/Fade' components: { CommonGallary, FadeAnimation }
-
使用通用元件
<template>
<!-- 新增動畫效果:漸隱漸現,內部common-gallary元件以插槽的方式嵌入 --> <fade-animation> <!-- 公用圖片畫廊 父子元件互動 + 展示控制--> <common-gallary :imgs="gallaryImgs" @close="handleGallaryClose" v-show="showGallary"></common-gallary> </fade-animation>
這裡可以看到傳遞給Gallery元件傳遞給父元件Banner的close的事件:handleGallaryClose,並且該元件上採用v-show做了元件展示的控制,控制變數為showGallary。
預設情況下:
data() { return { showGallary: false } },
點選景點主圖片區域時:
handleBannerClick() { this.showGallary = true }
點選通用元件Gallary區域時:
handleGallaryClose() { this.showGallary = false }