DeepSeek 助力 Vue 开发:打造丝滑的侧边栏(Sidebar)

news2025/2/21 17:57:28

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕

共同探索软件研发!敬请关注【宝码香车】
关注描述

csdngif标识

目录

  • DeepSeek 助力 Vue 开发:打造丝滑的侧边栏(Sidebar)
    • 📚前言
    • 📚进入安装好的DeepSeek
    • 📚页面效果
    • 📚指令输入
    • 📚think
      • 📘组件代码
      • 📘调用示例
      • 📘扩展建议
    • 📚代码测试
    • 📚整理后主要代码
      • 📘定义组件 Sidebar.vue
      • 📘调用 SidebarView.vue
    • 📚其他代码
      • 📘编写 \router\index.js
      • 📘编写 App.vue
    • 📚页面效果
    • 📚自己部署 DeepSeek 安装地址
    • 📚相关文章


📚📗📕📘📖🕮💡📝🗂️✍️🛠️💻🚀🎉🏗️🌐🖼️🔗📊👉🔖⚠️🌟🔐⬇️·正文开始⬇️·🎥😊🎓📩😺🌈🤝🤖📜📋🔍✅🧰❓📄📢📈 🙋0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣🔟🆗*️⃣#️⃣

DeepSeek 助力 Vue 开发:打造丝滑的侧边栏(Sidebar)

📚前言

在成本方面,DeepSeek 具有明显的优势。其训练成本和推理成本都远低于其他同类模型。例如,DeepSeek-V3 的训练成本仅为 557.6 万美元,而训练 GPT-4 这样的模型则需要数亿美元乃至数十亿美元 。在推理成本方面,DeepSeek 的 API 定价仅为每百万 tokens 输入 1 元、输出 2 元,价格仅为 GPT-4 Turbo 的百分之一 。如此低的成本,使得更多的企业和开发者能够使用 DeepSeek 的技术,降低了人工智能应用的门槛。

在功能方面,DeepSeek 不仅具备强大的自然语言处理能力,还在多模态处理、个性化推荐等方面具有独特的优势。在多模态处理方面,DeepSeek 支持文本、图像、语音等多种模态的数据融合和学习,能够实现更丰富和全面的理解和推理。在智能客服场景中,用户既可以通过文字与 DeepSeek 交流,也可以直接发送语音指令,甚至上传相关图片辅助说明问题,DeepSeek 都能准确理解用户需求,并提供相应的解决方案。在个性化推荐方面,DeepSeek 能根据用户行为和偏好,提供个性化内容推荐,提升用户满意度和参与度。

📚进入安装好的DeepSeek

0基础3步部署自己的DeepSeek安装步骤

打开搭建好的DeepSeek应用。

DeepSeek应用

进入应用。

进入DeepSeek应用

📚页面效果

页面效果

📚指令输入

已经创建好了一个基于Vue3的组合式API的项目(Composition API),并能正常运行起来,请帮我用 Vue3的组合式API(Composition API) 生成一个 侧边栏(Sidebar) 的功能组件,所有代码都保存在components/Sidebar 下的文件夹中。功能组件的script标签中只有setup属性,使用普通 JavaScript 实现,不使用TypeScript。
功能要有,如下属性:

属性名说明类型默认值
position侧边栏位置(left/right)String‘left’
width侧边栏宽度(支持所有CSS单位)String/Number‘300px’
collapsible是否可折叠Booleantrue
defaultCollapsed默认是否折叠Booleanfalse
showOverlay是否显示遮罩层(移动端模式)Booleantrue
overlayOpacity遮罩层透明度(0-1)Number0.5
closeOnClickOutside点击遮罩层/外部区域是否关闭Booleantrue
preventScroll展开时是否禁止背景滚动Booleantrue
animationType过渡动画类型(slide/fade/none)String‘slide’
animationDuration动画持续时间(毫秒)Number300
responsive是否启用响应式(自动在小屏幕折叠)Booleantrue
breakpoint响应式断点(小于该宽度自动折叠)Number768
modelValue控制侧边栏展开状态(v-model绑定)Boolean-
如下事件:
事件名说明参数
update:modelValue状态变化时触发(用于v-model)新状态(Boolean)
open展开时触发-
close折叠时触发-
toggle切换状态时触发新状态(Boolean)
overlay-click点击遮罩层时触发-

你有更好的建议也可以添加,要注明。组件定义好后给出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/
│ │ └── 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
│ │ └── AboutView.vue
│ ├── App.vue # 根组件
│ └── main.js # 应用入口
├── public/ # 公共资源目录
├── index.html # HTML 模板
├── package.json # 项目配置
├── vite.config.js # Vite 配置
└── node_modules/ # 依赖包目录

📚think

好的,我现在需要帮用户生成一个基于Vue3组合式API的侧边栏组件。用户已经提供了一个详细的属性和事件列表,并且要求将所有代码放在components/Sidebar文件夹下,使用普通JavaScript实现。

首先,我得分析用户的需求。他们需要一个功能全面的侧边栏,支持位置、宽度、折叠等功能,并且有各种事件和响应式设计。组件必须使用setup函数,所以我要考虑如何在组合式API中组织这些逻辑。

接下来,我会逐一处理每个属性。比如,position决定侧边栏的位置,left或right,这可以通过动态class来实现。width需要支持所有CSS单位,直接作为style的width应用即可。collapsible和defaultCollapsed会影响侧边栏是否可以折叠以及默认状态,这里可能需要用一个内部的状态变量来管理展开/折叠的状态。

然后是遮罩层部分,showOverlay控制遮罩层的显示与否。当组件在移动端模式下,点击遮罩层或外部区域会关闭侧边栏,这需要监听click事件,并根据条件决定是否关闭。同时,closeOnClickOutside和preventScroll属性也需要处理,可能需要添加事件监听器到document上。

动画部分,animationType和animationDuration决定了过渡效果。使用Vue的TransitionGroup或者自定义过渡类来实现滑动或渐变效果。这里可能需要动态切换class,根据当前状态应用不同的动画样式。

响应式设计方面,当屏幕宽度小于breakpoint时自动折叠。这需要用到useResizeObserver来监听页面大小变化,并在resize事件中调整侧边栏的状态。

关于modelValue和v-model的支持,我需要使用computed属性来处理双向绑定,同时在组件内部触发update:模型值事件。当用户手动打开或关闭侧边栏时,会派发这个事件更新父组件的状态。

事件部分,有open、close、toggle、overlay-click等事件,这些都需要通过emit函数来派发。例如,在点击遮罩层的时候,派发overlay-click事件,并在回调中处理关闭逻辑。

现在考虑内部状态管理,我会用ref定义isCollapsed和isOpen两个变量。isCollapsed表示当前是否折叠,isOpen可能用于控制显示隐藏的动画过渡。当组件挂载时,根据defaultCollapsed设置初始状态。

接下来是方法部分,toggleSidebar用来切换展开/折叠状态,并派发相应的事件。handleOverlayClick则处理点击遮罩层的情况,只有在closeOnClickOutside为true时才会关闭侧边栏。

然后是响应式处理,监听页面的resize事件,当宽度小于breakpoint时,自动折叠侧边栏。这可能需要使用useResizeObserver或直接监听window.resize事件,并根据当前状态和断点调整isCollapsed的值。

样式方面,我会动态绑定class,根据position决定left还是right,以及是否显示隐藏。width属性通过style对象应用到侧边栏容器上。遮罩层的透明度由overlayOpacity控制,添加对应的背景颜色。

最后是写示例组件,展示如何在父组件中使用这个侧边栏。例如,绑定modelValue、设置不同的位置和宽度,以及监听各种事件来响应状态变化。

在整个过程中,我需要确保代码结构清晰,逻辑正确,并且覆盖所有用户提供的属性和事件。同时,考虑到性能优化,避免不必要的计算或重复渲染。最后,测试组件在不同情况下的表现,比如移动端和桌面端的显示效果,动画是否流畅,点击外部区域是否正确关闭等。

📘组件代码

根据组件设计经验和最佳实践,以下是侧边栏组件的开发建议和完整方案:
src/components/Sidebar/Sidebar.vue

<template>
  <transition :name="transitionName" :duration="animationDuration">
    <div 
      v-show="isOpen"
      class="sidebar"
      :class="[positionClass, { collapsible }]"
      :style="sidebarStyles"
    >
      <!-- 头部插槽 -->
      <div v-if="$slots.header" class="sidebar-header">
        <slot name="header"></slot>
      </div>

      <!-- 内容区域 -->
      <div class="sidebar-body">
        <slot></slot>
      </div>

      <!-- 底部插槽 -->
      <div v-if="$slots.footer" class="sidebar-footer">
        <slot name="footer"></slot>
      </div>
    </div>
  </transition>

  <!-- 遮罩层 -->
  <transition name="fade" :duration="animationDuration">
    <div
      v-if="showOverlay && isOpen"
      class="sidebar-overlay"
      :style="overlayStyles"
      @click="handleOverlayClick"
    ></div>
  </transition>
</template>

<script setup>
import { computed, ref, watch, onMounted, onBeforeUnmount } from 'vue'

const props = defineProps({
  position: {
    type: String,
    default: 'left',
    validator: v => ['left', 'right'].includes(v)
  },
  width: {
    type: [String, Number],
    default: '300px'
  },
  collapsible: Boolean,
  defaultCollapsed: Boolean,
  showOverlay: Boolean,
  overlayOpacity: {
    type: Number,
    default: 0.5
  },
  closeOnClickOutside: Boolean,
  preventScroll: Boolean,
  animationType: {
    type: String,
    default: 'slide',
    validator: v => ['slide', 'fade', 'none'].includes(v)
  },
  animationDuration: {
    type: Number,
    default: 300
  },
  responsive: Boolean,
  breakpoint: {
    type: Number,
    default: 768
  },
  modelValue: Boolean
})

const emit = defineEmits([
  'update:modelValue',
  'open',
  'close',
  'toggle',
  'overlay-click'
])

// 响应式状态
const isOpen = ref(!props.defaultCollapsed)
const windowWidth = ref(window.innerWidth)

// 计算属性
const positionClass = computed(() => `position-${props.position}`)
const transitionName = computed(() => props.animationType === 'slide' ? `slide-${props.position}` : props.animationType)

const sidebarStyles = computed(() => ({
  width: typeof props.width === 'number' ? `${props.width}px` : props.width
}))

const overlayStyles = computed(() => ({
  opacity: props.overlayOpacity,
  backgroundColor: `rgba(0,0,0,${props.overlayOpacity})`
}))

// 方法
const toggle = (state) => {
  const newState = typeof state === 'boolean' ? state : !isOpen.value
  isOpen.value = newState
  emit('update:modelValue', newState)
  emit('toggle', newState)
  newState ? emit('open') : emit('close')
  
  // 处理滚动锁定
  if (props.preventScroll) {
    document.body.style.overflow = newState ? 'hidden' : ''
  }
}

const handleOverlayClick = () => {
  emit('overlay-click')
  if (props.closeOnClickOutside) toggle(false)
}

// 响应式处理
const checkResponsive = () => {
  if (props.responsive && windowWidth.value <= props.breakpoint) {
    toggle(false)
  }
}

// 生命周期
onMounted(() => {
  window.addEventListener('resize', () => {
    windowWidth.value = window.innerWidth
    checkResponsive()
  })
})

onBeforeUnmount(() => {
  window.removeEventListener('resize')
  document.body.style.overflow = '' // 清理滚动锁定
})

// 监听props变化
watch(() => props.modelValue, (val) => {
  isOpen.value = val
})

watch(windowWidth, checkResponsive)
</script>

<style scoped>
.sidebar {
  position: fixed;
  top: 0;
  height: 100vh;
  background: #ffffff;
  box-shadow: 2px 0 8px rgba(0,0,0,0.15);
  z-index: 1000;
  transition: transform 0.3s ease;
}

.position-left {
  left: 0;
  transform: translateX(-100%);
}

.position-right {
  right: 0;
  transform: translateX(100%);
}

.slide-left-enter-active,
.slide-left-leave-active {
  transition: transform v-bind('animationDuration + "ms"') ease;
}

.slide-left-enter-to,
.slide-left-leave-from {
  transform: translateX(0);
}

.slide-right-enter-active,
.slide-right-leave-active {
  transition: transform v-bind('animationDuration + "ms"') ease;
}

.slide-right-enter-to,
.slide-right-leave-from {
  transform: translateX(0);
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity v-bind('animationDuration + "ms"') ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

.sidebar-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0,0,0,0.5);
  z-index: 999;
}

.sidebar-header {
  padding: 16px;
  border-bottom: 1px solid #f0f0f0;
}

.sidebar-body {
  padding: 16px;
  height: calc(100vh - 120px);
  overflow-y: auto;
}

.sidebar-footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  padding: 16px;
  border-top: 1px solid #f0f0f0;
}
</style>

📘调用示例

<template>
  <!-- 基本用法 -->
  <Sidebar v-model="isOpen1">
    <template #header>
      <h3>导航菜单</h3>
    </template>
    <!-- 内容 -->
  </Sidebar>

  <!-- 响应式侧边栏 -->
  <Sidebar 
    v-model="isOpen2"
    position="right"
    width="350px"
    :responsive="true"
    :breakpoint="1024"
  >
    <template #footer>
      <button @click="isOpen2 = false">关闭</button>
    </template>
  </Sidebar>

  <!-- 自定义动画 -->
  <Sidebar
    v-model="isOpen3"
    animation-type="fade"
    :animation-duration="500"
    :show-overlay="false"
  />
</template>

<script setup>
import { ref } from 'vue'
import Sidebar from '@/components/Sidebar/Sidebar.vue'

const isOpen1 = ref(true)
const isOpen2 = ref(false)
const isOpen3 = ref(false)
</script>

📘扩展建议

  1. 键盘导航支持

    • 添加ESC键关闭支持
    const handleKeydown = (e) => {
      if (e.key === 'Escape' && isOpen.value) toggle(false)
    }
    
  2. 手势支持(移动端):

    let touchStartX = 0
    
    const onTouchStart = (e) => {
      touchStartX = e.touches[0].clientX
    }
    
    const onTouchEnd = (e) => {
      const deltaX = e.changedTouches[0].clientX - touchStartX
      if (Math.abs(deltaX) > 50) toggle(deltaX > 0)
    }
    
  3. 可访问性增强

    <div 
      role="navigation"
      aria-label="主侧边栏"
      :aria-expanded="isOpen"
    >
    
  4. 样式定制

    .sidebar {
      --sidebar-bg: #fff;
      --sidebar-shadow: 2px 0 8px rgba(0,0,0,0.15);
      background: var(--sidebar-bg);
      box-shadow: var(--sidebar-shadow);
    }
    

通过这种设计,侧边栏组件将具备以下优势:

  • 完整的响应式支持
  • 灵活的动画配置
  • 完善的移动端体验
  • 良好的可访问性
  • 支持插槽内容定制
  • 与Vue3生态完美集成

📚代码测试

有个报错,调整下代码

📚整理后主要代码

📘定义组件 Sidebar.vue

<script setup>
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'

const props = defineProps({
  position: {
    type: String,
    default: 'left',
    validator: v => ['left', 'right'].includes(v)
  },
  width: {
    type: [String, Number],
    default: '300px'
  },
  collapsible: {
    type: Boolean,
    default: true
  },
  defaultCollapsed: {
    type: Boolean,
    default: false
  },
  showOverlay: {
    type: Boolean,
    default: true
  },
  overlayOpacity: {
    type: Number,
    default: 0.5
  },
  closeOnClickOutside: {
    type: Boolean,
    default: true
  },
  preventScroll: {
    type: Boolean,
    default: true
  },
  animationType: {
    type: String,
    default: 'slide',
    validator: v => ['slide', 'fade', 'none'].includes(v)
  },
  animationDuration: {
    type: Number,
    default: 300
  },
  responsive: {
    type: Boolean,
    default: true
  },
  breakpoint: {
    type: Number,
    default: 768
  },
  modelValue: {
    type: Boolean,
    required: true
  }
})

const emit = defineEmits(['update:modelValue', 'open', 'close', 'toggle', 'overlay-click'])

// 计算样式
const sidebarStyles = computed(() => ({
  width: typeof props.width === 'number' ? `${props.width}px` : props.width,
  '--animation-duration': `${props.animationDuration}ms`
}))

const overlayStyles = computed(() => ({
  backgroundColor: `rgba(0, 0, 0, ${props.overlayOpacity})`
}))

// 处理遮罩点击
const handleOverlayClick = () => {
  if (props.closeOnClickOutside) {
    emit('update:modelValue', false)
    emit('overlay-click')
  }
}

// 响应式处理
onMounted(() => {
  if (props.responsive) {
    window.addEventListener('resize', handleResize)
  }
  if (props.preventScroll) {
    document.body.style.overflow = props.modelValue ? 'hidden' : ''
  }
})

onBeforeUnmount(() => {
  if (props.responsive) {
    window.removeEventListener('resize', handleResize)
  }
  if (props.preventScroll) {
    document.body.style.overflow = ''
  }
})

const handleResize = () => {
  if (window.innerWidth < props.breakpoint && props.modelValue) {
    emit('update:modelValue', false)
  }
}

// 监听状态变化
watch(() => props.modelValue, (val) => {
  if (props.preventScroll) {
    document.body.style.overflow = val ? 'hidden' : ''
  }
  emit(val ? 'open' : 'close')
})
</script>

<template>
  <transition :name="animationType" :duration="animationDuration">
    <div v-show="modelValue" class="sidebar-container">
      <div
          class="sidebar"
          :class="[`sidebar-${position}`, { collapsible }]"
          :style="sidebarStyles"
      >
        <slot name="header"></slot>
        <div class="sidebar-content">
          <slot></slot>
        </div>
        <slot name="footer"></slot>
      </div>
      <div
          v-if="showOverlay"
          class="sidebar-overlay"
          :style="overlayStyles"
          @click="handleOverlayClick"
      ></div>
    </div>
  </transition>
</template>

<style scoped>
.sidebar-container {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
}

.sidebar {
  position: fixed;
  top: 0;
  bottom: 0;
  background: #fff;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  z-index: 1001;
}

.sidebar-left { left: 0; }
.sidebar-right { right: 0; }

.sidebar-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1000;
}

.slide-enter-active,
.slide-leave-active {
  transition: transform var(--animation-duration) ease;
}

.slide-enter-from.sidebar-left,
.slide-leave-to.sidebar-left {
  transform: translateX(-100%);
}

.slide-enter-from.sidebar-right,
.slide-leave-to.sidebar-right {
  transform: translateX(100%);
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity var(--animation-duration) ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>

📘调用 SidebarView.vue

<script setup>
import { ref } from 'vue'
import Sidebar from '../components/Sidebar/Sidebar.vue'

// 基础示例状态
const isBasicOpen = ref(false)

// 响应式示例状态
const isResponsiveOpen = ref(false)

// 自定义主题示例状态
const isCustomOpen = ref(false)

// 处理菜单点击
const handleMenuClick = () => {
  console.log('Menu item clicked')
}
</script>

<template>
  <div class="sidebar-demo">
    <!-- 基础示例 -->
    <section class="demo-section">
      <h3>基础示例</h3>
      <button @click="isBasicOpen = true">打开左侧边栏</button>
      <Sidebar v-model="isBasicOpen">
        <template #header>
          <h3>基础侧边栏</h3>
        </template>

        <div class="menu-items">
          <div class="menu-item" @click="handleMenuClick">菜单项 1</div>
          <div class="menu-item" @click="handleMenuClick">菜单项 2</div>
          <div class="menu-item" @click="handleMenuClick">菜单项 3</div>
        </div>
      </Sidebar>
    </section>

    <!-- 响应式示例 -->
    <section class="demo-section">
      <h3>响应式示例</h3>
      <button @click="isResponsiveOpen = true">打开右侧边栏</button>
      <Sidebar
          v-model="isResponsiveOpen"
          position="right"
          :responsive="true"
          :breakpoint="768"
          animationType="fade"
      >
        <template #header>
          <h3>响应式侧边栏</h3>
        </template>

        <div class="responsive-content">
          <p>在小屏幕下自动折叠</p>
          <button @click="isResponsiveOpen = false">关闭</button>
        </div>
      </Sidebar>
    </section>

    <!-- 自定义主题示例 -->
    <section class="demo-section">
      <h3>自定义主题示例</h3>
      <button @click="isCustomOpen = true">打开自定义侧边栏</button>
      <Sidebar
          v-model="isCustomOpen"
          width="400px"
          :overlay-opacity="0.7"
          :animation-duration="500"
      >
        <template #header>
          <div class="custom-header">
            <h3>自定义主题</h3>
            <button @click="isCustomOpen = false">×</button>
          </div>
        </template>

        <div class="custom-content">
          <p>自定义宽度和动画效果</p>
          <div class="custom-menu">
            <div class="custom-menu-item">设置</div>
            <div class="custom-menu-item">个人信息</div>
            <div class="custom-menu-item">退出</div>
          </div>
        </div>
      </Sidebar>
    </section>
  </div>
</template>

<style scoped>
.sidebar-demo {
  padding: 20px;
}

.demo-section {
  margin-bottom: 30px;
}

button {
  padding: 8px 16px;
  margin: 10px 0;
  border: none;
  border-radius: 4px;
  background: #409EFF;
  color: white;
  cursor: pointer;
}

.menu-items {
  padding: 10px;
}

.menu-item {
  padding: 10px;
  cursor: pointer;
}

.menu-item:hover {
  background: #f5f7fa;
}

.custom-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #eee;
}

.custom-content {
  padding: 20px;
}

.custom-menu-item {
  padding: 12px;
  margin: 8px 0;
  background: #f5f7fa;
  border-radius: 4px;
  cursor: pointer;
}

.custom-menu-item:hover {
  background: #e4e7ed;
}
</style>

📚其他代码

📘编写 \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')
    }
  ],
})

export default router

📘编写 App.vue

<script setup>
import { ref } from 'vue'
import Sidebar from '../components/Sidebar/Sidebar.vue'

// 基础示例状态
const isBasicOpen = ref(false)

// 响应式示例状态
const isResponsiveOpen = ref(false)

// 自定义主题示例状态
const isCustomOpen = ref(false)

// 处理菜单点击
const handleMenuClick = () => {
  console.log('Menu item clicked')
}
</script>

<template>
  <div class="sidebar-demo">
    <!-- 基础示例 -->
    <section class="demo-section">
      <h3>基础示例</h3>
      <button @click="isBasicOpen = true">打开左侧边栏</button>
      <Sidebar v-model="isBasicOpen">
        <template #header>
          <h3>基础侧边栏</h3>
        </template>

        <div class="menu-items">
          <div class="menu-item" @click="handleMenuClick">菜单项 1</div>
          <div class="menu-item" @click="handleMenuClick">菜单项 2</div>
          <div class="menu-item" @click="handleMenuClick">菜单项 3</div>
        </div>
      </Sidebar>
    </section>

    <!-- 响应式示例 -->
    <section class="demo-section">
      <h3>响应式示例</h3>
      <button @click="isResponsiveOpen = true">打开右侧边栏</button>
      <Sidebar
          v-model="isResponsiveOpen"
          position="right"
          :responsive="true"
          :breakpoint="768"
          animationType="fade"
      >
        <template #header>
          <h3>响应式侧边栏</h3>
        </template>

        <div class="responsive-content">
          <p>在小屏幕下自动折叠</p>
          <button @click="isResponsiveOpen = false">关闭</button>
        </div>
      </Sidebar>
    </section>

    <!-- 自定义主题示例 -->
    <section class="demo-section">
      <h3>自定义主题示例</h3>
      <button @click="isCustomOpen = true">打开自定义侧边栏</button>
      <Sidebar
          v-model="isCustomOpen"
          width="400px"
          :overlay-opacity="0.7"
          :animation-duration="500"
      >
        <template #header>
          <div class="custom-header">
            <h3>自定义主题</h3>
            <button @click="isCustomOpen = false">×</button>
          </div>
        </template>

        <div class="custom-content">
          <p>自定义宽度和动画效果</p>
          <div class="custom-menu">
            <div class="custom-menu-item">设置</div>
            <div class="custom-menu-item">个人信息</div>
            <div class="custom-menu-item">退出</div>
          </div>
        </div>
      </Sidebar>
    </section>
  </div>
</template>

<style scoped>
.sidebar-demo {
  padding: 20px;
}

.demo-section {
  margin-bottom: 30px;
}

button {
  padding: 8px 16px;
  margin: 10px 0;
  border: none;
  border-radius: 4px;
  background: #409EFF;
  color: white;
  cursor: pointer;
}

.menu-items {
  padding: 10px;
}

.menu-item {
  padding: 10px;
  cursor: pointer;
}

.menu-item:hover {
  background: #f5f7fa;
}

.custom-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #eee;
}

.custom-content {
  padding: 20px;
}

.custom-menu-item {
  padding: 12px;
  margin: 8px 0;
  background: #f5f7fa;
  border-radius: 4px;
  cursor: pointer;
}

.custom-menu-item:hover {
  background: #e4e7ed;
}
</style>

📚页面效果

页面效果

📚自己部署 DeepSeek 安装地址

蓝耘元生代智算云平台地址:https://cloud.lanyun.net/#/registerPage?promoterCode=07100c37a0

📚相关文章

 

———— 相 关 文 章 ————

 

  1. 0基础3步部署自己的DeepSeek安装步骤

  2. DeepSeek 助力 Vue 开发:打造丝滑的步骤条

  3. DeepSeek 助力 Vue 开发:打造丝滑的进度条(Progress Bar)

  4. 自己部署 DeepSeek 助力 Vue 开发:打造丝滑的标签页(Tabs)

  5. 自己部署 DeepSeek 助力 Vue 开发:打造丝滑的折叠面板(Accordion)

  6. 自己部署 DeepSeek 助力 Vue 开发:打造丝滑的时间线(Timeline )

  7. DeepSeek 助力 Vue 开发:打造丝滑的返回顶部按钮(Back to Top)

  8. DeepSeek 助力 Vue 开发:打造丝滑的通知栏(Notification Bar)

  9. DeepSeek 助力 Vue 开发:打造丝滑的卡片(Card)

  10. DeepSeek 助力 Vue 开发:打造丝滑的无限滚动(Infinite Scroll)

  11. DeepSeek 助力 Vue 开发:打造丝滑的开关切换(Switch)

到此这篇文章就介绍到这了,更多精彩内容请关注本人以前的文章或继续浏览下面的文章,创作不易,如果能帮助到大家,希望大家多多支持宝码香车~💕,若转载本文,一定注明本文链接。


整理不易,点赞关注宝码香车

更多专栏订阅推荐:
👍 html+css+js 绚丽效果
💕 vue
✈️ Electron
⭐️ js
📝 字符串
✍️ 时间对象(Date())操作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2299426.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于opencv的 24色卡IQA评测算法源码-可完全替代Imatest

1.概要 利用24色卡可以很快的分析到曝光误差&#xff0c;白平衡误差&#xff0c;噪声&#xff0c;色差&#xff0c;饱和度&#xff0c;gamma值。IQA或tuning工程一般用Imatest来手动计算&#xff0c;不便于产测部署&#xff0c;现利用opencv实现了imatest的全部功能&#xff0c…

数据结构与算法之排序算法-(计数,桶,基数排序)

排序算法是数据结构与算法中最基本的算法之一&#xff0c;其作用就是将一些可以比较大小的数据进行有规律的排序&#xff0c;而想要实现这种排序就拥有很多种方法~ &#x1f4da; 非线性时间比较类&#xff1a; 那么我将通过几篇文章&#xff0c;将排序算法中各种算法细化的&a…

MATLAB图像处理:图像特征概念及提取方法HOG、SIFT

图像特征是计算机视觉中用于描述图像内容的关键信息&#xff0c;其提取质量直接影响后续的目标检测、分类和匹配等任务性能。本文将系统解析 全局与局部特征的核心概念&#xff0c;深入讲解 HOG&#xff08;方向梯度直方图&#xff09;与SIFT&#xff08;尺度不变特征变换&…

kibana es 语法记录 elaticsearch

目录 一、认识elaticsearch 1、什么是正向索引 2、什么是倒排索引 二、概念 1、说明 2、mysql和es的对比 三、mapping属性 1、定义 四、CRUD 1、查看es中有哪些索引库 2、创建索引库 3、修改索引库 4、删除索引库 5、新增文档 6、删除文档 5、条件查询 一、认识…

手写一个Java Android Binder服务及源码分析

手写一个Java Android Binder服务及源码分析 前言一、Java语言编写自己的Binder服务Demo1. binder服务demo功能介绍2. binder服务demo代码结构图3. binder服务demo代码实现3.1 IHelloService.aidl3.2 IHelloService.java&#xff08;自动生成&#xff09;3.3 HelloService.java…

【动态规划篇】:当回文串遇上动态规划--如何用二维DP“折叠”字符串?

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;动态规划篇–CSDN博客 文章目录 一.回文串类DP核心思想&#xff08;判断所有子串是否是回文…

Windows 安装 GDAL 并配置 Rust-GDAL 开发环境-1

Rust-GDAL 是 Rust 语言的 GDAL&#xff08;Geospatial Data Abstraction Library&#xff09; 绑定库&#xff0c;用于处理地理数据。由于 GDAL 依赖较多&#xff0c;在 Windows 上的安装相对复杂&#xff0c;本文档将介绍如何安装 GDAL 并配置 Rust-GDAL 的开发环境。 1. 检…

第1期 定时器实现非阻塞式程序 按键控制LED闪烁模式

第1期 定时器实现非阻塞式程序 按键控制LED闪烁模式 解决按键扫描&#xff0c;松手检测时阻塞的问题实现LED闪烁的非阻塞总结补充&#xff08;为什么不会阻塞&#xff09; 参考江协科技 KEY1和KEY2两者独立控制互不影响 阻塞&#xff1a;如果按下按键不松手&#xff0c;程序就…

开源语音克隆项目 OpenVoice V2 本地部署

#本机环境 WIN11 I5 GPU 4060ti 16G 内存 32G #开始 git clone https://github.com/myshell-ai/OpenVoice.git conda create -n opvenv python3.9 -y conda activate opvenv pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/…

DeepSeek大模型一键部署解决方案:全平台多机分布式推理与国产硬件优化异构计算私有部署

DeepSeek R1 走红后&#xff0c;私有部署需求也随之增长&#xff0c;各种私有部署教程层出不穷。大部分教程只是简单地使用 Ollama、LM Studio 单机运行量化蒸馏模型&#xff0c;无法满足复杂场景需求。一些操作配置也过于繁琐&#xff0c;有的需要手动下载并合并分片模型文件&…

如何利用PLM软件有效地推进制造企业标准化工作?

在智能制造浪潮的推动下&#xff0c;中国制造业正面临从“规模扩张”向“质量提升”的关键转型。工信部数据显示&#xff0c;85%的制造企业在产品研发、生产过程中因标准化程度不足导致效率损失超20%&#xff0c;而标准化水平每提升10%&#xff0c;企业综合成本可降低5%-8%。如…

环境影响评价(EIA)中,土地利用、植被类型及生态系统图件的制作

在环境影响评价&#xff08;EIA&#xff09;中&#xff0c;土地利用、植被类型及生态系统图件的制作需依据科学、法规和技术规范&#xff0c;以确保数据的准确性和图件的规范性。以下是主要的制作依据&#xff1a; 1. 法律法规与政策依据 《中华人民共和国环境影响评价法》 明确…

更高效实用 vscode 的常用设置

VSCode 可以说是文本编辑神器, 不止程序员使用, 普通人用其作为文本编辑工具, 更是效率翻倍. 这里分享博主对于 VSCode 的好用设置, 让 VSCode 如虎添翼 进入设置 首先进入设置界面, 后续都在这里进行配置修改 具体设置 每项配置通过搜索关键字, 来快速定位配置项 自动保存…

【异或数列——博弈论】

题目 思路 异或和为0&#xff08;即每一位都有偶数个1&#xff09;&#xff1a;平局最高有效位只有唯一的1&#xff1a;先手必胜最高有效位有奇数个1&#xff0c;偶数个0&#xff1a;先手必胜 若先选1产生优势&#xff0c;则剩下偶数个1&#xff0c;偶数个0&#xff1a;对手选…

草图绘制技巧

1、点击菜单栏文件–》新建–》左下角高级新手切换–》零件&#xff1b; 2、槽口&#xff1a;直槽口&#xff0c;中心点槽口&#xff0c;三点源槽口&#xff0c;中心点圆弧槽口&#xff1b; 3、草图的约束&#xff1a;需要按住ctrl键&#xff0c;选中两个草图&#xff0c;然后…

Spring Boot中如何自定义Starter

文章目录 Spring Boot中如何自定义Starter概念和作用1. 概念介绍2. 作用和优势2.1 简化依赖管理2.2 提供开箱即用的自动配置2.3 标准化和模块化开发2.4 提高开发效率2.5 提供灵活的配置覆盖3. 应用场景创建核心依赖1. 确定核心依赖的作用2. 创建 starter-core 模块2.1 依赖管理…

内容中台构建高效数字化内容管理新范式

内容概要 在数字化转型浪潮中&#xff0c;高效的内容管理能力已成为企业构建核心竞争力的关键要素。通过动态发布引擎、元数据智能分类与跨平台协作机制&#xff0c;企业能够实现内容的实时触达与精准分发&#xff0c;同时确保知识资产在多终端环境下的无缝适配与安全共享。这…

PyQt组态软件 拖拽设计界面测试

PyQt组态软件测试 最近在研究PyQt,尝试写个拖拽设计界面的组态软件&#xff0c;目前实现的功能如下&#xff1a; 支持拖入控件&#xff0c;鼠标拖动控件位置 拖动控件边缘修改控件大小支持属性编辑器&#xff0c;修改当前选中控件的属性 拖动框选控件&#xff0c;点选控件 控…

深度学习R4周:LSTM-火灾温度预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 任务&#xff1a; 数据集中提供了火灾温度&#xff08;Tem1&#xff09;、一氧化碳浓度&#xff08;CO 1&#xff09;烟雾浓度&#xff08;Soot 1&#xff09;…

Datawhale 数学建模导论二 笔记1

第6章 数据处理与拟合模型 本章主要涉及到的知识点有&#xff1a; 数据与大数据Python数据预处理常见的统计分析模型随机过程与随机模拟数据可视化 本章内容涉及到基础的概率论与数理统计理论&#xff0c;如果对这部分内容不熟悉&#xff0c;可以参考相关概率论与数理统计的…