Vue3 手绘风爆款实用笔记合集(含避坑+实战+API)

49 阅读4分钟

Vue3 手绘风爆款实用笔记合集(含避坑+实战+API)

✏️ 开篇说明 🎨

合集主打「爆款实用」,每篇聚焦1个Vue3高频需求,随手记、轻松学,核心知识点+极简可复制示例,新手友好、进阶可用,有错欢迎指出来~

📌 第一篇:Vue3 新手必看避坑指南(90%的人都踩过!)

新手学Vue3,最容易栽在细节上!这篇汇总高频坑点,附解决方案,帮你少走弯路、快速上手~

一、响应式数据踩坑(最高频!)

坑1:ref在JS里忘加.value


<script setup>
import { ref } from 'vue'
const count = ref(0)

// ❌ 错误:JS里操作ref忘了加.value,数据不更新
const add = () => {
  count++ 
}

// ✅ 正确:JS里必须加.value,模板里不用
const add = () => {
  count.value++ 
}
</script>

坑2:reactive绑简单类型无效


<script setup>
import { reactive } from 'vue'

// ❌ 错误:reactive只能绑对象/数组,简单类型无效
const count = reactive(0) // 不会触发响应式更新

// ✅ 正确:简单类型用ref,或包成对象用reactive
const count = ref(0)
// 或
const data = reactive({ count: 0 })
</script>

坑3:解构reactive数据丢失响应式


<script setup>
import { reactive } from 'vue'
const user = reactive({ name: '手绘君', age: 20 })

// ❌ 错误:解构后的数据不是响应式的
const { name } = user
name = '新名字' // 页面不更新

// ✅ 正确:用toRefs解构,保留响应式
import { reactive, toRefs } from 'vue'
const { name } = toRefs(user)
name.value = '新名字' // 正常更新
</script>

二、组件相关避坑

坑4:

🚨 重点:


<script setup>
import { ref } from 'vue'
const count = ref(0)

// ❌ 错误:setup语法糖里没有this
const add = () => {
  this.count.value++ 
}

// ✅ 正确:直接用变量名
const add = () => {
  count.value++ 
}
</script>

坑5:组件传值忘了defineProps/defineEmits


<!-- 子组件 ❌ 错误示例 -->
<script setup>
// 忘了defineProps,直接用props会报错
console.log(props.msg)

// 忘了defineEmits,直接emit会报错
emit('change')
</script>

<!-- 子组件 ✅ 正确示例 -->
<script setup>
// 父传子:defineProps声明
const props = defineProps({
  msg: String
})

// 子传父:defineEmits声明
const emit = defineEmits(['change'])
const send = () => {
  emit('change', '子组件消息')
}
</script>

三、其他高频避坑

  • 🚨 坑6:Vue3移除了filter,用computed替代

  • 🚨 坑7:v-model绑定reactive对象,不用加.value(模板里)

  • 🚨 坑8:onMounted等生命周期,不用写在methods里,直接在setup里调用

💡 小总结:新手避坑核心——记住ref/reative用法、setup语法糖无this、传值需声明!

📌 第二篇:Pinia 极简实战笔记(Vue3状态管理首选)

Vue3官方推荐用Pinia替代Vuex,更轻量、更简洁、不用配置modules,新手也能快速上手,这篇吃透核心用法~

一、快速上手(3步搞定)

1. 安装Pinia


# npm安装
npm install pinia
# yarn安装
yarn add pinia

2. 全局注册Pinia(main.js)

// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia' // 引入Pinia
import App from './App.vue'

const app = createApp(App)
app.use(createPinia()) // 注册Pinia
app.mount('#app')

3. 创建Store(核心文件)

在src目录下新建store文件夹,创建index.js(或单独创建userStore.js),用defineStore定义仓库。


// src/store/index.js
import { defineStore } from 'pinia'

// 第一个参数:仓库名(唯一,不能重复)
// 第二个参数:配置对象(state/actions/getters)
export const useUserStore = defineStore('user', {
  // 状态(类似Vue2的data)
  state: () => ({
    name: '手绘君',
    age: 20,
    isLogin: false
  }),
  // 方法(类似Vue2的methods,可修改state)
  actions: {
    // 修改单个状态
    setName(newName) {
      this.name = newName // 这里的this指向state,不用.value!
    },
    // 修改多个状态
    login(userInfo) {
      this.name = userInfo.name
      this.isLogin = true
    }
  },
  // 计算属性(类似Vue2的computed)
  getters: {
    // 简单计算
    doubleAge() {
      return this.age * 2
    },
    // 带参数的计算(返回一个函数)
    getAgeAdd(n) {
      return this.age + n
    }
  }
})

二、组件中使用Store


<script setup>
// 1. 引入创建好的Store
import { useUserStore } from '@/store'

// 2. 实例化Store
const userStore = useUserStore()

// 3. 使用state(3种方式)
console.log(userStore.name) // 方式1:直接使用
console.log(userStore.$state.age) // 方式2:通过$state访问

// 4. 调用actions(直接调用,不用dispatch!)
userStore.setName('新名字')
userStore.login({ name: '测试君' })

// 5. 使用getters(直接调用,不用加括号,带参数除外)
console.log(userStore.doubleAge) // 40
console.log(userStore.getAgeAdd(5)) // 25

// 6. 重置state(一键恢复初始值)
const reset = () => {
  userStore.$reset()
}
</script>

<template>
  <div>
    <p>姓名:{{ userStore.name }}</p>
    <p>年龄:{{ userStore.age }}</p>
    <p>年龄翻倍:{{ userStore.doubleAge }}</p>
    <button @click="userStore.setName('小明')">修改姓名</button>
  </div>
</template>

三、核心优势(为什么用Pinia?)

  • ✅ 无需配置modules:一个文件就是一个仓库,不用嵌套

  • ✅ 不用commit/mutations:直接在actions里修改state,更简洁

  • ✅ TypeScript友好:自动推导类型,不用手动声明

  • ✅ 体积小:仅1KB左右,比Vuex轻量很多

  • ✅ 支持热更新:修改Store不用重启项目

💡 小总结:Pinia用法=定义仓库+实例化+直接使用,新手无脑冲就对了!

📌 第三篇:Vue Router 4 实战手册(Vue3配套路由)

Vue3配套Vue Router 4,单页面应用(SPA)必备,这篇覆盖路由核心用法:路由配置、跳转、传参、守卫,极简示例可直接复制!

一、快速上手(4步搞定)

1. 安装Vue Router 4


# 注意:Vue3必须装vue-router@4版本
npm install vue-router@4
yarn add vue-router@4

2. 创建路由配置文件

src目录下新建router文件夹,创建index.js:


// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'

// 1. 引入组件(两种方式)
// 方式1:普通引入(适合首页、高频组件)
import Home from '@/views/Home.vue'
// 方式2:懒加载(适合非首页,优化性能)
const About = () => import('@/views/About.vue')

// 2. 路由规则配置
const routes = [
  // 首页路由
  {
    path: '/', // 路由路径(url地址)
    name: 'Home', // 路由名称(唯一)
    component: Home, // 对应组件
    meta: {
      title: '首页', // 页面标题(可自定义)
      requireAuth: false // 是否需要登录(自定义)
    }
  },
  // 关于页路由
  {
    path: '/about',
    name: 'About',
    component: About,
    meta: { title: '关于我们' }
  },
  // 动态路由(参数传递)
  {
    path: '/user/:id', // :id是动态参数
    name: 'User',
    component: () => import('@/views/User.vue'),
    meta: { title: '用户中心' }
  },
  // 404路由(匹配所有未定义路由)
  {
    path: '/:pathMatch(.*)*', // 匹配所有路径
    name: 'NotFound',
    component: () => import('@/views/NotFound.vue'),
    meta: { title: '页面不存在' }
  }
]

// 3. 创建路由实例
const router = createRouter({
  history: createWebHistory(), // 哈希模式用createWebHashHistory()
  routes // 传入路由规则
})

// 4. 导出路由
export default router

3. 全局注册路由(main.js)


// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 引入路由

const app = createApp(App)
app.use(router) // 注册路由
app.mount('#app')

4. 配置路由出口(App.vue)


<template>
  &lt;div id="app"&gt;
    <!-- 路由导航(类似a标签) -->
    <nav>
      <router-link to="/">首页</router-link>
      <router-link to="/about">关于我们</router-link>
      <router-link :to="{ name: 'User', params: { id: 123 } }"&gt;用户中心&lt;/router-link&gt;
    &lt;/nav&gt;
    
    <!-- 路由出口:匹配的组件会渲染到这里 -->
    <router-view></router-view>
  </div>
</template>

二、核心用法(高频刚需)

1. 路由跳转(3种方式)


<script setup>
import { useRouter, useRoute } from 'vue-router'

// 实例化路由
const router = useRouter() // 用于跳转
const route = useRoute() // 用于获取路由信息

// 方式1:router-link(模板中使用,最简洁)
// <router-link to="/home">首页</router-link>

// 方式2:编程式跳转(JS中使用)
const goHome = () => {
  router.push('/home') // 直接传路径
  // 或传对象(推荐,可传参数)
  router.push({
    name: 'Home', // 用路由名称跳转(更稳定)
    query: { name: '手绘君' } // 拼接在url上的参数
  })
}

// 方式3:替换当前路由(不会留下历史记录,适合登录页)
const goLogin = () => {
  router.replace('/login')
}

// 后退/前进
const goBack = () => {
  router.back() // 后退
  // router.forward() // 前进
}
</script>

2. 路由传参(2种方式)

方式1:query传参(url拼接,类似get请求)

// 跳转页:传参
router.push({
  name: 'About',
  query: { id: 1, msg: '测试' }
})
// url会变成:/about?id=1&msg=测试

// 接收页:获取参数
const route = useRoute()
console.log(route.query.id) // 1
console.log(route.query.msg) // 测试
方式2:params传参(动态路由,url不拼接,类似post请求)
// 1. 先配置动态路由(router/index.js)
{
  path: '/user/:id', // :id是动态参数
  name: 'User',
  component: User
}

// 2. 跳转页:传参
router.push({
  name: 'User', // 必须用name跳转,不能用path
  params: { id: 123, name: '手绘君' }
})

// 3. 接收页:获取参数
const route = useRoute()
console.log(route.params.id) // 123
console.log(route.params.name) // 手绘君

3. 路由守卫(权限控制核心)

以全局前置守卫为例(登录拦截),其他守卫用法类似:

// router/index.js
router.beforeEach((to, from, next) => {
  // to:要跳转到的路由
  // from:从哪个路由跳转过来
  // next:放行/跳转的函数

  // 1. 设置页面标题
  document.title = to.meta.title || 'Vue3笔记'

  // 2. 登录拦截(只有登录才能访问/user路由)
  const isLogin = localStorage.getItem('isLogin') // 模拟登录状态
  if (to.name === 'User' && !isLogin) {
    // 未登录,跳转到登录页
    next('/login')
  } else {
    // 已登录/无需登录,放行
    next()
  }
})

💡 小总结:路由核心=配置路由+跳转+传参+守卫,掌握这4点,满足90%的项目需求!

📌 第四篇:Vue3 组件封装实战(新手也能学会)

组件封装是Vue3的核心优势,能大幅提高代码复用率、简化开发,这篇以3个高频组件(按钮、输入框、弹窗)为例,教你从零封装可复用组件!

一、封装核心原则

  • ✅ 单一职责:一个组件只做一件事(比如按钮组件只负责按钮展示和点击)

  • ✅ 可复用:通过props传参,适配不同场景

  • ✅ 可扩展:通过slot插槽,支持自定义内容

  • ✅ 易维护:代码简洁,注释清晰,逻辑分离

二、实战1:封装通用按钮组件(Btn.vue)


<!-- src/components/Btn.vue -->
<template>
  <button 
    class="custom-btn"
    :class="['btn-' + type, { 'btn-disabled': disabled }]"
    @click="handleClick"
    :disabled="disabled"
  &gt;
    <!-- 插槽:自定义按钮内容 -->
    <slot>默认按钮</slot>
  </button>
</template>

<script setup>
// 1. 接收父组件传参(props)
const props = defineProps({
  // 按钮类型(primary/success/danger/default)
  type: {
    type: String,
    default: 'default' // 默认值
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  }
})

// 2. 子传父:点击事件
const emit = defineEmits(['click'])
const handleClick = () => {
  // 禁用状态下不触发事件
  if (!props.disabled) {
    emit('click')
  }
}
</script>

<style scoped>
.custom-btn {
  padding: 6px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
}
/* 不同类型按钮样式 */
.btn-default {
  background: #f5f5f5;
  color: #333;
}
.btn-primary {
  background: #42b983; /* Vue绿 */
  color: #fff;
}
.btn-success {
  background: #67c23a;
  color: #fff;
}
.btn-danger {
  background: #f56c6c;
  color: #fff;
}
/* 禁用样式 */
.btn-disabled {
  cursor: not-allowed;
  opacity: 0.6;
}
</style>

组件使用示例


<template>
  <div>
    <Btn @click="handleClick">默认按钮</Btn>
    <Btn type="primary" @click="handleClick">主要按钮</Btn>
    <Btn type="success" @click="handleClick">成功按钮</Btn>
    <Btn type="danger" disabled>禁用按钮</Btn>
    <!-- 插槽自定义内容 -->
    <Btn type="primary">
      <i class="icon">✓</i> 带图标按钮
    </Btn>
  </div>
</template>

<script setup>
import Btn from '@/components/Btn.vue'

const handleClick = () => {
  console.log('按钮被点击了')
}
</script>

三、实战2:封装通用输入框组件(Input.vue)


<!-- src/components/Input.vue -->
<template>
  &lt;div class="custom-input"&gt;
    <!-- 标签插槽 -->
    <label class="input-label" v-if="label">{{ label }}</label>
    <input
      class="input-content"
      :type="type"
      :placeholder="placeholder"
      :value="modelValue"
      @input="handleInput"
      :disabled="disabled"
    />
  </div>
</template>

<script setup>
// 1. 接收父组件传参
const props = defineProps({
  // 输入框类型(text/password/number)
  type: {
    type: String,
    default: 'text'
  },
  // 占位提示
  placeholder: {
    type: String,
    default: ''
  },
  // 绑定值(v-model)
  modelValue: {
    type: [String, Number],
    default: ''
  },
  // 标签文本
  label: {
    type: String,
    default: ''
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  }
})

// 2. 子传父:同步输入值(配合v-model使用)
const emit = defineEmits(['update:modelValue'])
const handleInput = (e) => {
  emit('update:modelValue', e.target.value)
}
</script>

<style scoped>
.custom-input {
  display: flex;
  align-items: center;
  margin: 10px 0;
}
.input-label {
  width: 80px;
  font-size: 14px;
  margin-right: 10px;
}
.input-content {
  padding: 6px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
  width: 200px;
}
.input-content:disabled {
  background: #f5f5f5;
  cursor: not-allowed;
}
</style>

组件使用示例(v-model绑定)


<template>
  <div>
    <Input 
      label="用户名" 
      placeholder="请输入用户名" 
      v-model="username"
    />
    <Input 
      label="密码" 
      type="password" 
      placeholder="请输入密码" 
      v-model="password"
    />
    <Input 
      label="手机号" 
      type="number" 
      placeholder="请输入手机号" 
      v-model="phone"
      disabled
    />
  </div>
</template>

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

const username = ref('')
const password = ref('')
const phone = ref('13800138000')
</script>

四、实战3:封装通用弹窗组件(Modal.vue)


<!-- src/components/Modal.vue -->
<template>
  <div class="modal-mask" v-if="visible" @click="handleMaskClick">
    &lt;div class="modal-content" @click.stop&gt;
      <!-- 弹窗标题 -->
      <div class="modal-header">
        <h3 class="modal-title">{{ title }}</h3>
        <button class="modal-close" @click="handleClose">×</button>
      </div>
      <!-- 弹窗内容(插槽,自定义) -->
      <div class="modal-body">
        <slot>默认弹窗内容</slot>
      </div&gt;
      <!-- 弹窗底部(插槽,自定义按钮) -->
      <div class="modal-footer">
        <slot name="footer">
          <Btn @click="handleClose">取消</Btn>
          <Btn type="primary" @click="handleConfirm">确认</Btn>
        </slot>
      </div>
    </div>
  </div>
</template>

<script setup>
import Btn from './Btn.vue' // 引入之前封装的按钮组件

// 接收父组件传参
const props = defineProps({
  // 是否显示弹窗
  visible: {
    type: Boolean,
    default: false
  },
  // 弹窗标题
  title: {
    type: String,
    default: '提示'
  },
  // 点击遮罩是否关闭
  maskClose: {
    type: Boolean,
    default: true
  }
})

// 子传父:关闭、确认事件
const emit = defineEmits(['close', 'confirm'])
// 关闭弹窗
const handleClose = () => {
  emit('close')
}
// 确认按钮
const handleConfirm = () => {
  emit('confirm')
}
// 点击遮罩关闭
const handleMaskClick = () => {
  if (props.maskClose) {
    emit('close')
  }
}
</script>

<style scoped>
/* 遮罩层 */
.modal-mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 999;
}
/* 弹窗内容 */
.modal-content {
  width: 400px;
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
}
/* 弹窗标题 */
.modal-header {
  padding: 16px;
  border-bottom: 1px solid #eee;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.modal-title {
  font-size: 16px;
  margin: 0;
}
.modal-close {
  border: none;
  background: none;
  font-size: 20px;
  cursor: pointer;
  color: #999;
}
/* 弹窗内容 */
.modal-body {
  padding: 20px;
  font-size: 14px;
}
/* 弹窗底部 */
.modal-footer {
  padding: 16px;
  border-top: 1px solid #eee;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
</style>

组件使用示例


<template>
  <div>
    <Btn type="primary" @click="showModal = true">打开弹窗</Btn>
    
    <Modal
      :visible="showModal"
      title="提示弹窗"
      :mask-close="false"
      @close="showModal = false"
      @confirm="handleConfirm"
    >
      <!-- 自定义弹窗内容 -->
      <p>确定要执行这个操作吗?</p>
      <Input placeholder="请输入备注" v-model="remark" />
      <!-- 自定义底部按钮(覆盖默认) -->
      <template #footer>
        <Btn @click="showModal = false">取消</Btn>
        <Btn type="danger" @click="handleDelete">删除</Btn>
        <Btn type="primary" @click="handleConfirm">确认</Btn>
      </template>
    </Modal>
  </div>
</template>

<script setup>
import Modal from '@/components/Modal.vue'
import Input from '@/components/Input.vue'
import Btn from '@/components/Btn.vue'
import { ref } from 'vue'

const showModal = ref(false)
const remark = ref('')

const handleConfirm = () => {
  console.log('确认操作,备注:', remark.value)
  showModal.value = false
}

const handleDelete = () => {
  console.log('执行删除操作')
  showModal.value = false
}
</script>

💡 小总结:组件封装=props传参+slot插槽+emit传事件,掌握这三点,能封装任何你需要的组件!

📌 第五篇:Vue3+Vite 优化实战(打包提速+页面优化)

Vue3+Vite 本身就比Vue2+Webpack快,但项目变大后仍会出现打包慢、页面卡顿,这篇汇总5个高频优化技巧,新手也能轻松操作,直接提升项目性能!

一、Vite 基础优化(打包提速)

1. 优化依赖预构建

Vite会预构建依赖,减少打包时间,修改vite.config.js配置,指定预构建的依赖:


// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  // 优化依赖预构建
  optimizeDeps: {
    // 强制预构建的依赖(高频使用的第三方库)
    include: ['vue', 'vue-router', 'pinia', 'axios'],
    // 排除不需要预构建的依赖
    exclude: ['lodash-es']
  }
})

2. 打包压缩优化(减小体积)

安装压缩插件,打包时自动压缩JS/CSS/HTML,减小文件体积,提升加载速度:


# 安装压缩插件
npm install vite-plugin-compression --save-dev

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import compression from 'vite-plugin-compression'

export default defineConfig({
  plugins: [
    vue(),
    // 打包压缩(gzip格式)
    compression({
      algorithm: 'gzip', // 压缩算法
      threshold: 10240, // 超过10KB的文件才压缩
      deleteOriginFile: false // 不删除原文件
    })
  ]
})

二、代码层面优化(页面提速)

1. 组件懒加载(路由懒加载)

之前路由配置中提到的懒加载,是最核心的优化技巧,减少首页加载时间:


// router/index.js
// ❌ 错误:全部引入,首页加载慢
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'

// ✅ 正确:懒加载,只有访问时才加载组件
const Home = () => import('@/views/Home.vue')
const About = () => import('@/views/About.vue')

// 进阶:分块打包(相同模块打包到一个文件)
const User = () => import(/* webpackChunkName: "user" */ '@/views/User.vue')
const UserInfo = () => import(/* webpackChunkName: "user" */ '@/views/UserInfo.vue')

2. 图片优化(减小图片体积)

Vite自带图片处理,配合插件优化图片,支持webp格式(体积更小):


# 安装图片优化插件
npm install vite-plugin-imagemin --save-dev

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import imagemin from 'vite-plugin-imagemin'

export default defineConfig({
  plugins: [
    vue(),
    // 图片优化
    imagemin({
      gifsicle: {
        optimizationLevel: 7, // gif优化等级
        interlaced: false
      },
      optipng: {
        optimizationLevel: 7 // png优化等级
      },
      mozjpeg: {
        quality: 80 // jpg质量(0-100)
      },
      pngquant: {
        quality: [0.8, 0.9], // png质量范围
        speed: 4
      },
      svgo: {
        plugins: [
          { name: 'removeViewBox' },
          { name: 'removeEmptyAttrs', active: false }
        ]
      }
    })
  ],
  // 配置图片路径,优化加载
  assetsInclude: ['**/*.png', '**/*.jpg', '**/*.webp'],
  build: {
    assetsInlineLimit: 4096 // 小于4KB的图片转base64,减少请求
  }
})

3. 减少不必要的响应式数据

Vue3的响应式会消耗性能,非响应式数据不用ref/reactive包裹:


<script setup>
import { ref, reactive } from 'vue'

// ✅ 正确:非响应式数据,直接定义(不会变化的数据)
const staticData = {
  name: '手绘君',
  age: 20
}

// ✅ 正确:响应式数据,用ref/reactive(会变化的数据)
const count = ref(0)
const user = reactive({
  name: '测试君'
})
</script>

4. 虚拟列表(长列表优化)

当列表数据超过1000条时,会出现卡顿,用虚拟列表只渲染可视区域的内容:


# 安装虚拟列表插件(vue3专用)
npm install vue-virtual-scroller@next --save

<template>
  <!-- 虚拟列表组件 -->
  <RecycleScroller
    class="scroller"
    :items="longList" // 长列表数据
    :item-size="50" // 每个列表项的高度
    key-field="id" // 唯一标识字段
  >
    <template #default="{ item }">
      <div class="list-item">{{ item.name }}</div>
    </template>
  </RecycleScroller>
</template>

<script setup>
import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'

// 模拟10000条长列表数据
const longList = Array.from({ length: 10000 }, (_, i) => ({
  id: i + 1,
  name: `列表项 ${i + 1}`
}))
</script>

<style scoped>
.scroller {
  height: 500px; // 必须设置固定高度
  width: 100%;
}
.list-item {
  height: 50px; // 和item-size一致
  line-height: 50px;
  border-bottom: 1px solid #eee;
}
</style>

三、优化总结

  • 🚀 打包优化:依赖预构建+压缩+图片优化,减小体积、提升打包速度

  • 🚀 页面优化:路由懒加载+虚拟列表,减少首页加载时间、解决长列表卡顿

  • 🚀 代码优化:减少不必要的响应式数据,降低性能消耗

💡 小技巧:优化后可以用 npm run build 查看打包体积,用浏览器开发者工具(Network)查看加载速度!

✏️ 合集持续更新ing,每篇都是爆款实用向,有错欢迎指出来~ 收藏起来,学Vue3不迷路!

(注:文档部分内容可能由 AI 生成)