Vue3电商项目实战-首页模块6【22-首页主体-补充-vue动画、23-首页主体-面板骨架效果、4-首页主体-组件数据懒加载、25-首页主体-热门品牌】
文章目录
- 22-首页主体-补充-vue动画
- 23-首页主体-面板骨架效果
- 24-首页主体-组件数据懒加载
- 25-首页主体-热门品牌
22-首页主体-补充-vue动画
目标: 知道vue中如何使用动画,知道Transition组件使用。
当vue中,显示隐藏,创建移除,一个元素或者一个组件的时候,可以通过transition实现动画。

如果元素或组件离开,完成一个淡出效果:
<transition name="fade"><p v-if="show">100</p>
</transition>
.fade-leave {opacity: 1
}
.fade-leave-active {transition: all 1s;
}
.fade-leave-to {opcaity: 0
}
- 进入(显示,创建)
- v-enter 进入前 (vue3.0 v-enter-from)
- v-enter-active 进入中
- v-enter-to 进入后
- 离开(隐藏,移除)
- v-leave 进入前 (vue3.0 v-leave-from)
- v-leave-active 进入中
- v-leave-to 进入后
多个transition使用不同动画,可以添加nam属性,name属性的值替换v即可。
23-首页主体-面板骨架效果
目的: 加上面板的骨架加载效果
定义一个骨架布局组件:
src/views/home/components/home-skeleton.vue
<template><div class='home-skeleton'><div class="item" v-for="i in 4" :key="i" :style="{backgroundColor:bg}"><XtxSkeleton bg="#e4e4e4" width="306px" height="306px" animated /><XtxSkeleton bg="#e4e4e4" width="160px" height="24px" animated /><XtxSkeleton bg="#e4e4e4" width="120px" height="24px" animated /></div></div>
</template><script>
export default {name: 'HomeSkeleton',props: {bg: {type: String,default: '#fff'}}
}
</script><style scoped lang='less'>
.home-skeleton {width: 1240px;height: 406px;display: flex;justify-content: space-between;.item {width: 306px;.xtx-skeleton ~ .xtx-skeleton{display: block;margin: 16px auto 0;}}
}
</style>
在 home-hot home-new 组件分别使用
<HomePanel title="人气推荐" sub-title="人气爆款 不容错过">
+ <div style="position: relative;height: 426px;">
+ <Transition name="fade">
+ <ul v-if="goods.length" 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>
+ <HomeSkeleton v-else />
+ </Transition>
+ </div></HomePanel>
<template><HomePanel title="新鲜好物" sub-title="新鲜出炉 品质靠谱"><template v-slot:right><XtxMore /></template>
+ <div style="position: relative;height: 406px;">
+ <Transition name="fade">
+ <ul v-if="goods.length" 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.name}}</p><p class="price">¥{{item.price}}</p></RouterLink></li></ul>
+ <HomeSkeleton bg="#f0f9f4" v-else />
+ </Transition>
+ </div></HomePanel>
</template>
在 src/assets/styles/common.less 定义动画
.fade{&-leave {&-active {position: absolute;width: 100%;transition: opacity .5s .2s;z-index: 1;}&-to {opacity: 0;}}
}
注意:
- 动画的父容器需要是定位,防止定位跑偏。
24-首页主体-组件数据懒加载
目的: 实现当组件进入可视区域在加载数据。
我们可以使用 @vueuse/core 中的 useIntersectionObserver 来实现监听进入可视区域行为,但是必须配合vue3.0的组合API的方式才能实现。
大致步骤:
- 理解
useIntersectionObserver的使用,各个参数的含义 - 改造 home-new 组件成为数据懒加载,掌握
useIntersectionObserver函数的用法 - 封装
useLazyData函数,作为数据懒加载公用函数 - 把
home-new和home-hot改造成懒加载方式
落的代码:
1.先分析下这个useIntersectionObserver 函数:
// stop 是停止观察是否进入或移出可视区域的行为
const { stop } = useIntersectionObserver(// target 是观察的目标dom容器,必须是dom容器,而且是vue3.0方式绑定的dom对象target,// isIntersecting 是否进入可视区域,true是进入 false是移出// observerElement 被观察的dom([{ isIntersecting }], observerElement) => {// 在此处可根据isIntersecting来判断,然后做业务},
)
2.开始改造 home-new 组件:src/views/home/components/home-new.vue
- 进入可视区后获取数据
<div ref="box" style="position: relative;height: 406px;">
// 省略。。。
<script>
import HomePanel from './home-panel'
import HomeSkeleton from './home-skeleton'
import { findNew } from '@/api/home'
import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
export default {name: 'HomeNew',components: { HomePanel, HomeSkeleton },setup () {const goods = ref([])const box = ref(null)const { stop } = useIntersectionObserver(box,([{ isIntersecting }]) => {if (isIntersecting) {stop()findNew().then(data => {goods.value = data.result})}})return { goods, box }}
}
</script>
3.由于首页面板数据加载都需要实现懒数据加载,所以封装一个钩子函数,得到数据。
src/hooks/index.js
// hooks 封装逻辑,提供响应式数据。
import { useIntersectionObserver } from '@vueuse/core'
import { ref } from 'vue'
// 数据懒加载函数
export const useLazyData = (apiFn) => {// 需要// 1. 被观察的对象// 2. 不同的API函数const target = ref(null)const result = ref([])const { stop } = useIntersectionObserver(target,([{ isIntersecting }], observerElement) => {if (isIntersecting) {stop()// 调用API获取数据apiFn().then(data => {result.value = data.result})}})// 返回--->数据(dom,后台数据)return { target, result }
}
4.再次改造 home-new 组件:src/views/home/components/home-new.vue
import { findNew } from '@/api/home'
+import { useLazyData } from '@/hooks'
export default {name: 'HomeNew',components: { HomePanel, HomeSkeleton },setup () {
+ const { target, result } = useLazyData(findNew)
+ return { goods: result, target }}
}
+ <div ref="target" style="position: relative;height: 426px;">
5.然后改造 home-hot 组件:src/views/home/components/home-hot.vue
+ <div ref="target" style="position: relative;height: 426px;">
import { findHot } from '@/api/home'
import HomePanel from './home-panel'
import HomeSkeleton from './home-skeleton'
+import { useLazyData } from '@/hooks'
export default {name: 'HomeHot',components: { HomePanel, HomeSkeleton },setup () {
+ const { target, result } = useLazyData(findHot)
+ return { target, list: result }}
}
25-首页主体-热门品牌
目的: 实现品牌的展示,和切换品牌效果。
基本步骤:
- 准备基础布局组件
- 获取数据实现渲染,完成切换效果
- 加上骨架效果和数据懒加载
落的代码:
.基础结构:src/views/home/components/home-brand.vue`
<template><HomePanel title="热门品牌" sub-title="国际经典 品质保证"><template v-slot:right><a href="javascript:;" class="iconfont icon-angle-left prev"></a><a href="javascript:;" class="iconfont icon-angle-right next"></a></template><div class="box" ref="box"><ul class="list" ><li v-for="i in 10" :key="i"><RouterLink to="/"><img src="http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/brand_goods_1.jpg" alt=""></RouterLink></li></ul></div></HomePanel>
</template><script>
import HomePanel from './home-panel'
export default {name: 'HomeBrand',components: { HomePanel }
}
</script><style scoped lang='less'>
.home-panel {background:#f5f5f5
}
.iconfont {width: 20px;height: 20px;background: #ccc;color: #fff;display: inline-block;text-align: center;margin-left: 5px;background: @xtxColor;&::before {font-size: 12px;position: relative;top: -2px}&.disabled {background: #ccc;cursor: not-allowed;}
}
.box {display: flex;width: 100%;height: 345px;overflow: hidden;padding-bottom: 40px;.list {width: 200%;display: flex;transition: all 1s;li {margin-right: 10px;width: 240px;&:nth-child(5n) {margin-right: 0;}img {width: 240px;height: 305px;}}}
}
</style>
2.使用组件:src/views/home/index.vue
<!-- 人气推荐 --><HomeHot /><!-- 热门品牌 -->
+ <HomeBrand />
+import HomeBrand from './components/home-brand'
export default {name: 'xtx-home-page',
+ components: { HomeCategory, HomeBanner, HomeNew, HomeHot, HomeBrand }
}
2.获取数据和切换效果:
- 由于最后会使用到数据懒加载,那么我们也会使用组合API实现。
- 业务上,只有两页数据切换,0—>1 或者 1—>0 的方式。
<template><HomePanel title="热门品牌" sub-title="国际经典 品质保证"><template v-slot:right><a @click="toggle(-1)" :class="{disabled:index===0}" href="javascript:;" class="iconfont icon-angle-left prev"></a><a @click="toggle(1)" :class="{disabled:index===1}" href="javascript:;" class="iconfont icon-angle-right next"></a></template><div class="box"><ul v-if="brands.length" class="list" :style="{transform:`translateX(${-index*1240}px)`}"><li v-for="item in brands" :key="item.id"><RouterLink to="/"><img :src="item.picture" alt=""></RouterLink></li></ul></div></HomePanel>
</template><script>
import { ref } from 'vue'
import HomePanel from './home-panel'
import { findBrand } from '@/api/home'
import { useLazyData } from '@/hooks'
export default {name: 'HomeBrand',components: { HomePanel },setup () {// 获取数据const brands = ref([])findBrand(10).then(data => {brands.value = data.result})// 切换效果,前提只有 0 1 两页const index = ref(0)// 1. 点击上一页// 2. 点击下一页const toggle = (step) => {const newIndex = index.value + stepif (newIndex < 0 || newIndex > 1) returnindex.value = newIndex}return { brands, toggle, index }}
}
</script>
3.加上数据懒加载和骨架效果
<template><HomePanel title="热门品牌" sub-title="国际经典 品质保证"><template v-slot:right><a @click="toggle(-1)" :class="{disabled:index===0}" href="javascript:;" class="iconfont icon-angle-left prev"></a><a @click="toggle(1)" :class="{disabled:index===1}" href="javascript:;" class="iconfont icon-angle-right next"></a></template>
+ <div ref="target" class="box">
+ <Transition name="fade">
+ <ul v-if="brands.length" class="list" :style="{transform:`translateX(${-index*1240}px)`}"><li v-for="item in brands" :key="item.id"><RouterLink to="/"><img :src="item.picture" alt=""></RouterLink></li></ul>
+ <div v-else class="skeleton">
+ <XtxSkeleton class="item" v-for="i in 5" :key="i" animated bg="#e4e4e4" width="240px" height="305px"/>
+ </div>
+ </Transition></div></HomePanel>
</template><script>
import { ref } from 'vue'
import HomePanel from './home-panel'
import { findBrand } from '@/api/home'
+import { useLazyData } from '@/hooks'
export default {name: 'HomeBrand',components: { HomePanel },setup () {// 获取数据// const brands = ref([])// findBrand(10).then(data => {// brands.value = data.result// })
+ // 注意:useLazyData需要的是API函数,如果遇到要传参的情况,自己写函数再函数中调用API
+ const { target, result } = useLazyData(() => findBrand(10))// 切换效果,前提只有 0 1 两页const index = ref(0)// 1. 点击上一页// 2. 点击下一页const toggle = (step) => {const newIndex = index.value + stepif (newIndex < 0 || newIndex > 1) returnindex.value = newIndex}
+ return { brands: result, toggle, index, target }}
}
</script>
.skeleton {width: 100%;display: flex;.item {margin-right: 10px;&:nth-child(5n) {margin-right: 0;}}}
总结: 注意下useLazyData传参的情况。
相关文章:
Vue3电商项目实战-首页模块6【22-首页主体-补充-vue动画、23-首页主体-面板骨架效果、4-首页主体-组件数据懒加载、25-首页主体-热门品牌】
文章目录22-首页主体-补充-vue动画23-首页主体-面板骨架效果24-首页主体-组件数据懒加载25-首页主体-热门品牌22-首页主体-补充-vue动画 目标: 知道vue中如何使用动画,知道Transition组件使用。 当vue中,显示隐藏,创建移除&#x…...
linux 使用
一、操作系统命令 1、版本命令:lsb_release -a 2、内核命令:cat /proc/version 二、debian与CentOS区别 debian德班和CentOS是Linux里两个著名的版本。两者的包管理方式不同。 debian安装软件是用apt(apt-get install),而CentOS是用yum de…...
基于遗传算法的微电网调度(风、光、蓄电池、微型燃气轮机)(Matlab代码实现)
💥💥💥💞💞💞欢迎来到本博客❤️❤️❤️💥💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清…...
方向导数与梯度下降
文章目录方向角与方向余弦方向角方向余弦方向导数定义性质梯度下降梯度下降法(Gradient descent)是一个一阶最优化算法,通常也称为最速下降法。 要使用梯度下降法找到一个函数的局部极小值,必须向函数上当前点对应梯度(…...
Java岗面试题--Java基础(日积月累,每日三题)
目录面试题一:Java中有哪些容器(集合类)?追问:Java中的容器,线程安全和线程不安全的分别有哪些?面试题二: HashMap 的实现原理/底层数据结构? JDK1.7 和 JDK1.8追问一&am…...
java基础—Volatile关键字详解
java基础—Volatile关键字详解 文章目录java基础—Volatile关键字详解并发编程的三大特性:volatile的作用是什么volatile如何保证有可见性volatile保证可见性在JMM层面原理volatile保证可见性在CPU层面原理可见性问题的例子volatile如何保证有序性单例模式使用volat…...
内存检测工具Sanitizers
Sanitizers介绍 Sanitizers 是谷歌开源的内存检测工具,包括AddressSanitizer、MemorySanitizer、ThreadSanitizer、LeakSanitizer。 Sanitizers是LLVM的一部分。 gcc4.8:支持Address和Thread Sanitizer。 gcc4.9:支持Leak Sanitizer和UBSani…...
Triton : OpenAI 开发的用于Gpu开发语言
Triton : OpenAI 开发的用于Gpu开发语言https://openai.com/blog/triton/1、介绍 https://openai.com/blog/triton/ 2、git地址 https://github.com/openai/triton 3、论文 http://www.eecs.harvard.edu/~htk/publication/2019-mapl-tillet-kung-cox.pdf SIMD : Single Inst…...
Python文件操作-代码案例
文章目录文件打开文件open写文件上下文管理器第三方库简单应用案例使用python生成二维码使用python操作excel程序员鼓励师学生管理系统文件 变量就在内存中,文件在硬盘中. 内存空间更小,访问速度快,成本贵,数据容易丢失,硬盘空间大,访问慢,偏移,持久化存储. \\在才是 \的含义…...
活动目录(Active Directory)管理,AD自动化
每个IT管理员几乎每天都在Active Directory管理中面临许多挑战,尤其是在管理Active Directory用户帐户方面。手动配置用户属性非常耗时、令人厌烦且容易出错,尤其是在大型、复杂的 Windows 网络中。Active Directory管理员和IT经理大多必须执行重复和世俗…...
Allegro如何使用Vertext命令修改丝印线段的形状操作指导
Allegro如何使用Vertext命令修改丝印线段的形状操作指导 在用Allegro画丝印线段的时候,如果画了一段不是自己需要形状的线段,无需删除重画,可以用Vertext命令直接编辑 如下图 修改前 修改后 具体操作如下 选择Edit...
Leetcode力扣秋招刷题路-0030
从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 30. 串联所有单词的子串 给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。…...
基于Prometheus和k8s搭建监控系统
文章目录1、实验环境2、Prometheus介绍?3、Prometheus特点3.1 样本4、Prometheus组件介绍5、Prometheus和zabbix对比分析6、Prometheus的几种部署模式6.1 基本高可用模式6.2 基本高可用远程存储6.3 基本HA 远程存储 联邦集群方案7、Prometheus的四种数据类型7.1 C…...
类和对象(下)
类和对象(下)再谈构造函数构造函数体赋值初始化列表explicit关键字static成员静态成员的特性友元友元函数友元类成员函数做友元内部类匿名对象编译器的一些优化再谈构造函数 构造函数体赋值 在创建对象的时候编译器会调用构造函数给对象中的成员变量一…...
达梦数据库单机部署
一、安装前准备 1. 安装环境 操作系统:redhat7.9 达梦数据库版本:V8 内存:2G CPU:x86_64 2. 新建用户组和用户 groupadd dinstall useradd -g dinstall -m -d /home/dmdba -S /bin/bash dmdba passwd dmdba3. 配置参数 vi /etc/security/limits.conf #在末尾添加以下内…...
从零到一学习Flutter——(二)状态和路由
背景 前文提到了Widget的状态,在Flutter中一切都是Widget,那么由Widget组成的页面,会有很多复杂的父子关系,要想交互友好,则需要这些Widget进行通讯,也就是所谓的状态管理。 同时在了解了布局之后,我们会写出很多的页面,那么在这些页面切换,也是一个很重要的能力。 …...
TC358774XBG/TC358775XBG替代方案|CS5518替代TC358774XBG/TC358775XBG设计DSI转LVSD设计资料
TC358774XBG/TC358775XBG替代方案|CS5518替代TC358774XBG/TC358775XBG设计DSI转LVSD设计资料 TC358774XBG/TC358775XBG 芯片的主要功能是作为 DSI - LVDS 通信协议桥接,主芯片的视频数据可通过 DSI 链路流 出,以驱动兼容 LVDS 的显示板。换句话说&#x…...
Linux---Kernal与Shell讲解
目录 Shell简介 什么是Shell Shell分类 内核Kernal Shell简介 什么是Shell 我们首先需要知道一台完整的计算机是由硬件组成的,而人不可以直接与硬件交互,为了完成交互,进行了以下的操作 将硬件设备交由内核管理,给硬件套个内…...
Thiol-PEG-Acid,HS-PEG-COOH,巯基-聚乙二醇-羧基试剂供应
一:产品描述 1、名称 英文:HS-PEG-COOH,Thiol-PEG-Acid 中文:巯基-聚乙二醇-羧基 2、CAS编号:N/A 3、所属分类:Carboxylic acid PEG Thiol PEG 4、分子量:可定制,Thiol-聚乙二…...
数据结构与算法基础-学习-09-线性表之栈的理解、初始化顺序栈、判断顺序栈空、获取顺序栈长度的实现
一、个人理解栈是线性表的一种衍生,和之前的顺序表和链表在插入和删除元素上有较大差异,其他基本相同,栈是数据只能插入表的尾部(栈顶),删除数据时只能删除表的尾部(栈顶)数据&#…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
