Vue相关案例
案例一
案例:实现v-for的模板编译
根据响应式数据渲染模板到页面
技术:
JavaScript ES5/vite/数据响应式/模板编译
问题:如何实现数据响应式?
Proxy代理劫持数据
项目结构:
├─app.js├─index.html├─package.json├─MyVue3.0| ├─application.js -管理响应式数据组件初始化/页面挂载创建| ├─compile.js -模板编译/编译节点/替换节点/实现v-for{}/{{}}文本替换| ├─handler.js - 处理proxy代理里的getter/setter方法| ├─index.js| ├─reactive.js - 实现数据响应式| └utils.js - 工具:判断是否是对象├─components| ├─TestB| | └index.js| ├─TestA| | └index.js
模拟 vue3.x版本环境下搭建的v-for
//app.jsimport { createApp } from './createApp';import TestA from './components/TestA';const app = createApp({components: [TestA]});app.mount('#app');
//createApp.jsexport function createApp() {return {mount: mount}}function mount(el) { }
源码地址:
https://gitee.com/kevinleeeee/v-for-vue3.x-demo
案例二
案例:万年历
功能:
- 当天/当月/当年的日期信息
聚合接口:
- 获取当前的详细信息
- 获取近期的假期
- 获取当年所有假期
//项目创建vue create calendar-pro//增加vue3特性vue add vue-next
vue3.0 提供了极大的程序设计的可能性,它单独的抛出了许多的 Composition API 组合,每个 API实际上是独立的,可以在任何地方(vue,vuex)去取出相应的 API到程序里调用,每个 Composition API 都是一个工具函数,方便不同的应用场景下使用来完成逻辑业务需要
//vue3.0开发思想,Composition API组合的函数都要解构出来使用//像vue2.0里的method/data/computed...import { computed, watch, onMounted } from "vue";//setup函数:所有逻辑在里面编写,并把视图所有需要的属性和方法一一导出
程序开发优先考虑数据,有了数据才开始写视图,没有数据先模拟数据
//项目目录├─babel.config.js├─package.json├─README.md├─vue.config.js - 配置后端数据代理/关闭eslint├─src| ├─App.vue - 根页面结构/路由占位/组件缓存/路由重定向/路由地址侦听改变state| ├─main.js - 入口文件/创建应用/注册路由/注册store/挂载应用| ├─views - 视图层| | ├─Day.vue 当天页面组件/组件通信/挂载时请求后台数据/侦听修改state| | ├─Month.vue 近期页面组件/组件通信/挂载时请求后台数据/侦听修改state| | └Year.vue 当年页面组件/组件通信/挂载时请求后台数据/侦听修改state| ├─store| | ├─index.js - 出口文件/创建Store实例/注册state,mutations| | ├─mutations.js - 管理state修改的方法(修改标题,输出内容长度,输入内容,错误代码,请求数据,缓存field)| | └states.js - 初始化state对象(标题,输入内容,长度,错误状态码,请求数据)| ├─services - 数据请求层| | ├─index.js - 封装请求数据方法/请求到的数据提交存入state| | └request.js - 封装接口请求方法/获取当天/近期/当年详细信息| ├─router| | └index.js - 路由出口文件/配置路由地址和对应(或动态)加载组件/创建组件实例| ├─libs| | ├─https.js - 封装请求数据POST/GET方法| | └utils.js - 工具:加零/拿图标日期/格式化中文日期/拿当前日期/格式化输入日期| ├─data| | ├─error.js - 错误状态代码对象数据| | └tab.js - 底栏tab的图标数组数据| ├─configs| | └keys.js - 配置聚合appKey| ├─components| | ├─YearPage - 当前组件| | | ├─Item.vue - 子项/绑定视图| | | └List.vue - 列表项/遍历子项/传参| | ├─Tab - tab图标底栏组件| | | ├─Icon.vue - 子项/图标/路由跳转链接/绑定视图| | | └index.vue - 遍历子项/传参| | ├─SearchInput - 输入框组件| | | └index.vue - 绑定视图/根据输入内容做事件处理/侦听修改| | ├─MonthPage - 近期组件| | | ├─Item.vue - 子项/绑定视图| | | └List.vue - 列表项/遍历子项/传参| | ├─Header - 标题组件| | | └index.vue 定义视图插槽/根组件设置标题内容| | ├─ErrorTip - 错误提示组件| | | └index.vue - 获取错误状态码/绑定视图| | ├─DayPage - 当天组件| | | ├─Card.vue - 出口/绑定视图/传参| | | ├─List| | | | ├─index.vue - 列表项/传参| | | | └Item.vue - 子项/视图绑定| ├─assets| | ├─js| | | ├─common.js| | | └fastclick.js| | ├─img| | | ├─bg.jpg| | | ├─error.png| | ├─css| | | ├─border.css| | | └resets.css├─public| ├─favicon.ico| └index.html
源码地址:
https://gitee.com/kevinleeeee/vue3-wannianli-demo
案例三
案例:星座运势
功能:
tab底栏(今天/明天/本周/本月/本年)- 标题
nav栏(12 星座)- 卡片
- 健康指数
- 列表
聚合接口:
接口地址:http://web.juhe.cn/constellation/getAll返回格式:json请求方式:http get请求示例:http://web.juhe.cn/constellation/getAll?consName=%E7%8B%AE%E5%AD%90%E5%BA%A7&type=today&key=申请的KEY接口备注:十二星座的今日运势
请求参数说明:
| 名称 | 必填 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 在个人中心->我的数据,接口名称上方查看 |
| consName | 是 | string | 星座名称,如:双鱼座 |
| type | 是 | string | 运势类型:today,tomorrow,week,month,year |
JSON返回示例:
/*今日或明日运势格式*/{"name": "狮子座",/*星座名称*/"datetime": "2014年06月27日",/*日期*/"date": 20140627,"all": "89",/*综合指数*/"color": "古铜色",/*幸运色*/"health": "95",/*健康指数*/"love": "80",/*爱情指数*/"money": "84",/*财运指数*/"number": 8,/*幸运数字*/"QFriend": "处女座",/*速配星座*/"summary": "有些思考的小漩涡... ",/*今日概述*/"work": "80" /*工作指数*/"error_code": 0 /*返回码*/}
问题:如何对 nav栏(白羊座/处女座..)切换时实现内容更新切换?
在点击 nav栏时重新向后端请求数据,配合actived激活函数,解决组件不同步的问题
export default {...,setup() {const store = useStore(),state = store.state,status = ref("");onMounted(() => {getData(store);//定义的响应式状态属性在挂载组件时保存了consName数据(金牛座)status.value = state.consName;});//激活函数onActivated(() => {//如果他俩不同,说明上面挂载组件的阶段还没有进行过//此操作可以解决组件不同步的问题if (status.value !== state.consName) {getData(store);status.value = state.consName;}});},};
//项目目录:├─vue.config.js - 关闭eslint/代理跨域├─src| ├─App.vue - 根组件/页面结构/路由重定向/路由地址监听/修改state| ├─main.js - 入口文件/注册App/插件/store/路由| ├─views| | ├─Month.vue - 本月页面内容组件/组件挂载请求数据/修改state/视图绑定更新| | ├─Today.vue - 同上| | ├─Tomorrow.vue - 同上| | ├─Week.vue - 同上| | └Year.vue - 同上| ├─store| | ├─index.js| | ├─mutations.js| | └state.js| ├─services| | ├─index.js| | └request.js| ├─router| | └index.js| ├─libs| | ├─https.js| | └utils.js| ├─directives - 自定义指令| | ├─index.js - 出口文件| | └navCurrent.js - 挂载/更新方法时定义相关逻辑| ├─datas| | ├─cache.js| | ├─error.js - 错误状态码数据| | ├─nav.js - nav栏数据| | ├─num.js - 指数数据| | └tab.js - tab底栏图标数据| ├─configs| | └keys.js| ├─components| | ├─Tab| | | ├─Icon.vue - 图标组件| | | └index.vue - 底栏组件| | ├─NumList| | | ├─index.vue| | | └Item.vue| | ├─NavBar| | | ├─index.vue| | | └Item.vue| | ├─List| | | ├─MonthList.vue - 本月内容组件(里面包含复用的组件)| | | ├─TodayList.vue - 今天内容组件(里面包含复用的组件)| | | ├─TomorrowList.vue - 明天内容组件(里面包含复用的组件)| | | ├─WeekList.vue - 本周内容组件(里面包含复用的组件)| | | └YearList.vue - 本年内容组件(里面包含复用的组件)| | ├─Header| | | └index.vue| | ├─ErrorTip| | | └index.vue| | ├─common| | | ├─Card.vue - 公共卡片组件| | | ├─ConsItem.vue - 公共子项内容组件| | | ├─index.js - 全局组件注册的出口文件| | | └Summary.vue - 公共运势总结组件| ├─assets| | ├─js| | | ├─common.js| | | └fastclick.js| | ├─img| | | ├─cons.png| | | ├─error.jpg| | | ├─双子座.jpeg| | ├─css| | | ├─border.css| | | └resets.css├─public| └index.html
源码地址:
https://gitee.com/kevinleeeee/vue3-constellation-demo
案例四
案例:驾照题库(未完成)
备注:
目前完成至首页的组件编写,答题和结果还没完成
功能:
- 页面:首页选择/答题/结果
- 后端数据本地缓存
//项目结构:├─vue.config.js├─src| ├─App.vue - 根组件/视图结构/监听路由| ├─main.js - 入口文件| ├─views| | ├─index.vue 首页页面区域| | ├─Result.vue| | └Test.vue| ├─store| | ├─index.js| | ├─mutations.js| | └state.js| ├─services| | ├─index.js - 请求数据函数| | └request.js - 请求数据函数里的请求方法| ├─router| | └index.js| ├─libs| | └https.js - 封装axios请求| ├─datas| | ├─error.js| | ├─subject1&a1.js - 缓存后端数据| | ├─subject1&a2.js| | ├─subject1&b1.js| | ├─subject1&b2.js| | ├─subject1&c1.js| | ├─subject1&c2.js| | ├─subject4&a1.js| | ├─subject4&a2.js| | ├─subject4&b1.js| | ├─subject4&b2.js| | ├─subject4&c1.js| | └subject4&c2.js| ├─configs| | ├─keys.js| | ├─model.js - 驾照类型数据| | └subject.js - 科目类型数据| ├─components| | ├─SubjectSelector - 科目选择组件| | | ├─index.vue - 遍历子项/传数据| | | └Item.vue - 绑定模板/点击事件/修改state| | ├─ModelSelector 驾照选择组件| | | ├─index.vue - 遍历子项/传数据| | | └Item.vue - 绑定模板/点击事件/修改state| | ├─Header| | | └index.vue
接口地址:http://v.juhe.cn/jztk/query返回格式:json请求方式:get post请求示例:http://v.juhe.cn/jztk/query?subject=1&model=c1&key=您申请的appKey&testType=rand接口备注:根据输入参数返回相关题目
请求参数说明:
| 名称 | 必填 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 您申请的 appKey |
| subject | 是 | int | 选择考试科目类型,1:科目 1;4:科目 4 |
| model | 是 | string | 驾照类型,可选择参数为:c1,c2,a1,a2,b1,b2;当 subject=4 时可省略 |
| testType | 否 | string | 测试类型,rand:随机测试(随机 100 个题目),order:顺序测试(所选科目全部题目) |
返回参数说明:
注意: 当四个选项都为空的时候表示判断题,
item1:正确item2:错误,请开发者自行判断!
| 名称 | 类型 | 说明 |
|---|---|---|
| error_code | int | 返回状态码 |
| reason | string | 返回原因 |
| result | string | 题目内容 |
JSON返回示例:
{"error_code": 0,"reason": "ok","result": [{"id": 12,"question": "这个标志是何含义?", //问题"answer": "4", //答案"item1": "前方40米减速", //选项,当内容为空时表示判断题正确选项"item2": "最低时速40公里", //选项,当内容为空时表示判断题错误选项"item3": "限制40吨轴重","item4": "限制最高时速40公里","explains": "限制最高时速40公里:表示该标志至前方限制速度标志的路段内,机动车行驶速度不得超过标志所示数值。此标志设在需要限制车辆速度的路段的起点。以图为例:限制行驶时速不得超过40公里。", //答案解释"url": "http://images.juheapi.com/jztk/c1c2subject1/12.jpg" //图片url}]}
源码地址:
https://gitee.com/kevinleeeee/vue3-license-demo
案例五
案例:UI 插件-轮播图
技术: vue3.x
功能:
- 插槽的方式定义视图结构
- 用户自定义插件配置
- 自动轮播
- 小圆点指示器联动图片
- 两侧按钮向前向后翻图片
//用户自定义的配置项<carousel:autoplay="true":duration="3000":initial="4":hasDot="true":hasDirector="true":dotBgColor="'#000'":autoplayDir="'prev'">
//项目结构:├─package.json├─README.md├─src| ├─App.vue - 根组件/用户配置/定义子组件插槽内容/遍历子组件| ├─main.js - 入口文件/注册插件| ├─libs| | ├─myUi| | | ├─index.js - 插件出口文件/全局注册组件| | | ├─Carousel| | | | ├─Director.vue - 两侧按钮组件| | | | ├─Dot.vue - 小圆点组件/根据索引长度定义圆点个数| | | | ├─index.vue - 出口文件/父组件/业务逻辑/视图绑定事件/定义子组件插槽内容| | | | └Item.vue - 每一张图片组件/组件实例绑定响应式索引和自身索引| ├─data| | └carousel.js - 定义图片名称数据| ├─assets| | ├─img| | | ├─1.jpg| | | ├─2.jpg| | | ├─3.jpg| | | ├─4.jpg| | | └5.jpg├─public| └index.html
问题:如何改变自定义配置项initial来操作视图显示指定下标的初始图片?
- 子组件标签属性定义
v-if="selfIndex === currentIndex" - 通过
Composition API里的getCurrentInstance方法拿到组件实例 - 通过组件实例里的
vnode.key属性拿到遍历子组件时的自身index - 通过组件实例的
parent.ctx.currentIndex属性拿到组件执行期上下文里定义的currentIndex - 并将
selfIndex和currentIndex属性做响应式处理并返回视图使用 - 此时,用户修改标签属性
initial的值改变视图显示下标的图片
问题:如何拿到父组件v-for遍历的item长度?
通过访问组件实例里slots.default()[0].children.length属性可以拿到
问题:如何实现自动轮播功能?
- 在
Carousel组件里新增逻辑 - 定义定时器方法和延迟时间
duration - 组件挂载完毕时拿到父组件
v-for遍历的item长度 - 执行定时器方法,并在组件卸载之前需要清除计时器
- 定时器方法里执行
setIndex(dir)函数 - 通过
currentIndex下标来显示指定图片 具体实现:
- 方向为
next:currentIndex === itemLen说明到达最后一张图片时,将currentIndex重置为 0 - 方向为
prev:currentIndex === -1说明到达第一张图片时,将currentIndex重置为itemLen - 1最后一项
- 方向为
问题:如何给轮播图添加动画效果?
- 先给子组件视图嵌套
<transition>标签 - 定义类
.v-enter-active,.v-leave-active {transition: all 0.3s linear;}.v-enter-active {transform: translateX(100%);}.v-enter-to {transform: translateX(0);}.v-leave-active {transform: translateX(0);}.v-leave-to {transform: translateX(-100%);}
问题:如何实现用户配置:hasDot="true"来显示或隐藏小圆点指示器?
通过子组件模板绑定v-if="hasDot"父组件传递过来的hasDot属性决定是否显示
问题:如何实现操作小圆点指示器?
- 定义子组件
Dot.vue - 遍历父组件
item长度v-for="item in itemLen" - 父组件
Carousel传的值有:itemLen,currentIndex,hasDot,dotBgColor - 子组件视图
<a>标签动态绑定属性:style="{ backgroundColor: item - 1 === currentIndex ? dotBgColor : '#fff',}" 以上绑定会实现:
- 小圆点同步图片的索引显示当前选中的圆点状态
- 同时实现用户配置的选中小圆点的颜色操作(默认为橙色)
- 向父组件
emit事件传递index - 父组件定义点击事件并根据子组件传的
index修改currentIndex实现点击小圆点同步当前轮播的图片
问题:如何实现鼠标移入停止轮播?
- 给
Carousel组件视图绑定两个事件:mouseenter/mouseleave - 鼠标移入时清除定时器实现停止轮播
- 鼠标移出时重新执行定时器内部封装的
autoPlay函数实现继续轮播
问题:如何实现左右两侧按钮?
- 定义子组件
Director.vue <div>标签定义属性v-if="dir === 'next'"实现用户配置操作是否显示两侧按钮<a>标签定义点击事件@click="dirClick(dir)"- 另一个
<div>标签定义属性v-else-if="dir === 'prev'" <a>标签定义点击事件@click="dirClick(dir)"- 定义
dirClick函数并把dir参数emit事件传递给父组件 - 父组件同时挂载向前和向后组件并各加上属性
dir="next"和dir="prev" - 父组件根据
dirClick事件处理函数复用setIndex函数即可实现向前/向后翻逻辑 - 实现点击
prev/next按钮显示前一张或后一张图片
源码地址:
