18-首页主体-轮播图-逻辑封装
目的: 封装小兔鲜轮播图组件,第三步:逻辑功能实现。
大致步骤:
- 自动播放,暴露自动轮播属性,设置了就自动轮播
- 如果有自动播放,鼠标进入离开,暂停,开启
- 指示器切换,上一张,下一张
- 销毁组件,清理定时器
** 落地代码 ** : src/components/library/xtx-carousel.vue
- 自动轮播实现
+import { ref, watch } from 'vue'
export default {
name: 'XtxCarousel',
props: {
sliders: {
type: Array,
default: () => []
},
+ duration: {
+ type: Number,
+ default: 3000
+ },
+ autoPlay: {
+ type: Boolean,
+ default: false
+ }
},
setup (props) {
// 默认显示的图片的索引
const index = ref(0)
+ // 自动播放
+ let timer = null
+ const autoPlayFn = () => {
+ clearInterval(timer)
+ timer = setInterval(() => {
+ index.value++
+ if (index.value >= props.sliders.length) {
+ index.value = 0
+ }
+ }, props.duration)
+ }
+ watch(() => props.sliders, (newVal) => {
+ // 有数据&开启自动播放,才调用自动播放函数
+ if (newVal.length && props.autoPlay) {
+ index.value = 0
+ autoPlayFn()
+ }
+ }, { immediate: true })
+
return { index }
}
}
- 如果有自动播放,鼠标进入离开,暂停,开启
// 鼠标进入停止,移出开启自动,前提条件:autoPlay为true
const stop = () => {
if (timer) clearInterval(timer)
}
const start = () => {
if (props.sliders.length && props.autoPlay) {
autoPlayFn()
}
}
return { index, stop, start }
+ <div class='xtx-carousel' @mouseenter="stop()" @mouseleave="start()">
使用需要加 auto-play <XtxCarousel auto-play :sliders="sliders" />
- 指示器切换,上一张,下一张
// 上一张下一张
const toggle = (step) => {
const newIndex = index.value + step
if (newIndex >= props.sliders.length) {
index.value = 0
return
}
if (newIndex < 0) {
index.value = props.sliders.length - 1
return
}
index.value = newIndex
}
return { index, stop, start, toggle }
销毁组件,清理定时器
// 组件消耗,清理定时器
onUnmounted(() => {
clearInterval(timer)
})
总结: 按照思路步骤,一步步实现即可。
19-首页主体-面板封装
目的: 提取首页的公用面板进行复用
大致思路:
- 头部
- 标题和副标题由props传入
- 右侧内容由插槽传入
- 查看更多使用次数多封装成全局组件
- 主体
- 全部由插槽传入
- 全部由插槽传入
实现步骤:
- 查看更多全局组件实现
src/components/library/xtx-more.vue
定义
<template>
<RouterLink :to="path" class="xtx-more">
<span>查看全部</span>
<i class="iconfont icon-angle-right"></i>
</RouterLink>
</template>
<script>
export default {
name: 'XtxMore',
props: {
path: {
type: String,
default: '/'
}
}
}
</script>
<style scoped lang='less'>
.xtx-more {
margin-bottom: 2px;
span {
font-size: 16px;
vertical-align: middle;
margin-right: 4px;
color: #999;
}
i {
font-size: 14px;
vertical-align: middle;
position: relative;
top: 2px;
color: #ccc;
}
&:hover {
span,i {
color: @xtxColor;
}
}
}
</style>
src/components/library/index.js
注册
import XtxSkeleton from './xtx-skeleton.vue'
import XtxCarousel from './xtx-carousel.vue'
+import XtxMore from './xtx-more.vue'
export default {
install (app) {
app.component(XtxSkeleton.name, XtxSkeleton)
app.component(XtxCarousel.name, XtxCarousel)
+ app.component(XtxMore.name, XtxMore)
}
}
- 定义首页需要的面板组件
<template>
<div class="home-panel">
<div class="container">
<div class="head">
<h3>{{ title }}<small>{{ subTitle }}</small></h3>
<slot name="right" />
</div>
<slot />
</div>
</div>
</template>
<script>
export default {
name: 'HomePanel',
props: {
title: {
type: String,
default: ''
},
subTitle: {
type: String,
default: ''
}
}
}
</script>
<style scoped lang='less'>
.home-panel {
background-color: #fff;
.head {
padding: 40px 0;
display: flex;
align-items: flex-end;
h3 {
flex: 1;
font-size: 32px;
font-weight: normal;
margin-left: 6px;
height: 35px;
line-height: 35px;
small {
font-size: 16px;
color: #999;
margin-left: 20px;
}
}
}
}
</style>
20-首页主体-新鲜好物
目的: 使用面板组件完成新鲜好物模块。
大致步骤:
- 封装API调用接口
- 进行组件基础布局
- 调用接口渲染组件
落地代码:
src/api/home.js
export const findNew = () => {
return request('home/new', 'get')
}
<template>
<div class="home-new">
<HomePanel title="新鲜好物" sub-title="新鲜出炉 品质靠谱">
<template #right><XtxMore path="/" /></template>
<!-- 面板内容 -->
<ul class="goods-list">
<li v-for="item in goods" :key="item.id">
<RouterLink :to="`/product/${item.id}`">
<img :src="item.picture" alt="">
<p class="name ellipsis">{{item.name}}</p>
<p class="price">¥{{item.price}}</p>
</RouterLink>
</li>
</ul>
</HomePanel>
</div>
</template>
<script>
import { ref } from 'vue'
import HomePanel from './home-panel'
import { findNew } from '@/api/home'
export default {
name: 'HomeNew',
components: { HomePanel },
setup () {
const goods = ref([])
findNew().then(data => {
goods.value = data.result
})
return { goods }
}
}
</script>
<style scoped lang="less">
.goods-list {
display: flex;
justify-content: space-between;
height: 406px;
li {
width: 306px;
height: 406px;
background: #f0f9f4;
.hoverShadow();
img {
width: 306px;
height: 306px;
}
p {
font-size: 22px;
padding: 12px 30px 0 30px;
text-align: center;
}
.price {
color: @priceColor;
}
}
}
</style>
src/views/home/index.vue
<!-- 新鲜好物 -->
+ <HomeNew />
</div>
</template>
<script>
import HomeCategory from './components/home-category'
import HomeBanner from './components/home-banner'
+import HomeNew from './components/home-new'
export default {
name: 'xtx-home-page',
+ components: { HomeCategory, HomeBanner, HomeNew }
}
</script>
总结: vue3.0中 只支持v-slot指令,所以需要配合template来使用。
21-首页主体-人气推荐
目的: 完成人气推荐模块
大致步骤:
- 定义API函数
- 定义组件且完成渲染
- 在首页组件中导入使用
落地代码:
src/api/home.js
export const findHot = () => {
return request('home/hot', 'get')
}
src/views/home/components/home-hot.vue
<template>
<HomePanel title="人气推荐" sub-title="人气爆款 不容错过">
<ul ref="pannel" class="goods-list">
<li v-for="item in goods" :key="item.id">
<RouterLink to="/">
<img :src="item.picture" alt="">
<p class="name">{{item.title}}</p>
<p class="desc">{{item.alt}}</p>
</RouterLink>
</li>
</ul>
</HomePanel>
</template>
<script>
import { ref } from 'vue'
import HomePanel from './home-panel'
import { findHot } from '@/api/home'
export default {
name: 'HomeNew',
components: { HomePanel },
setup () {
const goods = ref([])
findHot().then(data => {
goods.value = data.result
})
return { goods }
}
}
</script>
<style scoped lang='less'>
.goods-list {
display: flex;
justify-content: space-between;
height: 426px;
li {
width: 306px;
height: 406px;
.hoverShadow();
img {
width: 306px;
height: 306px;
}
p {
font-size: 22px;
padding-top: 12px;
text-align: center;
}
.desc {
color: #999;
font-size: 18px;
}
}
}
</style>
src/views/home/index.vue
<!-- 新鲜好物 -->
<HomeNew />
<!-- 人气推荐 -->
+ <HomeHot />
</div>
</template>
<script>
import HomeCategory from './components/home-category'
import HomeBanner from './components/home-banner'
import HomeNew from './components/home-new'
+import HomeHot from './components/home-hot'
export default {
name: 'xtx-home-page',
+ components: { HomeCategory, HomeBanner, HomeNew, HomeHot }
}
</script>