按照结构新增五个组件:左侧分类、Banner、新鲜好物、人气推荐、产品列表。在 src/views/Home/components 路径下依次创建 HomeCategory.vue
、HomeBanner.vue
、HomeNew.vue
、HomeHot.vue
、HomeProduct.vue
:
在 Home 的 index.vue 模块入口组件中引入各个组件并渲染:
在 HomeCategory.vue
文件中添加以下代码:
后端接口返回的 JSON 数据格式如下:
获取数据并进行遍历输出:
创建 src/apis/home.js 文件,编写方法用于获取 Banner 图的 API:
/**
* @description: 获取banner图
*/
import http from '@/utils/http'
export function getBannerAPI() {
return http({
url: 'home/banner'
})
}
获取数据并进行遍历输出:
在页面中显示的【新鲜好物】和【人气推荐】两个模块是一样的分布,代码也相同,只是显示的数据不同,因此可以抽取公共部分进行复用。
核心思路:把可复用的结构只写一次,把可能发生变化的部分抽象成组件参数(popS/插槽)。抽象可变的部分:
在 src/views/Home/components 路径下创建 HomePanel.vue 文件,代码如下:
新鲜好物新鲜出炉 品质靠谱
主体内容
因为主标题和副标题是纯文本,可以抽象成 props 传入,代码如下:
<script setup>
//定义 Props,主标题和副标题
defineProps({
title: {
type: String
},
subTitle: {
type: String
}
})
</script>
在主代码中使用参数:
{{title}}{{ subTitle }}
在 src/views/Home/components 路径下有之前创建好的 HomeNew.vue 文件,添加以下代码:
在 src/apis/home.js 文件中,编写方法用于获取 【新鲜好物】 的 API:
/**
* @description: 获取新鲜好物
* @param {*}
* @return {*}
*/
export function findNewAPI(){
return http({
url: '/home/new'
})
}
获取数据并进行遍历输出:
-
{{ item.name }}
¥{{ item.price }}
在 src/views/Home/components 路径下有之前创建好的 HomeHot.vue 文件,添加以下代码:
在 src/apis/home.js 文件中,编写方法用于获取 【人气推荐】 的 API:
/**
* @description: 获取人气推荐
* @param {*}
* @return {*}
*/
export function findHotAPI(){
return http({
url:'/home/hot'
})
}
获取数据并进行遍历输出:
-
{{ item.title }}
main.js 入口文件通常只做一些初始化的事情,不应该包含太多的逻辑代码,可以通过插件的方法把懒加载指令封装为插件,main.js 入口文件只需要负责注册插件即可。
在 src/directives/ 目录下创建 index.js 文件,在其中自定义指令 v-img-lazy
,实现当图片进入视口区域时,才对其进行加载:
// 定义懒加载插件
import { useIntersectionObserver } from '@vueuse/core'
export const lazyPlugin = {
install (app) {
// 懒加载指令逻辑
app.directive('img-lazy', {
mounted (el, binding) {
// el: 指令绑定的那个元素 img
// binding: binding.value 指令等于号后面绑定的表达式的值 图片url
console.log(el, binding.value)
const { stop } = useIntersectionObserver(
el,
([{ isIntersecting }]) => {
console.log(isIntersecting)
if (isIntersecting) {
// 进入视口区域
el.src = binding.value
stop()
}
},
)
}
})
}
}
在 main.js 中自定义指令注册为全局指令:
// 全局指令注册
import { directivePlugin } from '@/directives'
app.use(directivePlugin)
在 HomeHot.vue 和 HomeNew.vue 文件的代码上使用自定义的懒加载指令进行修改。修改之后如下:
这样当图片进入视口区域后,才会将图片的地址赋给 img 的 src 属性。
因为商品列表页面也是有很多模块代码可以复用,只是数据不同,因此我们依然可以继续使用封装好的面板组件。
在之前创建好的 HomeProduct.vue 文件中添加如下代码:
在 src/apis/home.js 文件中,封装获取商品列表信息的接口:
/**
* @description: 获取所有商品模块
* @param {*}
* @return {*}
*/
export function getGoodsAPI() {
return http({
url: '/home/goods'
})
}
获取数据并进行遍历输出:
使用 v-img-lazy
懒加载指令替换 img 标签的原始 src:
<img v-img-lazy="cate.picture" />
<img v-img-lazy="goods.picture" alt="" />
在小兔鲜项目的很多个业务模块中都需要用到同样的商品展示模块,没必要重复定义,封装起来,方便复用。
原代码:
-
{{ good.name }}
{{ good.desc }}
¥{{ good.price }}
修改之后的代码:
-
创建 src\views\Home\components\GoodsItem.vue 文件,抽取可复用的代码,并将商品信息抽象成 props 参数传入:
{{ good.name }}
{{ good.desc }}
¥{{ good.price }}
修改 src\views\Home\components\HomeProduct.vue 中商品信息的代码:
-