DeepSeek 助力 Vue 开发:打造丝滑的面包屑导航(Breadcrumbs)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕
目录
- DeepSeek 助力 Vue 开发:打造丝滑的面包屑导航(Breadcrumbs)
- 📚前言
- 📚进入安装好的DeepSeek
- 📚页面效果
- 📚指令输入
- **1. 属性 (Props)**
- **2. 事件 (Events)**
- **3. 插槽 (Slots)**
- **路由集成**
- **激活项处理**
- **可访问性**
- **样式**
- **响应式设计**
- 📚think
- 📘组件代码
- 📘以下是两个使用示例:
- 📘优化建议:
- 📘组件特点:
- 📘使用时请确保:
- 📚代码测试
- 📚上面是主要代码,为了代码正常跑通,附其他辅助代码。
- 📘编写 src\router\index.js
- 🗂️文件位置
- 📝代码
- 📘编写 src\App.vue
- 🗂️文件位置
- 📝代码
- 📚页面效果
- 📚自己部署 DeepSeek 安装地址
- 📚相关文章
📚📗📕📘📖🕮💡📝🗂️✍️🛠️💻🚀🎉🏗️🌐🖼️🔗📊👉🔖⚠️🌟🔐⬇️·正文开始
⬇️·🎥😊🎓📩😺🌈🤝🤖📜📋🔍✅🧰❓📄📢📈 🙋0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣🔟🆗*️⃣#️⃣
DeepSeek 助力 Vue 开发:打造丝滑的面包屑导航(Breadcrumbs)
📚前言
DeepSeek 在中文语境优化方面也做得非常出色。由于其训练语料中中文占比超 40%,因此更符合中文语言习惯和文化背景,在中文语法、成语、网络用语及行业术语方面进行了专项训练,中文语义理解准确率高。而 ChatGPT 的中文语料占比约 10%,在中文处理上相对较弱。
DeepSeek 采用了完全开源策略,将模型权重、训练框架及数据管道全部开源,采用 MIT 许可证,允许用户自由使用、修改和商业化。这一策略对 AI 社区和行业发展产生了深远的影响。
📚进入安装好的DeepSeek
0基础3步部署自己的DeepSeek安装步骤
打开搭建好的DeepSeek应用。
进入应用。
📚页面效果
📚指令输入
已经创建好了一个基于Vue3的组合式API的项目(Composition API),并能正常运行起来,请帮我用 Vue3的组合式API(Composition API) 生成一个 面包屑导航(Breadcrumbs) 的功能组件,所有代码都保存在components/Breadcrumbs 下的文件夹中。功能组件的script标签中只有setup属性,使用普通 JavaScript 实现,不使用TypeScript。
功能要有,如下属性:
为了创建一个灵活且可重用的 Vue3 面包屑导航组件,以下是建议的属性和事件定义,以及其他关键实现要点:
1. 属性 (Props)
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
items | BreadcrumbItem[] | 必填 | 面包屑项数组,每个元素包含 text , to , icon 等字段 |
separator | string | Component | '/' | 分隔符(支持文本或图标组件) |
disableRouter | boolean | false | 是否禁用自动路由跳转(触发事件代替) |
activeClass | string | 'active' | 当前激活项的 CSS 类名(通常最后一个项自动激活) |
containerClass | string | '' | 容器元素的自定义类名 |
itemClass | string | '' | 每个面包屑项的自定义类名 |
separatorClass | string | '' | 分隔符的自定义类名 |
2. 事件 (Events)
事件名 | 参数 | 说明 |
---|---|---|
item-click | (item: BreadcrumbItem, event: MouseEvent) | 点击面包屑项时触发(disableRouter 为 true 时需手动处理跳转) |
3. 插槽 (Slots)
插槽名 | 作用域参数 | 说明 |
---|---|---|
item | { item, isActive } | 自定义单个面包屑项的渲染内容 |
separator | - | 自定义分隔符的渲染内容 |
路由集成
- 默认使用
router-link
实现导航(需引入 Vue Router)。 - 通过
disableRouter
属性切换为普通<a>
标签或自定义元素。
激活项处理
- 自动将最后一个
item
标记为激活状态(不可点击),通过activeClass
应用样式。
可访问性
- 在容器上添加
role="navigation"
和aria-label="Breadcrumb"
。 - 使用
aria-current="page"
标记当前激活项。
样式
- 提供基础 CSS 结构,但允许通过类名完全覆盖样式。
- 使用 CSS 变量增强主题定制能力:
响应式设计
- 考虑移动端折叠场景(如隐藏中间项),可通过 CSS 媒体查询或逻辑处理实现。
通过以上设计,组件将具备高可定制性,同时保持核心功能的简洁性。开发者可通过插槽、属性以及事件灵活扩展功能。
你有更好的建议也可以添加,要注明。组件定义好后给出2个及以上完整的调用示例。
下面是现有目录
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/
│ │ └── 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
│ │ └── AboutView.vue
│ ├── App.vue # 根组件
│ └── main.js # 应用入口
├── public/ # 公共资源目录
├── index.html # HTML 模板
├── package.json # 项目配置
├── vite.config.js # Vite 配置
└── node_modules/ # 依赖包目录
📚think
嗯,用户已经创建了一个基于Vue3组合式API的项目,并且想生成一个面包屑导航组件。我需要帮他写这个组件,并确保所有代码放在components/Breadcrumbs文件夹下。
首先,分析需求。用户提供了详细的属性、事件和插槽说明,还有路由集成、激活项处理等要点。所以,我得把这些都考虑进去。
先看属性部分。items是必填的,每个item包含text、to、icon。那在组件中,我需要接收这些props,并确保它们正确传递。separator默认是’/',可以是字符串或组件。disableRouter控制是否禁用路由跳转,activeClass用于激活状态的类名。容器和分隔符的类名也需要处理。
接下来是事件。item-click事件在点击时触发,参数包括item和event。当disableRouter为true时,需要手动处理跳转。所以,在setup函数中,我得定义一个emit,并在点击事件里调用它。
插槽方面,有item和separator两个插槽。item插槽传递item和isActive状态,separator插槽没有作用域参数。这意味着在模板中,我需要用slot来渲染这些内容。
路由集成部分,如果disableRouter为false,默认使用router-link,否则用a标签或者自定义元素。所以,在template里,需要根据disableRouter的值来决定使用哪个组件。
激活项处理方面,最后一个item默认是active状态,不能点击。所以,在循环items时,判断是否是最后一个,并设置对应的class和disabled属性。
可访问性也是重点,容器添加role="navigation"和aria-label,当前激活项加aria-current=“page”。
样式部分,用户希望提供基础结构,允许通过类名覆盖。所以,我需要在组件中正确应用containerClass、itemClass和separatorClass,并且可能使用CSS变量来增强主题定制能力。
响应式设计方面,可能需要处理移动端的折叠情况,比如隐藏中间项,这可能需要后续用CSS媒体查询或逻辑处理实现,但目前先不考虑,留到以后扩展。
现在,开始写组件代码。首先,在Breadcrumbs.vue中,使用script标签,setup语法糖,只用普通JavaScript。
在setup函数中,接收props:items、separator、disableRouter、activeClass、containerClass、itemClass、separatorClass。然后,定义emit事件,item-click。
接下来,计算items的长度,最后一个索引是items.length - 1。如果items为空,则抛出警告或处理错误。
渲染部分,使用template,循环每个item,判断是否为最后一个来设置active状态。对于每个item,使用router-link或者a标签,根据disableRouter决定。
分隔符的处理:在每个item后面插入separator,除了最后一个。如果用户提供了separator插槽,就用它;否则,显示props中的separator内容,并应用separatorClass。
插槽方面,item插槽传递item和isActive状态,让开发者自定义渲染内容。separator插槽则没有作用域参数。
测试一下示例是否正确。第一个示例使用默认配置,第二个禁用了路由并添加了点击事件处理,第三个展示了自定义分隔符和样式。这些应该都能正常工作。
最后,确保组件结构清晰,代码规范,并且在main.js中注册了全局组件或在需要的页面引入。
📘组件代码
根据你的需求,我帮你创建了一个灵活的面包屑导航组件。以下是完整实现:
<!-- components/Breadcrumbs/Breadcrumbs.vue -->
<template>
<nav
role="navigation"
aria-label="Breadcrumb"
:class="['breadcrumbs', containerClass]"
>
<ol class="breadcrumbs__list">
<li
v-for="(item, index) in items"
:key="index"
class="breadcrumbs__item"
:class="[
itemClass,
{ [activeClass]: isLast(index) }
]"
>
<!-- 项内容 -->
<slot
name="item"
:item="item"
:isActive="isLast(index)"
>
<component
:is="linkComponent(item)"
v-if="!isLast(index)"
:to="item.to"
class="breadcrumbs__link"
@click="handleClick(item, $event)"
>
<component
:is="item.icon"
v-if="item.icon"
class="breadcrumbs__icon"
/>
<span class="breadcrumbs__text">{{ item.text }}</span>
</component>
<span
v-else
class="breadcrumbs__current"
aria-current="page"
>
<component
:is="item.icon"
v-if="item.icon"
class="breadcrumbs__icon"
/>
{{ item.text }}
</span>
</slot>
<!-- 分隔符 -->
<span
v-if="!isLast(index)"
class="breadcrumbs__separator"
:class="separatorClass"
>
<slot name="separator">
{{ separator }}
</slot>
</span>
</li>
</ol>
</nav>
</template>
<script setup>
import { computed } from 'vue';
import { RouterLink } from 'vue-router';
const props = defineProps({
items: {
type: Array,
required: true,
validator: (value) => {
return value.every(item => 'text' in item);
}
},
separator: {
type: [String, Object],
default: '/'
},
disableRouter: {
type: Boolean,
default: false
},
activeClass: {
type: String,
default: 'active'
},
containerClass: {
type: String,
default: ''
},
itemClass: {
type: String,
default: ''
},
separatorClass: {
type: String,
default: ''
}
});
const emit = defineEmits(['item-click']);
const isLast = (index) => index === props.items.length - 1;
const linkComponent = (item) => {
if (props.disableRouter) {
return item.to ? 'a' : 'span';
}
return item.to ? RouterLink : 'span';
};
const handleClick = (item, event) => {
emit('item-click', item, event);
if (props.disableRouter && item.to) {
event.preventDefault();
}
};
</script>
<style>
.breadcrumbs {
--text-color: #666;
--link-color: #2c3e50;
--active-color: #999;
--separator-margin: 0 8px;
--item-spacing: 0.5rem;
}
.breadcrumbs__list {
display: flex;
list-style: none;
padding: 0;
margin: 0;
}
.breadcrumbs__item {
display: inline-flex;
align-items: center;
color: var(--text-color);
}
.breadcrumbs__link {
color: var(--link-color);
text-decoration: none;
transition: color 0.2s;
}
.breadcrumbs__link:hover {
color: var(--active-color);
}
.breadcrumbs__current {
color: var(--active-color);
}
.breadcrumbs__separator {
margin: var(--separator-margin);
color: var(--text-color);
}
.breadcrumbs__icon {
margin-right: 4px;
}
</style>
📘以下是两个使用示例:
<!-- views/BreadcrumbsView.vue -->
<template>
<div class="breadcrumbs-demo">
<h2>基本用法</h2>
<Breadcrumbs
:items="[
{ text: '首页', to: '/' },
{ text: '用户中心', to: '/user' },
{ text: '个人资料' }
]"
class="my-breadcrumbs"
@item-click="handleItemClick"
/>
<h2>自定义样式和插槽</h2>
<Breadcrumbs
:items="[
{ text: '首页', to: '/', icon: HomeIcon },
{ text: '商品分类', to: '/category' },
{ text: '电子产品' }
]"
separator=">"
active-class="custom-active"
container-class="custom-container"
item-class="custom-item"
separator-class="custom-separator"
>
<template #item="{ item, isActive }">
<span :class="{ 'custom-link': !isActive }">
<component :is="item.icon" v-if="item.icon" />
{{ item.text }}
</span>
</template>
<template #separator>
<span class="custom-sep">→</span>
</template>
</Breadcrumbs>
</div>
</template>
<script setup>
import Breadcrumbs from '@/components/Breadcrumbs/Breadcrumbs.vue';
import HomeIcon from '@/components/icons/Home.vue';
const handleItemClick = (item, event) => {
console.log('Clicked item:', item);
// 自定义处理逻辑
};
</script>
<style>
.my-breadcrumbs {
--link-color: #409eff;
--active-color: #909399;
}
.custom-container {
padding: 12px;
background: #f5f7fa;
}
.custom-item {
font-size: 0.9em;
}
.custom-separator {
color: #c0c4cc;
}
.custom-active {
font-weight: bold;
}
.custom-link {
color: #606266;
}
.custom-sep {
margin: 0 12px;
}
</style>
📘优化建议:
- 响应式折叠:可以添加一个
maxItems
属性,当面包屑项超过指定数量时自动折叠中间项 - 过渡动画:为面包屑变化添加淡入淡出过渡效果
- 路由匹配:自动根据当前路由生成面包屑路径(需配合路由配置)
- 主题系统:通过CSS变量提供更多可定制选项(如间距、字体大小等)
- 键盘导航:添加键盘焦点样式和支持键盘操作
📘组件特点:
- 完全支持Vue Router集成
- 完善的ARIA可访问性支持
- 通过CSS变量实现主题定制
- 灵活的内容插槽系统
- 类型验证和防御性编程
- 移动端友好的响应式设计
📘使用时请确保:
- 已安装并配置vue-router
- 图标组件需要提前注册或导入
- 根据实际需求调整CSS变量值
📚代码测试
正常
📚上面是主要代码,为了代码正常跑通,附其他辅助代码。
📘编写 src\router\index.js
🗂️文件位置
📝代码
import { createRouter, createWebHistory } from 'vue-router'
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')
}
],
})
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>
</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>
📚页面效果
📚自己部署 DeepSeek 安装地址
蓝耘元生代智算云平台地址:https://cloud.lanyun.net/#/registerPage?promoterCode=07100c37a0
📚相关文章
-
0基础3步部署自己的DeepSeek安装步骤
-
DeepSeek 助力 Vue 开发:打造丝滑的步骤条(Step bar)
-
DeepSeek 助力 Vue 开发:打造丝滑的进度条(Progress Bar)
-
自己部署 DeepSeek 助力 Vue 开发:打造丝滑的标签页(Tabs)
-
自己部署 DeepSeek 助力 Vue 开发:打造丝滑的折叠面板(Accordion)
-
自己部署 DeepSeek 助力 Vue 开发:打造丝滑的时间线(Timeline )
-
DeepSeek 助力 Vue 开发:打造丝滑的返回顶部按钮(Back to Top)
-
DeepSeek 助力 Vue 开发:打造丝滑的通知栏(Notification Bar)
-
DeepSeek 助力 Vue 开发:打造丝滑的卡片(Card)
-
DeepSeek 助力 Vue 开发:打造丝滑的无限滚动(Infinite Scroll)
-
DeepSeek 助力 Vue 开发:打造丝滑的开关切换(Switch)
-
DeepSeek 助力 Vue 开发:打造丝滑的侧边栏(Sidebar)
到此这篇文章就介绍到这了,更多精彩内容请关注本人以前的文章或继续浏览下面的文章,创作不易,如果能帮助到大家,希望大家多多支持宝码香车~💕,若转载本文,一定注明本文链接。
更多专栏订阅推荐:
👍 html+css+js 绚丽效果
💕 vue
✈️ Electron
⭐️ js
📝 字符串
✍️ 时间对象(Date())操作