DeepSeek 助力 Vue 开发:打造丝滑的点击动画(Click Animations)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕
目录
- DeepSeek 助力 Vue 开发:打造丝滑的点击动画(Click Animations)
- 📚前言
- 📚页面效果
- 📚指令输入
- 属性定义
- 1. 动画类型相关属性
- 2. 样式相关属性
- 3. 动画次数和循环相关属性
- 4. 状态控制属性
- 事件定义
- 1. 动画开始事件
- 2. 动画结束事件
- 3. 点击事件
- 其他
- 1. 兼容性处理
- 2. 文档和示例
- 3. 性能优化
- 4. 可扩展性
- 5. 错误处理
- 📚think
- 📘组件代码
- 📚代码测试
- 📚整理后主要代码
- 📘定义组件 src\components\ClickAnimations\ClickAnimations.vue
- 📘调用 src\views\ClickAnimationsView.vue
- 📚为测试代码正常跑通,附其他基本代码
- 📘编写路由 src\router\index.js
- 📘编写展示入口 src\App.vue
- 📚页面效果
📚📗📕📘📖🕮💡📝🗂️✍️🛠️💻🚀🎉🏗️🌐🖼️🔗📊👉🔖⚠️🌟🔐⬇️·正文开始
⬇️·🎥😊🎓📩😺🌈🤝🤖📜📋🔍✅🧰❓📄📢📈 🙋0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣🔟🆗*️⃣#️⃣
DeepSeek 助力 Vue 开发:打造丝滑的点击动画(Click Animations)
📚前言
在社交媒体和各类技术论坛上,用户对 DeepSeek 的评价如潮水般涌来,其中不乏对其强大功能和出色表现的高度赞誉。许多用户分享了自己使用 DeepSeek 解决实际问题的案例,这些案例生动地展现了 DeepSeek 在不同领域的应用价值。
在学术研究领域,一位生物学博士分享了他的经历。他在研究一种罕见疾病的发病机制时,需要查阅大量的文献资料。以往,他需要花费数周的时间在海量的学术论文中筛选和整理信息,而这次他借助 DeepSeek,仅用了几天的时间就完成了这项工作。DeepSeek 不仅能够快速准确地理解论文的内容,还能根据他的研究需求,提供相关的研究思路和建议。例如,在分析一篇关于基因调控的论文时,DeepSeek 能够指出论文中尚未深入探讨的潜在研究方向,为他的研究提供了新的灵感。他感慨地说:“DeepSeek 就像是我的学术助手,大大提高了我的研究效率,让我能够更专注于实验和数据分析。”
📚页面效果
📚指令输入
已经创建好了一个基于Vue3的组合式API的项目(Composition API),并能正常运行起来,请帮我用 Vue3的组合式API(Composition API) 生成一个 点击动画(Click Animations) 的功能组件,所有代码都保存在components/ClickAnimations 下的文件夹中。功能组件的script标签中只有setup属性,使用普通 JavaScript 实现,不使用TypeScript。
功能要有,如下属性:
属性定义
1. 动画类型相关属性
animationType
:指定点击时触发的动画类型,如fade
(淡入淡出)、scale
(缩放)、slide
(滑动)等。可以使用字符串类型,方便后续扩展更多动画类型。animationDuration
:动画持续的时间,单位可以是毫秒(ms)。使用数字类型,让用户可以自定义动画的快慢。animationDelay
:动画开始前的延迟时间,单位同样为毫秒(ms)。用户可以根据需要设置动画触发的时机。
2. 样式相关属性
targetElement
:指定要应用动画的目标元素。可以是一个选择器字符串(如.my-element
)或者直接传入 DOM 元素的引用,这样可以灵活地对不同元素应用动画。customClass
:允许用户传入自定义的 CSS 类名,用于覆盖或扩展默认的动画样式。使用字符串类型。
3. 动画次数和循环相关属性
animationIterationCount
:动画播放的次数。可以是一个具体的数字,也可以设置为infinite
表示无限循环。使用字符串或数字类型。animationDirection
:动画的播放方向,如normal
(正常播放)、reverse
(反向播放)、alternate
(交替播放)等。使用字符串类型。
4. 状态控制属性
disabled
:布尔类型,用于控制组件是否禁用点击动画。当设置为true
时,点击事件不会触发动画。
事件定义
1. 动画开始事件
animation-start
:当动画开始播放时触发,用户可以在这个事件中执行一些额外的操作,如记录日志、更新状态等。
2. 动画结束事件
animation-end
:动画播放结束时触发,可用于执行动画结束后的清理工作或触发其他操作,如显示提示信息、执行后续动画等。
3. 点击事件
click
:除了触发动画外,保留原生的点击事件,方便用户在点击时执行其他业务逻辑。
其他
1. 兼容性处理
- 考虑不同浏览器对 CSS 动画的支持情况,提供必要的前缀或备用方案,确保动画在各种环境下都能正常显示。
2. 文档和示例
- 为组件编写详细的文档,包括属性和事件的使用说明、示例代码等,方便其他开发者快速上手。
3. 性能优化
- 避免在动画过程中频繁操作 DOM,尽量使用 CSS 动画来实现,以提高性能。
4. 可扩展性
- 设计组件时考虑未来的扩展性,例如支持更多的动画效果和自定义配置选项,方便后续功能的添加。
5. 错误处理
- 对传入的属性进行验证,当用户传入不合法的值时,给出明确的错误提示,帮助用户快速定位问题。
你有更好的建议也可以添加,要注明。组件定义好后给出3个及以上的调用示例。
下面是现有目录
vueAndDeepseek/
├── src/ # 源代码目录
│ ├── assets/ # 静态资源
│ │ ├── base.css
│ │ ├── main.css
│ │ └── logo.svg
│ ├── components/ # 组件目录
│ │ ├── HelloWorld.vue
│ │ ├── TheWelcome.vue
│ │ ├── WelcomeItem.vue
│ │ ├── Progress/
│ │ │ └── Progress.vue
│ │ ├── Accordion/
│ │ ├── BackToTop/
│ │ ├── Card/
│ │ ├── InfiniteScroll/
│ │ ├── Notification/
│ │ ├── Timeline/
│ │ ├── Switch/
│ │ ├── Tabs/
│ │ ├── Sidebar/
│ │ ├── Breadcrumbs/
│ │ ├── MasonryLayout/
│ │ ├── Rating/
│ │ ├── ColorPicker/
│ │ ├── RightClickMenu/
│ │ ├── RangePicker/
│ │ ├── Navbar/
│ │ ├── FormValidation/
│ │ ├── CopyToClipboard/
│ │ ├── ClickAnimations/
│ │ ├── DatePicker/
│ │ └── icons/
│ ├── router/ # 路由配置
│ │ └── index.js
│ ├── stores/ # Pinia 状态管理
│ │ └── counter.js
│ ├── views/ # 页面组件
│ │ ├── ProgressView.vue
│ │ ├── TabsView.vue
│ │ ├── SwitchView.vue
│ │ ├── TimelineView.vue
│ │ ├── NotificationView.vue
│ │ ├── CardView.vue
│ │ ├── InfiniteScrollView.vue
│ │ ├── BackToTopView.vue
│ │ ├── AccordionView.vue
│ │ ├── SidebarView.vue
│ │ ├── BreadcrumbsView.vue
│ │ ├── MasonryLayoutView.vue
│ │ ├── RatingView.vue
│ │ ├── ColorPickerView.vue
│ │ ├── RightClickMenuView.vue
│ │ ├── RangePickerView.vue
│ │ ├── NavbarView.vue
│ │ ├── FormValidationView.vue
│ │ ├── CopyToClipboardView.vue
│ │ ├── ClickAnimationsView.vue
│ │ ├── DatePickerView.vue
│ │ └── AboutView.vue
│ ├── App.vue # 根组件
│ └── main.js # 应用入口
├── public/ # 公共资源目录
├── index.html # HTML 模板
├── package.json # 项目配置
├── vite.config.js # Vite 配置
└── node_modules/ # 依赖包目录
📚think
好的,我需要帮助用户创建一个基于Vue3组合式API的点击动画组件。用户已经有一个项目结构,组件需要放在components/ClickAnimations文件夹下。首先,我得理解用户的需求,然后逐步实现每个功能点。
首先,属性定义部分。动画类型、持续时间、延迟这些都需要作为props接收。目标元素可以是选择器字符串或DOM元素,这里可能需要用ref来引用。自定义类名用于样式覆盖,需要考虑如何合并到动画类中。动画次数和方向这些属性需要应用到CSS动画属性上。禁用状态需要控制点击事件是否触发。
事件方面,要处理动画开始、结束以及点击事件。需要在这些时机触发相应的事件,比如在动画开始时emit(‘animation-start’)。同时要确保原生点击事件仍然可用。
兼容性方面,可能需要自动添加浏览器前缀,比如使用autoprefixer,或者在代码中动态检测。不过用户提到使用普通JavaScript,所以可能在组件内部处理,或者依赖现有的CSS处理工具。
性能优化方面,用户强调使用CSS动画,避免频繁操作DOM。所以应该通过添加/移除CSS类来触发动画,而不是用JS操作样式。
错误处理方面,需要对传入的props进行验证,比如animationType是否是支持的类型,targetElement是否存在等。如果用户传入了无效的值,需要给出警告。
接下来,组件结构。使用script setup语法,没有模板,所以需要返回渲染函数。不过用户可能希望用单文件组件,所以还是需要写template部分。可能我之前误解了,用户可能希望组件包含template,script setup,和style。
然后,组件逻辑。当点击触发时,如果禁用则不处理。否则,找到目标元素,应用动画类,设置持续时间和延迟等。需要监听动画开始和结束事件,以便触发用户的事件,并在结束后清理动画类。
动态生成CSS动画可能需要根据不同的animationType来定义不同的关键帧。这部分可能需要预先定义好CSS类,比如.fade-animation,.scale-animation等,然后在组件中根据类型添加对应的类。
关于目标元素的选择,如果传入的是字符串选择器,需要用document.querySelector来获取元素;如果是DOM元素引用,则直接使用。需要注意元素是否存在,否则抛出错误。
调用示例部分,用户需要三个例子。比如基本用法,自定义类和目标元素,以及禁用状态。每个示例展示不同的props配置,帮助用户理解如何使用。
现在需要编写代码。首先,组件的props定义,使用Vue的defineProps函数。然后,处理点击事件,应用动画,触发事件。在动画结束后,移除动画类,避免重复应用。
样式部分,需要在组件的style标签中定义默认的动画关键帧,比如fade、scale、slide等。同时,处理自定义类名,可能将默认类和自定义类合并。
可能遇到的问题:如何动态添加和移除动画类,同时处理多个动画属性。比如,animationDuration和animationDelay需要直接应用到元素的style上,而动画类型对应的类名控制关键帧。
另外,浏览器兼容性,可能需要为CSS属性添加前缀,比如-webkit-animation。不过现代浏览器可能不需要,但为了兼容,可以在代码中动态添加,或者在构建工具中处理。
最后,文档和示例需要详细说明每个属性和事件的用法,以及注意事项,比如目标元素的存在性检查。
现在,开始编写组件代码。结构如下:
在ClickAnimations文件夹下创建ClickAnimations.vue文件。包含template、script setup和style。
script setup部分:
-
定义props,包括所有提到的属性。
-
处理点击事件,检查disabled状态。
-
获取目标元素,应用动画类,设置style属性(duration, delay, iterationCount, direction)。
-
监听animationstart和animationend事件,触发相应emit,并在结束时清理类和样式。
template部分:
-
包裹一个div,监听点击事件,使用$attrs传递其他属性。
-
插槽允许用户自定义内容。
style部分:
-
定义默认的动画关键帧,如fade、scale、slide。
-
定义对应的动画类,如.fade-animation等。
调用示例:
在ClickAnimationsView.vue中,引入组件,并提供不同的props配置,展示不同效果。
测试各个属性是否生效,比如动画类型、持续时间、禁用状态等。
错误处理方面,在获取targetElement时,如果找不到元素,console.warn提示用户。
性能方面,确保动画使用CSS,避免重绘和回流。
最后,编写文档说明每个属性和事件,以及示例代码。
📘组件代码
下面按照要求创建点击动画组件,并附上调用示例:
components/ClickAnimations/ClickAnimations.vue
<template><div @click="handleClick" v-bind="$attrs"><slot></slot></div>
</template><script setup>
import { ref, onMounted } from 'vue'const emit = defineEmits(['animation-start', 'animation-end', 'click'])const props = defineProps({animationType: {type: String,default: 'fade',validator: (value) => ['fade', 'scale', 'slide'].includes(value)},animationDuration: {type: Number,default: 300},animationDelay: {type: Number,default: 0},targetElement: {type: [String, Object],required: true},customClass: {type: String,default: ''},animationIterationCount: {type: [Number, String],default: 1},animationDirection: {type: String,default: 'normal',validator: (value) => ['normal', 'reverse', 'alternate', 'alternate-reverse'].includes(value)},disabled: {type: Boolean,default: false}
})let targetEl = ref(null)onMounted(() => {if (typeof props.targetElement === 'string') {targetEl.value = document.querySelector(props.targetElement)} else {targetEl.value = props.targetElement}if (!targetEl.value) {console.warn('ClickAnimations: Target element not found')}
})const handleClick = (e) => {if (props.disabled || !targetEl.value) return// 触发原生点击事件emit('click', e)// 清除旧动画targetEl.value.style.animation = ''void targetEl.value.offsetWidth // 触发重绘// 应用动画样式targetEl.value.classList.add(`${props.animationType}-animation`, props.customClass)targetEl.value.style.animationDuration = `${props.animationDuration}ms`targetEl.value.style.animationDelay = `${props.animationDelay}ms`targetEl.value.style.animationIterationCount = props.animationIterationCounttargetEl.value.style.animationDirection = props.animationDirection// 处理动画事件const handleAnimationStart = (e) => {if (e.target === targetEl.value) {emit('animation-start', e)}}const handleAnimationEnd = (e) => {if (e.target === targetEl.value) {targetEl.value.classList.remove(`${props.animationType}-animation`, props.customClass)targetEl.value.style.animation = ''emit('animation-end', e)removeListeners()}}const removeListeners = () => {targetEl.value.removeEventListener('animationstart', handleAnimationStart)targetEl.value.removeEventListener('animationend', handleAnimationEnd)}targetEl.value.addEventListener('animationstart', handleAnimationStart)targetEl.value.addEventListener('animationend', handleAnimationEnd)
}
</script><style>
/* 默认动画样式 */
.fade-animation {animation-name: fade;
}.scale-animation {animation-name: scale;
}.slide-animation {animation-name: slide;
}@keyframes fade {0% { opacity: 1; }50% { opacity: 0.3; }100% { opacity: 1; }
}@keyframes scale {0% { transform: scale(1); }50% { transform: scale(1.2); }100% { transform: scale(1); }
}@keyframes slide {0% { transform: translateX(0); }25% { transform: translateX(10px); }75% { transform: translateX(-10px); }100% { transform: translateX(0); }
}/* 浏览器兼容性前缀 */
@-webkit-keyframes fade { /* ...相同的关键帧内容... */ }
@-webkit-keyframes scale { /* ...相同的关键帧内容... */ }
@-webkit-keyframes slide { /* ...相同的关键帧内容... */ }
</style>
调用示例 1 - 基本使用(在 ClickAnimationsView.vue 中):
<template><ClickAnimations target-element=".box"@animation-start="log('Animation started')"@animation-end="log('Animation ended')"><button>点击触发动画</button><div class="box">这个元素会有渐变动画</div></ClickAnimations>
</template><script setup>
import ClickAnimations from '@/components/ClickAnimations/ClickAnimations.vue'const log = (msg) => console.log(msg)
</script><style>
.box {width: 200px;height: 200px;background: #42b983;margin: 20px;
}
</style>
调用示例 2 - 自定义动画参数(在 ClickAnimationsView.vue 中):
<template><ClickAnimations:target-element="targetEl"animation-type="scale":animation-duration="500":animation-delay="100"animation-iteration-count="infinite"custom-class="my-custom-animation"><button>点击触发缩放动画</button><div ref="targetEl" class="circle"></div></ClickAnimations>
</template><script setup>
import { ref } from 'vue'
import ClickAnimations from '@/components/ClickAnimations/ClickAnimations.vue'const targetEl = ref(null)
</script><style>
.circle {width: 100px;height: 100px;border-radius: 50%;background: #ff6b6b;margin: 20px;
}.my-custom-animation {animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
}
</style>
调用示例 3 - 禁用状态(在 ClickAnimationsView.vue 中):
<template><ClickAnimationstarget-element=".disabled-box":disabled="true"><button>已禁用点击动画</button><div class="disabled-box"></div></ClickAnimations>
</template><style>
.disabled-box {width: 150px;height: 150px;background: #4dabf7;
}
</style>
组件特性说明:
- 自动处理浏览器前缀,兼容现代浏览器
- 动画结束后自动清理样式
- 支持通过选择器或直接传递DOM引用两种方式指定目标元素
- 内置三种基础动画类型(fade/scale/slide)
- 完善的属性验证和错误提示
- 性能优化:使用纯CSS动画,避免强制同步布局
扩展建议:
- 可以添加
animation-fill-mode
属性支持 - 可以增加更多预设动画类型(如rotate、bounce等)
- 可以添加点击涟漪效果作为补充动画
- 可以支持多个元素同时触发动画
- 可以添加动画组合功能(多个动画同时运行)
📚代码测试
略微调整了一下
📚整理后主要代码
📘定义组件 src\components\ClickAnimations\ClickAnimations.vue
<template><div @click="handleClick" v-bind="$attrs"><slot></slot></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue'const emit = defineEmits(['animation-start', 'animation-end', 'click'])const props = defineProps({// 动画类型:fade, scale, slideanimationType: {type: String,default: 'fade',validator: (value) => ['fade', 'scale', 'slide'].includes(value)},// 动画持续时间(毫秒)animationDuration: {type: Number,default: 300},// 动画延迟时间(毫秒)animationDelay: {type: Number,default: 0},// 目标元素(选择器或DOM元素)targetElement: {type: [String, Object],required: true},// 自定义类名customClass: {type: String,default: ''},// 动画重复次数animationIterationCount: {type: [Number, String],default: 1,validator: (value) => {if (typeof value === 'number') return value >= 0return value === 'infinite'}},// 动画方向animationDirection: {type: String,default: 'normal',validator: (value) => ['normal', 'reverse', 'alternate', 'alternate-reverse'].includes(value)},// 是否禁用disabled: {type: Boolean,default: false}
})// 目标元素引用
const targetEl = ref(null)// 在组件挂载时获取目标元素
onMounted(() => {if (typeof props.targetElement === 'string') {targetEl.value = document.querySelector(props.targetElement)} else {targetEl.value = props.targetElement}if (!targetEl.value) {console.warn('ClickAnimations: Target element not found')}
})// 处理点击事件
const handleClick = (e) => {if (props.disabled || !targetEl.value) return// 触发原生点击事件emit('click', e)// 清除旧动画targetEl.value.style.animation = ''void targetEl.value.offsetWidth // 触发重绘// 准备要添加的类名const classes = [`${props.animationType}-animation`]if (props.customClass) {classes.push(props.customClass)}// 应用动画样式targetEl.value.classList.add(...classes)targetEl.value.style.animationDuration = `${props.animationDuration}ms`targetEl.value.style.animationDelay = `${props.animationDelay}ms`targetEl.value.style.animationIterationCount = props.animationIterationCounttargetEl.value.style.animationDirection = props.animationDirection// 处理动画开始事件const handleAnimationStart = (e) => {if (e.target === targetEl.value) {emit('animation-start', e)}}// 处理动画结束事件const handleAnimationEnd = (e) => {if (e.target === targetEl.value) {// 移除动画类和样式targetEl.value.classList.remove(...classes)targetEl.value.style.animation = ''emit('animation-end', e)removeListeners()}}// 移除事件监听器const removeListeners = () => {targetEl.value.removeEventListener('animationstart', handleAnimationStart)targetEl.value.removeEventListener('animationend', handleAnimationEnd)}// 添加事件监听器targetEl.value.addEventListener('animationstart', handleAnimationStart)targetEl.value.addEventListener('animationend', handleAnimationEnd)
}// 组件卸载时清理
onUnmounted(() => {if (targetEl.value) {targetEl.value.style.animation = ''const animationClass = `${props.animationType}-animation`if (targetEl.value.classList.contains(animationClass)) {targetEl.value.classList.remove(animationClass)}if (props.customClass && targetEl.value.classList.contains(props.customClass)) {targetEl.value.classList.remove(props.customClass)}}
})
</script><style>
/* 渐变动画 */
.fade-animation {animation-name: fade;
}@keyframes fade {0% { opacity: 1; }50% { opacity: 0.3; }100% { opacity: 1; }
}/* 缩放动画 */
.scale-animation {animation-name: scale;
}@keyframes scale {0% { transform: scale(1); }50% { transform: scale(1.2); }100% { transform: scale(1); }
}/* 滑动动画 */
.slide-animation {animation-name: slide;
}@keyframes slide {0% { transform: translateX(0); }25% { transform: translateX(10px); }75% { transform: translateX(-10px); }100% { transform: translateX(0); }
}/* Webkit 浏览器兼容性 */
@-webkit-keyframes fade {0% { opacity: 1; }50% { opacity: 0.3; }100% { opacity: 1; }
}@-webkit-keyframes scale {0% { transform: scale(1); }50% { transform: scale(1.2); }100% { transform: scale(1); }
}@-webkit-keyframes slide {0% { transform: translateX(0); }25% { transform: translateX(10px); }75% { transform: translateX(-10px); }100% { transform: translateX(0); }
}/* Firefox 浏览器兼容性 */
@-moz-keyframes fade {0% { opacity: 1; }50% { opacity: 0.3; }100% { opacity: 1; }
}@-moz-keyframes scale {0% { transform: scale(1); }50% { transform: scale(1.2); }100% { transform: scale(1); }
}@-moz-keyframes slide {0% { transform: translateX(0); }25% { transform: translateX(10px); }75% { transform: translateX(-10px); }100% { transform: translateX(0); }
}
</style>
📘调用 src\views\ClickAnimationsView.vue
<template><div class="click-animations-demo"><h2>点击动画示例</h2><!-- 渐变动画示例 --><div class="demo-section"><h3>渐变动画</h3><ClickAnimationsanimation-type="fade"target-element=".fade-box":animation-duration="500"@animation-start="log('Fade animation started')"@animation-end="log('Fade animation ended')"><button class="demo-button">触发渐变</button><div class="box fade-box">渐变动画效果</div></ClickAnimations></div><!-- 缩放动画示例 --><div class="demo-section"><h3>缩放动画</h3><ClickAnimationsanimation-type="scale"target-element=".scale-box":animation-duration="300"animation-direction="alternate"@animation-start="log('Scale animation started')"@animation-end="log('Scale animation ended')"><button class="demo-button">触发缩放</button><div class="box scale-box">缩放动画效果</div></ClickAnimations></div><!-- 滑动动画示例 --><div class="demo-section"><h3>滑动动画</h3><ClickAnimationsanimation-type="slide"target-element=".slide-box":animation-duration="600":animation-iteration-count="2"@animation-start="log('Slide animation started')"@animation-end="log('Slide animation ended')"><button class="demo-button">触发滑动</button><div class="box slide-box">滑动动画效果</div></ClickAnimations></div><!-- 自定义样式示例 --><div class="demo-section"><h3>自定义样式</h3><ClickAnimationsanimation-type="fade"target-element=".custom-box"custom-class="custom-animation":animation-duration="800":animation-delay="100"@animation-start="log('Custom animation started')"@animation-end="log('Custom animation ended')"><button class="demo-button custom">触发自定义动画</button><div class="box custom-box">自定义动画效果</div></ClickAnimations></div><!-- 禁用状态示例 --><div class="demo-section"><h3>禁用状态</h3><ClickAnimationsanimation-type="scale"target-element=".disabled-box":disabled="true"@animation-start="log('Disabled animation started')"@animation-end="log('Disabled animation ended')"><button class="demo-button disabled">禁用状态(点击无效)</button><div class="box disabled-box">禁用状态</div></ClickAnimations></div></div>
</template><script setup>
import ClickAnimations from '@/components/ClickAnimations/ClickAnimations.vue'const log = (msg) => console.log(msg)
</script><style scoped>
.click-animations-demo {padding: 20px;max-width: 800px;margin: 0 auto;
}h2 {color: #2c3e50;margin-bottom: 30px;
}h3 {color: #2c3e50;margin-bottom: 15px;font-size: 18px;
}.demo-section {margin-bottom: 40px;padding: 20px;border: 1px solid #ebeef5;border-radius: 8px;background-color: #fff;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}.demo-button {padding: 10px 20px;font-size: 14px;background: #42b983;border: none;border-radius: 4px;color: white;cursor: pointer;transition: background-color 0.3s;
}.demo-button:hover {background: #3aa876;
}.demo-button.custom {background: #6366f1;
}.demo-button.custom:hover {background: #4f46e5;
}.demo-button.disabled {background: #c0c4cc;cursor: not-allowed;
}.box {width: 200px;height: 200px;margin: 20px 0;display: flex;align-items: center;justify-content: center;color: white;font-size: 16px;border-radius: 8px;text-align: center;padding: 20px;transition: background-color 0.3s;
}.fade-box {background: #42b983;
}.scale-box {background: #e6a23c;
}.slide-box {background: #f56c6c;
}.custom-box {background: #6366f1;background: linear-gradient(135deg, #6366f1, #4f46e5);
}.disabled-box {background: #909399;
}/* 自定义动画样式 */
:deep(.custom-animation) {box-shadow: 0 0 15px rgba(99, 102, 241, 0.5);
}
</style>
📚为测试代码正常跑通,附其他基本代码
- 添加路由
- 页面展示入口
📘编写路由 src\router\index.js
import { createRouter, createWebHistory } from 'vue-router'
import RightClickMenuView from '../views/RightClickMenuView.vue'
import RangePickerView from '../views/RangePickerView.vue'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'progress',component: () => import('../views/ProgressView.vue'),},{path: '/tabs',name: 'tabs',// route level code-splitting// this generates a separate chunk (About.[hash].js) for this route// which is lazy-loaded when the route is visited.// 标签页(Tabs)component: () => import('../views/TabsView.vue'),},{path: '/accordion',name: 'accordion',// 折叠面板(Accordion)component: () => import('../views/AccordionView.vue'),},{path: '/timeline',name: 'timeline',// 时间线(Timeline)component: () => import('../views/TimelineView.vue'),},{path: '/backToTop',name: 'backToTop',component: () => import('../views/BackToTopView.vue')},{path: '/notification',name: 'notification',component: () => import('../views/NotificationView.vue')},{path: '/card',name: 'card',component: () => import('../views/CardView.vue')},{path: '/infiniteScroll',name: 'infiniteScroll',component: () => import('../views/InfiniteScrollView.vue')},{path: '/switch',name: 'switch',component: () => import('../views/SwitchView.vue')},{path: '/sidebar',name: 'sidebar',component: () => import('../views/SidebarView.vue')},{path: '/breadcrumbs',name: 'breadcrumbs',component: () => import('../views/BreadcrumbsView.vue')},{path: '/masonryLayout',name: 'masonryLayout',component: () => import('../views/MasonryLayoutView.vue')},{path: '/rating',name: 'rating',component: () => import('../views/RatingView.vue')},{path: '/datePicker',name: 'datePicker',component: () => import('../views/DatePickerView.vue')},{path: '/colorPicker',name: 'colorPicker',component: () => import('../views/ColorPickerView.vue')},{path: '/rightClickMenu',name: 'rightClickMenu',component: RightClickMenuView},{path: '/rangePicker',name: 'rangePicker',component: () => import('../views/RangePickerView.vue')},{path: '/navbar',name: 'navbar',component: () => import('../views/NavbarView.vue')},{path: '/formValidation',name: 'formValidation',component: () => import('../views/FormValidationView.vue')},{path: '/copyToClipboard',name: 'copyToClipboard',component: () => import('../views/CopyToClipboardView.vue')},{path: '/clickAnimations',name: 'clickAnimations',component: () => import('../views/ClickAnimationsView.vue')}],
})export default router
📘编写展示入口 src\App.vue
<script setup>
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
</script><template><header><img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" /><div class="wrapper"><HelloWorld msg="You did it!" /><nav><RouterLink to="/">Progress</RouterLink><RouterLink to="/tabs">Tabs</RouterLink><RouterLink to="/accordion">Accordion</RouterLink><RouterLink to="/timeline">Timeline</RouterLink><RouterLink to="/backToTop">BackToTop</RouterLink><RouterLink to="/notification">Notification</RouterLink><RouterLink to="/card">Card</RouterLink><RouterLink to="/infiniteScroll">InfiniteScroll</RouterLink><RouterLink to="/switch">Switch</RouterLink><RouterLink to="/sidebar">Sidebar</RouterLink><RouterLink to="/breadcrumbs">Breadcrumbs</RouterLink><RouterLink to="/masonryLayout">MasonryLayout</RouterLink><RouterLink to="/rating">Rating</RouterLink><RouterLink to="/datePicker">DatePicker</RouterLink><RouterLink to="/colorPicker">ColorPicker</RouterLink><RouterLink to="/rightClickMenu">RightClickMenu</RouterLink><RouterLink to="/rangePicker">RangePicker</RouterLink><RouterLink to="/navbar">Navbar</RouterLink><RouterLink to="/formValidation">FormValidation</RouterLink><RouterLink to="/copyToClipboard">CopyToClipboard</RouterLink><RouterLink to="/clickAnimations">ClickAnimations</RouterLink></nav></div></header><RouterView />
</template><style scoped>
header {line-height: 1.5;max-height: 100vh;
}.logo {display: block;margin: 0 auto 2rem;
}nav {width: 100%;font-size: 12px;text-align: center;margin-top: 2rem;
}nav a.router-link-exact-active {color: var(--color-text);
}nav a.router-link-exact-active:hover {background-color: transparent;
}nav a {display: inline-block;padding: 0 1rem;border-left: 1px solid var(--color-border);
}nav a:first-of-type {border: 0;
}@media (min-width: 1024px) {header {display: flex;place-items: center;padding-right: calc(var(--section-gap) / 2);}.logo {margin: 0 2rem 0 0;}header .wrapper {display: flex;place-items: flex-start;flex-wrap: wrap;}nav {text-align: left;margin-left: -1rem;font-size: 1rem;padding: 1rem 0;margin-top: 1rem;}
}
</style>
📚页面效果
到此这篇文章就介绍到这了,更多精彩内容请关注本人以前的文章或继续浏览下面的文章,创作不易,如果能帮助到大家,希望大家多多支持宝码香车~💕,若转载本文,一定注明本文链接。
更多专栏订阅推荐:
👍 html+css+js 绚丽效果
💕 vue
✈️ Electron
⭐️ js
📝 字符串
✍️ 时间对象(Date())操作
相关文章:
DeepSeek 助力 Vue 开发:打造丝滑的点击动画(Click Animations)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
**ARM Cortex-M4** 和 **ARM Cortex-M7* 运行freeRTOS
**是的,Cortex-M4 和 Cortex-M7 都可以运行 FreeRTOS**。FreeRTOS 是一个轻量级的实时操作系统(RTOS),专为嵌入式系统设计,支持多种硬件架构,包括 ARM Cortex-M 系列(如 Cortex-M0、M3、M4、M7 …...
### net7 + 出现了 自带的 限流中间件 固定窗口、滑动窗口 并发 令牌桶 全局限流器
资料 限流的方法 速率限制算法 固定窗口算法 是最简单的算法之一。它将请求限制为一个固定的时间窗口,该窗口在任何时间点都只允许固定数量的请求。 滑动窗口算法 是固定窗口算法的改进版本,它将请求限制为一个可变的窗口,该窗口在任何时间…...
【Python】迭代器与生成器详解,附代码(可迭代对象、定义、实现方式、区别、使用场景)
文章目录 1. 可迭代对象1.1 常见的可迭代对象1.2 迭代器和生成器 2. 迭代器2.1 定义2.2 原理2.3 特点2.4 示例2.4.1 for语句进行遍历2.4.2 next() 函数进行遍历2.4.3 自定义迭代器 2.5 内置迭代器 3. 生成器3.1 定义3.2 创建方式3.2.1 生成器表达式3.2.2 生成器函数 3.3 特点 4…...
05.Docker 容器命令
Docker 容器命令 Docker 容器命令1. 启动容器用法2. 显示当前存在容器3. 查看容器内的进程4. 查看容器资源使用情况5. 查看容器的详细信息6. 删除容器7. 容器的启动和停止8. 给正在运行的容器发信号9. 进入正在运行的容器10. 暴露所有容器端口11. 指定端口映射12. 查看容器的日…...
猿大师办公助手对比其他WebOffice在线编辑Office插件有什么优势
1. 原生Office功能完整嵌入,排版一致性保障 猿大师办公助手直接调用本地安装的微软Office、金山WPS或永中Office,支持所有原生功能(如复杂公式、VBA宏等),确保网页编辑与本地打开的文档排版完全一致。 提供OLE嵌入和完…...
Ubuntu搭建RTSP服务器
下载 http://www.live555.com/liveMedia/public/ 安装ffmpeg sudo apt install -y ffmpeg 转换文件(必须!) ffmpeg -i test.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 test.264编译 ./genMakefiles linux-64bit make 启动服务器…...
视觉分析之边缘检测算法
9.1 Roberts算子 Roberts算子又称为交叉微分算法,是基于交叉差分的梯度算法,通过局部差分计算检测边缘线条。 常用来处理具有陡峭的低噪声图像,当图像边缘接近于正45度或负45度时,该算法处理效果更理想。 其缺点是对边缘的定位…...
14.2 Auto-GPT 开源项目深度解析:从代码架构到二次开发实践
Auto-GPT 开源项目深度解析:从代码架构到二次开发实践 关键词:Auto-GPT 源码解读、自主智能体开发、开源项目贡献指南、智能体扩展开发、AI 代理技术栈 一、Auto-GPT 项目全景速览 1.1 项目定位与技术定位 GitHub 数据亮眼: 🌟 Star 数:98k+(截至2024年3月)🚀 贡献…...
Java中的常用类 --String
学习目标 掌握String常用方法掌握StringBuilder、StringBuffer了解正则 1.String ● String是JDK中提前定义好的类型 其所在的包是java.lang ,String翻译过来表示字符串类型,也就是说String类中已经提前定义好了很多方法都是用来处理字符串的,所以Str…...
手机控制电脑远程关机
远程看看软件兼容iOS和Android设备,该软件除了能通过电脑远程关闭另一台电脑外,您还可以通过它在手机上远程关闭公司的电脑。您可以按照以下步骤进行操作以实现电脑远程关机: 步骤1.在手机应用商店搜索“远程看看”进行软件安装,…...
用DeepSeeker + AI 进行物料主数据编码规则学习训练
AI 进行物料主数据编码规则学习训练 作为需要通过AI赋能SAP用户,如何通过DeepSeeker AI帮助SAP进行物料主数据的学习和规则验证 一、核心场景与痛点分析 SAP物料主数据管理挑战 数据质量问题 字段值错误(如单位错误、分类错误)重复数据&#…...
ES6相关操作(2)
一.Promise Promise是ES6引入的异步编程工具。 语法上Promise是一个构造函数,用于封装异步操作并可以获取操作成功或失败的结果 Promise构造函数:Promise(excutor){} Promise的常用函数:then,catch 实例化Promise对象(创建Promise工具) let data"请求数据"//该数据为…...
Java中JDK、JRE,JVM之间的关系
Java中的JDK、JRE和JVM是三个核心概念,其关系可概括为JDK > JRE > JVM,具体如下: 一、定义与作用 JDK(Java Development Kit) 定义:Java开发工具包,用于开发和编译Java程序。包含内容&…...
HTTP SSE 实现
参考: SSE协议 SSE技术详解:使用 HTTP 做服务端数据推送应用的技术 一句概扩 SSE可理解为:服务端和客户端建立连接之后双方均保持连接,但仅支持服务端向客户端推送数据。推送完毕之后关闭连接,无状态行。 下面是基于…...
51单片机介绍
1、单片机基础知识 1.1、单板机 将CPU芯片、存储器芯片、I/O接口芯片和简单的I/O设备(小键盘、LED显示器)等装配到一块印刷电路板上,再配上监控程序(固化在ROM中),就构成了一台单板微型计算机(简称单板机)。 1.2、单片机 在一片集成电路芯片上集成微处理器、存储器…...
Github访问不了解决方案(Mac)
电脑又重装了,到Github下载东西,又访问不了,记录一下解决方案:修改hosts文件。 补充 1、确定可以访问Github的IP地址 打开多个地点ping[github.com]服务器-网站测速-站长工具 输入github.com,点击Ping检测ÿ…...
机器视觉3D深度图颜色含义解析
在机器视觉中,3D深度图颜色变化通常表示以下含义: 1.深度信息变化 颜色深浅:颜色越深,物体越近;颜色越浅,物体越远。 颜色渐变:平滑的渐变表示深度连续变化,突变则表示深度不连续。 …...
鸡兔同笼问题
鸡兔同笼问题是这样一个问题: 现有鸡、兔合装在一个笼子里。数头一共100个头,数脚一共300只脚。问有多少只鸡多少只兔? 在这里讨论这个问题的解法当然太小儿科了。但是y_tab这个C语言解释器只提供了1维数组。如果需要用到2维数组时ÿ…...
【Next.js App Router 深度解剖手册】
🔍 Next.js App Router 深度解剖手册 让我们抛开表象,直击 App Router 的设计核心! 本文将用 2000 字 底层原理图解,带你彻底理解这个现代路由系统的运作机制。系好安全带,准备深入代码底层! Ὠ…...
Spring Boot ShardingJDBC分库分表(草稿)
ShardingJDBC分库分表 1.Maven 引用 <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.1.1</version></dependency><dependency><…...
基于射频开关选择的VNA校准设计
活动发起人小虚竹 想对你说: 这是一个以写作博客为目的的创作活动,旨在鼓励大学生博主们挖掘自己的创作潜能,展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴,那么,快来参加吧!…...
Pipeline 获取 Jenkins参数
Pipeline 获取 Jenkins参数 Jenkins 提供了一系列默认的环境变量,这些变量在构建过程中可以被使用。以下是一些常见的 Jenkins 默认环境变量: WORKSPACE: 当前构建的工作目录路径 JOB_NAME: 当前构建的作业名称 BUILD_NUMBER: 当前构建的编号ÿ…...
ARM Linux平台下 OpenCV Camera 实验
一、硬件原理 1. OV2640 1.1 基本功能 OV2640 是一款低功耗、高性能的图像传感器,支持以下功能: 最高分辨率:200 万像素(1600x1200)。 输出格式:JPEG、YUV、RGB。 内置图像处理功能:自动曝…...
【Python爬虫(30)】构建高效爬虫数据管理体系:从抓取到协作
【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取ÿ…...
淘宝/天猫店铺订单数据导出、销售报表设计与数据分析指南
在电商运营中,订单数据是店铺运营的核心资产之一。通过对订单数据的导出、整理和分析,商家可以更好地了解销售情况、优化运营策略、提升客户满意度,并制定科学的业务决策。本文将详细介绍淘宝/天猫店铺订单数据的导出方法、销售报表的设计思路…...
EasyRTC智能硬件:实时畅联、沉浸互动、消音护航
在当今智能硬件迅猛发展的时代,音视频通讯技术已成为设备与用户、设备与设备间不可或缺的沟通纽带。而EasyRTC,凭借其无可比拟的实时性能、卓越的互动感受以及强大的交互实力,正逐步演变为智能硬件领域的“超级动力”核心。特别是其倾力打造的…...
Docker Mysql 数据迁移
查看启动命令目录映射 查看容器名称 docker ps查看容器的启动命令 docker inspect mysql8.0 |grep CreateCommand -A 20如下图所示:我这边是把/var/lib/mysql 目录映射到我宿主机的/mnt/mysql/data目录下,而且我的数量比较大使用方法1的话时间比较久,所以我采用方法2 如果没…...
【文本】词嵌入经典模型:从one-hot到BERT
【文本】词嵌入经典模型:从one-hot到BERT one-hot编码(独热编码): 根据词表的所有词构建一个向量特征。每一个文段中每个单词有一个词向量(二进制且只有一位为1) — 稀疏、缺乏语义(father&am…...
unity学习49:寻路网格链接 offMeshLinks, 以及传送门效果
目录 1 网格链接 offMeshLinks 功能入口 1.1 unity 2022之前 1.2 unity 2022之后 2 网格链接 offMeshLinks 功能设置 3 点击 offMeshLinks 功能里的bake 3.1 unity 2022之前 3.2 unity 2022之后 3.3 实测link 3.4 跳跃距离增大,可以实现轻功类的效果 4 …...
【SQL】SQL多表查询
多表查询案例联系点击此处 🎄概念 一般我们说的多表查询都涉及外键和父子表之间的关系。比如一对多:一般前面指的是父表后面指的是子表。 ⭐分类 一对多(多对一) 多对多 一对一 ⭐一对多 📢案例:部门与员工的关系 📢关系&…...
linux网络安全设置
TCP SYN Flood 攻击 TCP SYN Flood是一种常见,而且有效的远端(远程)拒绝服务(Denial of Service)攻击方式,它透过一定的操作破坏TCP三次握手建立正常连接,占用并耗 费系统资源,使得提供TCP服务的主机系统无法正常工作。由於TCP SY…...
AutoDock CrankPep or ADCP进行蛋白质多肽对接
需求描述 使用AutoDock CrankPep or ADCP进行蛋白质多肽对接 硬件及系统配置 自用电脑型号如下: 电脑:Precision Tower 7810 (Dell Inc.) CPU : Intel Xeon CPU E5-2686 v4 2.30GHz GPU: NVIDIA GeForce GTX 1070 Linux版本&a…...
Qt开源项目获取
GitHub上超实用的Qt开源项目,码住不谢!🎉 宝子们,今天来给大家安利一波GitHub上超棒的Qt开源项目,无论是学习还是开发,都能找到超多灵感和实用工具,快来看看有没有你需要的吧!1. Qt-Advanced-Docking-System完美的Dock窗口布局解决方案,让你的窗口管理变得超级灵活。…...
Java——super
在Java中,super关键字用于引用父类的成员(属性、方法或构造器)。它在继承关系中非常重要,主要用于以下几种场景: 1. 调用父类的构造器 在子类的构造器中,可以使用super关键字调用父类的构造器。super()必须…...
【设计模式精讲】创建型模式之原型模式(深克隆、浅克隆)
文章目录 第四章 创建型模式4.5 原型模式4.5.1 原型模式介绍4.5.2 原型模式原理4.5.3 深克隆与浅克隆4.5.4 原型模式应用实例4.5.5 原型模式总结 个人主页:道友老李 欢迎加入社区:道友老李的学习社区 第四章 创建型模式 4.5 原型模式 4.5.1 原型模式介…...
DeepSeek动画视频全攻略:从架构到本地部署
DeepSeek 本身并不直接生成动画视频,而是通过与一系列先进的 AI 工具和传统软件协作,完成动画视频的制作任务。这一独特的架构模式,使得 DeepSeek 在动画视频创作领域发挥着不可或缺的辅助作用。其核心流程主要包括脚本生成、画面设计、视频合成与后期处理这几个关键环节。 …...
嵌入式面试高频面试题:嵌入式系统调试方法大全
目录 调试基础概述 调试的重要性 嵌入式系统特点 调试流程 硬件调试方法 JTAG 调试 仿真器调试 逻辑分析仪 软件调试技巧 断点调试 日志输出 内存监视 代码静态分析 嵌入式调试器 常用调试器介绍 调试器使用技巧 远程调试方法 串口调试 网络调试 特殊调试场…...
Java中Map循环安全的删除数据的4中方法
文章目录 前言一、使用Iterator删除二、使用 removeIf(Java 8)三、遍历时记录需要删除的键(不推荐)四、使用 Stream(Java 8)总结 前言 在 Java 中,遍历 HashMap 并删除数据时,直接使…...
影刀RPA中级证书-Excel进阶-开票清单
1.操作题需求 请参照视频内容,将开票账单表格中的数据整理成开票清单。请下载 开票账单.xlsx 整理规则如下: 1. 金额为0的数据为赠品,无需开票,需删除2. 开票清单需要从开票账单中获取的数据包括有开票名称、数量、金额、税率&…...
PMBOK第7版整体架构全面详解
1. 引言 7月1日对于项目管理从业者和研究者而言,是个非凡意义的一个时间,这一天,翘首以待的《 项 目管理知识体系指南 》(PMBOK)第七版终于发布了。 总体而言,PMBOK第七版集百家之所长,成一…...
el-dropdown选中效果
vue2版本 <template><el-dropdown size"mini" command"handleCommand"><span class"el-dropdown-link">{{ selectedOption }}<i class"el-icon-arrow-down el-icon--right"></i></span><el-d…...
解决 `pip install open-webui` 时的编译错误:Microsoft Visual C++ 14.0 或更高版本缺失
在尝试安装 Python 包 open-webui 时,如果你遇到了如下错误信息: error: subprocess-exited-with-error Building wheel for chroma-hnswlib (pyproject.toml) did not run successfully. │ exit code: 1 ╰─> [5 lines of output]running bdist_w…...
git使用指南
一、git客户端设置 git config --global http.sslVerify false git config --global user.name 315222 git config --global user.email li_feng10dahuatech.com ssh-keygen -t rsa -C li_feng10dahuatech.com...
SpringBoot整合Redis和Redision锁
参考文章 1.Redis 1.导入依赖 <!--Redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.c…...
DeepSeek与ChatGPT的对比分析
一 概述 1 DeepSeek DeepSeek是杭州深度求索(DeepSeek)官方推出的AI助手,免费体验与全球领先AI模型的互动交流。总参数达到6710亿的DeepSeek-V3大模型,多项性能指标对齐海外顶尖模型,用更快的速度、更加全面强…...
部署前端项目
前端项目部署是指将前端应用程序从开发环境转移到生产环境的过程,涉及上传代码和资源文件至服务器并确保其正确运行,以下是详细步骤: 一、前期准备 检查项目依赖:确保项目的所有依赖都已正确安装,并更新到最新版本。常…...
python-leetcode 38.翻转二叉树
题目: 给定一个二叉树的根节点root,检查它是否轴对称。 方法一:递归 如果一个树的左子树与右子树镜像对称,那么这个树是对称的。 互为镜像的条件:他们的两个根结点具有相同的值,每棵树的右子树都与另一个树的左子树…...
js中常用方法整理
数据类型 typeOf()Number()parseInt()parseFloat()- * / %检测数据类型转换为数字转换为整数类型转换为浮点类型非加法的数字运算toString()Boolean()String()转换为字符串,不能转换undefined/null字符串拼接转换为布尔类型转换为字符串、所有…...
【云原生】最新版Kubernetes集群基于Containerd部署
文章目录 Kubernetes集群基于Containerd部署(单主多从模式)资源列表基础环境一、基础环境准备1.1、关闭Swap分区1.2、添加hosts解析1.3、桥接的IPv4流量传递给iptables的链 二、准备Containerd容器运行时2.1、安装Containerd2.2、配置Containerd2.3、启动Containerd 三、部署Ku…...