当前位置: 首页 > news >正文

前台常见功能解决方案:下载+全屏+引导

目录

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. 引导处理 

相关文章:

  • kali基本扫描工具(自带)
  • XSS 攻击
  • Codeforces Round 927 (Div. 3) D. Card Game 题解 贪心
  • 基于Hadoop技术的智慧图书馆海量数据储存系统研究
  • Debezium+Kafka:Oracle 11g 数据实时同步至 DolphinDB 解决方案
  • 【C++课程学习】:命名空间的理解(图文详解)
  • i2c总线介绍
  • 文心智能体大赛:百度文心智能体平台初体验
  • 基于webpack+Vue3+JavaScript+antd+less+axios技术栈实现所有组件全局自动化注册
  • [JDK工具-5] jinfo jvm配置信息工具
  • 自从有了可观测性,传统运维如何进行提升?
  • Flutter 中的 ClipRect 小部件:全面指南
  • springBoot项目中的static和templates文件夹
  • SQL约束
  • docker命令详解大全
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • co.js - 让异步代码同步化
  • download使用浅析
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • js正则,这点儿就够用了
  • Laravel Mix运行时关于es2015报错解决方案
  • leetcode讲解--894. All Possible Full Binary Trees
  • mysql innodb 索引使用指南
  • mysql外键的使用
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • SQLServer之索引简介
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • 闭包--闭包之tab栏切换(四)
  • 从输入URL到页面加载发生了什么
  • 仿天猫超市收藏抛物线动画工具库
  • 聊聊flink的TableFactory
  • 每天一个设计模式之命令模式
  • 前嗅ForeSpider采集配置界面介绍
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 试着探索高并发下的系统架构面貌
  • 通过git安装npm私有模块
  • 协程
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • 一个完整Java Web项目背后的密码
  • 用quicker-worker.js轻松跑一个大数据遍历
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​批处理文件中的errorlevel用法
  • # C++之functional库用法整理
  • #Linux(make工具和makefile文件以及makefile语法)
  • (4.10~4.16)
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (ZT)出版业改革:该死的死,该生的生
  • (含笔试题)深度解析数据在内存中的存储
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (一)Neo4j下载安装以及初次使用
  • (总结)Linux下的暴力密码在线破解工具Hydra详解