前台常见功能解决方案:下载+全屏+引导
目录
01: 文件下载解决方案
02: 通用组件:方法触发的 message 构建分析
03: 通用组件:构建 message 组件基本能力
04: 通用组件:方法触发 message 展示
05: 模块全屏解决方案
06: 构建 floating 基础布局
07: 样式修正:处理难看的 scrollBar
08: 功能引导解决方案
09: 解决功能引导图标不显示的问题
10: 总结
01: 文件下载解决方案
想要实现下载图片功能,需要使用到专门的下载包。
目前常用的支持下载功能的包有两个:
1. 小文件下载:file-saver
2. 大文件下载:streamsaver
咱们的图片下载属于小文件的下载,所以我们直接使用 file-saver。
1. 安装 file-saver
npm i --save file-saver@2.0.5
2. 在 src/views/main/components/list/item.vue 中,增加下载功能:
<script setup>
import { saveAs } from 'file-saver'/*** 下载按钮点击事件*/
const onDownload = () => {// 提示消息message('success', '图片开始下载')// 延迟一段时间执行,可以得到更好的体验setTimeout(() => {/*** 接收两个参数:* 1. 下载的图片链接* 2. 下载的文件名称*/saveAs(props.data.photoDownLink,`${props.data.title} - 作者:${props.data.author}`)}, 100)
}
02: 通用组件:方法触发的 message 构建分析
之前的时候,我们构建过一个 confirm 的通用组件,该组件我们可以直接通过 方法进行调用展示。
对于接下来打算构建的 message 组件,我们依然希望可以通过方法的调用直接展示对应的组件。
根据我们之前的经验,可以知道:
1. 首先我们需要先构建出一个对应的 message.vue
2. 然后构建出对应的 message.js 模块
3. 在模块中,通过:
1. h 函数构建 vnode
2. render 函数,进行渲染
依次进行处理。以上方式,就是咱们 message 的构建过程。
03: 通用组件:构建 message 组件基本能力
- src/libs
- - message
- - - index.vue
- - - index.js
<template><transition name="down" @after-leave="destroy"><divv-show="isVisable"class="min-w-[420px] fixed top-[20px] left-[50%] translate-x-[-50%] z-50 flex items-center px-3 py-1.5 rounded-sm border cursor-pointer":class="styles[type].containerClass"><m-svg-icon:name="styles[type].icon":fillClass="styles[type].fillClass"class="h-1.5 w-1.5 mr-1.5"></m-svg-icon><span class="text-sm" :class="styles[type].textClass">{{ content }}</span></div></transition>
</template><script>
import mSvgIcon from '../svg-icon/index.vue'/*** 消息类型可选项*/
const typeEnum = ['success', 'warn', 'error']
</script><script setup>
import { ref, onMounted } from 'vue'
const props = defineProps({/*** message 的消息类型*/type: {type: String,required: true,validator(val) {const result = typeEnum.includes(val)if (!result) {throw new Error(`你的 type 必须是 ${typeEnum.join('、')} 中的一个`)}return result}},/*** 描述文本*/content: {type: String,required: true},/*** 展示时长*/duration: {type: Number},/*** 关闭时的回调*/destroy: {type: Function}
})// 样式表数据
const styles = {// 警告warn: {icon: 'warn',fillClass: 'fill-warn-300',textClass: 'text-warn-300',containerClass:'bg-warn-100 border-warn-200 hover:shadow-lg hover:shadow-warn-100'},// 错误error: {icon: 'error',fillClass: 'fill-error-300',textClass: 'text-error-300',containerClass:'bg-error-100 border-error-200 hover:shadow-lg hover:shadow-error-100'},// 成功success: {icon: 'success',fillClass: 'fill-success-300',textClass: 'text-success-300',containerClass:'bg-success-100 border-success-200 hover:shadow-lg hover:shadow-success-100'}
}// 控制显示处理
const isVisable = ref(false)
// 关闭前 动画执行时间
const animDuration = '0.5s'
/*** 保证动画展示,需要在 mounted 之后进行展示*/
onMounted(() => {isVisable.value = true/*** 延迟时间关闭*/setTimeout(() => {isVisable.value = falsesetTimeout(() => {if (props.destory) {props.destory()}}, parseInt(duration.replace('0.', '').replace('s', '') * 100))}, props.duration)
})
</script><style lang="scss" scoped>
.down-enter-active,
.down-leave-active {transition: all v-bind(animDuration);
}.down-enter-from,
.down-leave-to {opacity: 0;transform: translate3d(-50%, -100px, 0);
}
</style>
04: 通用组件:方法触发 message 展示
// src/libs/message/index.jsimport { h, render } from 'vue'
import messageComponent from './index.vue'export const message = (type, content, duration = 3000) => {/*** 动画结束时的回调*/const onDestroy = () => {// 3. message 销毁render(null, document.body)}// 1. 返回 vnodeconst vnode = h(messageComponent, {type,content,duration,destroy: onDestroy})// 2. renderrender(vnode, document.body)
}
05: 模块全屏解决方案
让页面中的指定区域进行全屏展示也是非常常见的一个功能。想要让页面的指定区域进行全屏展示,我们通常可以使用 全屏API,该 API 中提供了两个方法:
1. Element.requestFullscreen(): 让指定元素进行全屏。
2. Document.exitFullscreen(): 退出全屏。
但是这个 API 比较原始,使用起来没有那么方便,所以我们可以使用一个 vueuse 中更加简便的 API:useFullScreen。
使用 useFullScreen 生成 img 图片的全屏方法:
<script setup>import { useFullscreen } from '@vueuse/core'const imgTarget = ref(null)/*** 生成全屏方法*/const { enter: onImgFullScreen } = useFullscreen(imgTarget)
</script>
<template><m-button @click="onImgFullScreen" />
</template>
06: 构建 floating 基础布局
- src/views/layout/components
- - floating
- - - index.vue
<template><div class="fixed bottom-10 right-2"><!-- 引导页 --><divclass="guide-start w-4 h-4 mb-1 bg-white dark:bg-zinc-900 border dark:border-0 border-zinc-200 rounded-full flex justify-center items-center cursor-pointer duration-200 group hover:shadow-lg"@click="onGuideClick"><m-svg-iconname="guide"class="w-2 h-2"fillClass="fill-zinc-900 dark:fill-zinc-200 group-hover:fill-main "></m-svg-icon></div><!-- 反馈 --><m-popover class="flex items-center guide-feedback" placement="top-left"><template #reference><divclass="w-4 h-4 bg-white dark:bg-zinc-900 border dark:border-0 border-zinc-200 rounded-full flex justify-center items-center cursor-pointer duration-200 group hover:shadow-lg"><m-svg-iconname="feedback"class="w-2 h-2"fillClass="fill-zinc-900 dark:fill-zinc-200 group-hover:fill-main "></m-svg-icon></div></template><div class="w-[140px] overflow-hidden"><divclass="flex items-center p-1 cursor-pointer rounded hover:bg-zinc-100/60 dark:hover:bg-zinc-800"@click="onToFeedback"><m-svg-iconname="feedback"class="w-1.5 h-1.5 mr-1"fillClass="fill-zinc-900 dark:fill-zinc-300"></m-svg-icon><span class="text-zinc-800 dark:text-zinc-300 text-sm">立即吐槽</span></div></div></m-popover></div>
</template><script setup>
import Driver from 'driver.js'
import 'driver.js/dist/driver.min.css'
import steps from './steps'
import { onMounted } from 'vue'
import { FEEDBACK_URL } from '@/constants'/*** 引导页处理*/
let driver = null
onMounted(() => {driver = new Driver({// 禁止点击蒙版关闭allowClose: false,closeBtnText: '关闭',nextBtnText: '下一个',prevBtnText: '上一个'})
})/*** 开始引导*/
const onGuideClick = () => {driver.defineSteps(steps)driver.start()
}/*** 反馈处理*/
const onToFeedback = () => {window.open(FEEDBACK_URL, '_blank')
}
</script><style lang="scss" scoped>
.driver-fix-stacking {position: fixed;z-index: 100004 !important;
}
</style>
07: 样式修正:处理难看的 scrollBar
scrollBar 看着实在是有点难看,接下来就需要修正一下这个 scrollBar 的样式。
对于 tailwind 而言,默认没有提供 scrollBar 的样式类名。想要处理 scrollBar 的样式,需要安装单独的插件:tailwind-scrollbar。
1. 安装插件
npm install --save-dev tailwind-scrollbar@1.3.1
2. 在 tailwind.config.js 中注册该插件
plugins: [require('tailwind-scrollbar')]
3. 在 tailwind.config.js 中,让 scrollBar 支持 dark 模式
module.exports = {……theme: {extend: {……variants: {scrollbar: ['dark']}}}……
}
4. 在 src/views/min/index.vue 中使用
scrollbar-thin
scrollbar-thumb-transparent
xl:scrollbar-thumb-zinc-200
xl:dark:scrollbar-thumb-zinc-900
scrollbar-track-transparent
scrollbar-thumb-transparent // 滚道样式
5. 在 src/libs/search/index.vue 中使用
scrollbar-thin
scrollbar-thumb-zinc-200
dark:scrollbar-thumb-zinc-900
scrollbar-track-transparent
6. 补充 边弧度 样式
/* src/styles/index.scss */::-webkit-scrollbar-thumb {border-radius: 10px;
}
08: 功能引导解决方案
想要完成功能引导的实现,我们需要借助一个第三方包:driver.js
下面我们就使用这个第三方包来实现咱们的功能引导:
1. 安装 driver.js
npm install --save driver.js@0.9.8
2. 在 src/views/layout/components/floating/index.vue 中导入对应模块
import Driver from 'driver.js'
import 'driver.js/dist/driver.min.css'
3. 初始化 Driver
/*** 引导页处理*/
let driver = null
onMounted(() => {driver = new Driver({// 禁止点击蒙版关闭allowClose: false,closeBtnText: '关闭',nextBtnText: '下一个',prevBtnText: '上一个'})
})
4. 构建引导步骤
// src/views/layout/components/steps.jsexport default [{// 在哪个元素中高亮element: '.guide-home',// 配置对象popover: {// 标题title: 'logo',// 描述description: '点击可返回首页'}},{element: '.guide-search',popover: {title: '搜索',description: '搜索您期望的图片'}},{element: '.guide-theme',popover: {title: '风格',description: '选择一个您喜欢的风格',// 弹出的位置position: 'left'}},{element: '.guide-my',popover: {title: '账户',description: '这里标记了您的账户信息',position: 'left'}},{element: '.guide-start',popover: {title: '引导',description: '这里可再次查看引导信息',position: 'left'}},{element: '.guide-feedback',popover: {title: '反馈',description: '您的任何不满都可以在这里告诉我们',position: 'left'}}
]
使用:
<script setup>
import steps from './steps'/*** 开始引导*/
const onGuideClick = () => {driver.defineSteps(steps)driver.start()
}</script>
09: 解决功能引导图标不显示的问题
/* src/styles/index.scss */.driver-fix-stacking {position: relative;
}.driver-navigation-btns {line-height: 0;
}
// src/views/layout/components/floating/index.vue<style lang="scss" scoped>
.driver-fix-stacking {position: fixed;z-index: 100004 !important;
}
</style>
10: 总结
本篇文章中,我们处理了4个核心功能:
1. 文件下载
2. 通用组件:message 构建
3. 全屏处理
4. 引导处理