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

重生之我在学Vue--第18天 Vue 3 项目功能扩展

重生之我在学Vue–第18天 Vue 3 项目功能扩展

文章目录

  • 重生之我在学Vue--第18天 Vue 3 项目功能扩展
    • 前言
    • 一、权限管理系统
      • 1.1 用户角色体系设计
      • 1.2 路由权限控制
      • 1.3 组件级权限控制
    • 二、分页与搜索系统
      • 2.1 分页类型对比
      • 2.2 分页组件实现
      • 2.3 搜索功能实现
    • 三、文件上传系统
      • 3.1 文件上传组件
      • 3.2 阿里云OSS集成
    • 四、今日任务:扩展项目功能
      • 4.1 必做任务清单
      • 4.2 扩展挑战

前言

当项目具备基础功能后,我们需要像搭乐高一样添加更复杂的模块!今天我们将解锁三大高阶能力:权限控制数据分页文件处理,让你的任务管理系统具备企业级应用雏形!

Vue3 官方中文文档传送点: 组合式函数 | Vue.js

功能扩展的核心是逻辑复用架构分层,避免代码变成"意大利面条"!

Vue前端成仙之路:Vue 前端成仙之路_野生的程序嫣的博客-CSDN博客

GO后端成神之路:Go 后端成神之路_野生的程序嫣的博客-CSDN博客

一、权限管理系统

1.1 用户角色体系设计

// types/user.d.ts
interface User {
  id: string
  username: string
  role: 'admin' | 'user'
  avatar?: string
}

// stores/auth.ts
export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: null as User | null,
    token: localStorage.getItem('token') || ''
  }),
  actions: {
    login(userData: { username: string; password: string }) {
      // 模拟登录接口
      this.user = { id: '1', username: userData.username, role: 'admin' }
      this.token = 'mock_token'
      localStorage.setItem('token', this.token)
    }
  }
})

1.2 路由权限控制

// router/index.js
router.beforeEach((to) => {
  const authStore = useAuthStore()
  
  // 需要登录且未登录
  if (to.meta.requiresAuth && !authStore.token) {
    return '/login'
  }
  
  // 检查角色权限
  if (to.meta.roles && !to.meta.roles.includes(authStore.user?.role)) {
    return '/403' // 无权限页面
  }
})

1.3 组件级权限控制

<template>
  <button 
    v-if="hasPermission('delete')" 
    @click="handleDelete"
  >
    删除任务
  </button>
</template>

<script setup>
import { useAuthStore } from '@/stores/auth'

const authStore = useAuthStore()
const hasPermission = (action) => {
  return authStore.user?.role === 'admin' || 
    (action === 'view' && authStore.user)
}
</script>

二、分页与搜索系统

2.1 分页类型对比

分页方式适用场景实现要点
前端分页数据量小(<1000条)一次性加载后JS处理
后端分页大数据量需要API支持page/size参数
滚动加载移动端场景监听滚动事件+节流处理

2.2 分页组件实现

<template>
  <div class="pagination">
    <button 
      v-for="page in pages" 
      :key="page"
      :class="{ active: currentPage === page }"
      @click="changePage(page)"
    >
      {{ page }}
    </button>
  </div>
</template>

<script setup>
const props = defineProps({
  total: Number,
  pageSize: Number,
  currentPage: Number
})

const emit = defineEmits(['update:currentPage'])

const pages = computed(() => {
  return Math.ceil(props.total / props.pageSize)
})

const changePage = (page) => {
  emit('update:currentPage', page)
}
</script>

2.3 搜索功能实现

// 前端搜索(适用于小数据)
const filteredList = computed(() => {
  return tasks.value.filter(task => 
    task.title.includes(searchKeyword.value) ||
    task.description.includes(searchKeyword.value)
  )
})

// 后端搜索(推荐)
const loadData = async () => {
  const res = await axios.get('/api/tasks', {
    params: {
      page: currentPage.value,
      size: pageSize.value,
      keyword: searchKeyword.value
    }
  })
  tasks.value = res.data
}

三、文件上传系统

3.1 文件上传组件

<template>
  <div class="uploader">
    <input type="file" @change="handleFileChange" />
    <progress :value="progress" max="100"></progress>
    <button @click="upload">开始上传</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import axios from 'axios'

const file = ref(null)
const progress = ref(0)

const handleFileChange = (e) => {
  file.value = e.target.files[0]
}

const upload = async () => {
  const formData = new FormData()
  formData.append('file', file.value)
  
  await axios.post('/api/upload', formData, {
    onUploadProgress: (e) => {
      progress.value = Math.round((e.loaded / e.total) * 100)
    }
  })
}
</script>

3.2 阿里云OSS集成

// utils/oss.js
import OSS from 'ali-oss'

export const ossClient = new OSS({
  region: 'oss-cn-shanghai',
  accessKeyId: import.meta.env.VITE_OSS_KEY,
  accessKeySecret: import.meta.env.VITE_OSS_SECRET,
  bucket: 'your-bucket'
})

// 前端直传示例
const uploadToOSS = async (file) => {
  const result = await ossClient.put(`uploads/${Date.now()}_${file.name}`, file)
  return result.url
}

四、今日任务:扩展项目功能

4.1 必做任务清单

  1. 角色权限系统
    • 添加登录页面(区分admin/user角色)
    • 实现路由守卫权限控制
    • 动态渲染导航菜单(根据角色显示不同功能)

  2. 分页功能
    • 为任务列表添加分页组件
    • 实现前后端分页切换功能(配置开关)
    • 添加页码跳转输入框

  3. 文件上传
    • 允许为任务添加附件
    • 实现上传进度显示
    • 限制文件类型为图片/PDF(最大10MB)

4.2 扩展挑战

// 大文件分片上传(断点续传)
const uploadChunk = async (file, chunkSize = 1024 * 1024) => {
  let chunkIndex = 0
  const chunks = Math.ceil(file.size / chunkSize)
  
  while (chunkIndex < chunks) {
    const start = chunkIndex * chunkSize
    const end = Math.min(file.size, start + chunkSize)
    const chunk = file.slice(start, end)
    
    await axios.post('/api/upload', {
      chunk,
      index: chunkIndex,
      total: chunks,
      fileHash: fileHash
    })
    
    chunkIndex++
  }
}

相关文章:

  • “Failed to Load SteamUI.dll” 错误详解:全面解析与高效解决方案,助你快速修复 Steam 客户端问题
  • React 18 并发更新的工作原理与实战应用
  • 【软件工程】06_软件设计
  • AI学习第二天--监督学习 半监督学习 无监督学习
  • Unitest和pytest区别
  • LeetCode[59]螺旋矩阵Ⅱ
  • K8S学习之基础三十五:k8s之Prometheus部署模式
  • 【算法题解答·七】哈希
  • 安科瑞分布式光伏监测系统:推动绿色能源高效发展
  • Word 小黑第26套
  • DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加导出数据功能
  • 痉挛性斜颈护理宝典:重拾生活平衡
  • Python数据可视化——生成数据(一)
  • LabVIEW 中的曲线拟合模型与方法概述
  • Windows Server中的NTP服务器部署(NTP Srver Deployment in Windows Server)
  • 考研专业课复习方法:如何高效记忆和理解?
  • stm32第五天按键的基础知识
  • 基于k3s部署Nginx、MySQL、PHP和Redis的详细教程
  • Useage of Generic in Java
  • 数据结构——树与二叉树
  • 杭州钱塘区3宗涉宅用地均以底价成交,共计成交金额25.73亿元
  • “11+2”复式票,宝山购彩者领走大乐透1170万头奖
  • 山东省市监局“你点我检”专项抽检:一批次“无抗”鸡蛋农兽药残留超标
  • 2025年上海科技节5月17日启动,56家重点实验室和大科学设施将向公众开放
  • 美国政府信用卡被设1美元限额,10美元采购花一两小时填表
  • A股高开高走:沪指涨0.82%,创指涨2.63%,超4100股收涨