Code前端首页关于Code前端联系我们

Vue.js 从入门到实战,这些高频问题帮你少踩坑

terry 16小时前 阅读数 100 #SEO
文章标签 js高频问题

Vue.js 是什么,适合哪些场景?

Vue 是一套用于构建用户界面的渐进式 JavaScript 框架。“渐进式”意味着它能按需集成:简单页面用 CDN 引入写几个组件就能跑;复杂项目用 CLI/Vite 搭工程化架构,再结合路由、状态管理形成完整生态。

和 React、Angular 比,Vue 更轻量化,API 友好易上手;React 侧重函数式编程和生态灵活性,Angular 偏向企业级重型框架。

Vue 适合的场景特别广:中小型前端项目快速迭代(比如后台管理系统、官网);需要强交互的页面(电商购物车、表单验证);甚至能和原生 App 结合做 Hybrid 开发(借助 Weex 等方案),要是你想快速出效果,又不想被框架过度约束,Vue 是稳选。

怎么快速搭建第一个 Vue 项目?

想跑通第一个 Vue demo,有三种常见方式,难度从低到高:

CDN 快速体验

不用装任何工具,新建 HTML 文件,引入 CDN 链接就能写代码:

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>  
<div id="app">{{ message }}</div>  
<script>  
  const { createApp } = Vue  
  createApp({  
    data() { return { message: 'Hello Vue!' } }  
  }).mount('#app')  
</script>  

保存后用浏览器打开,页面会渲染出 Hello Vue!,适合体验基础语法。

Vue CLI 构建工程化项目

如果电脑装了 Node.js(建议 v14+),打开终端执行:

npm install -g @vue/cli  
vue create my-vue-project  

跟着命令行提示选预设(比如默认 Vue 3),等依赖装完后,进入项目目录 cd my-vue-project,再跑 npm run serve,浏览器访问 http://localhost:8080 就能看到默认项目模板,这种方式适合需要 Webpack 配置、插件生态的中大型项目。

Vite 极速启动(推荐 Vue 3 项目)

Vite 是 Vue 作者尤雨溪开发的前端工具,启动和热更新比 CLI 快很多,终端执行:

npm create vite@latest my-vite-project -- --template vue  
cd my-vite-project  
npm install  
npm run dev  

访问 http://localhost:5173 就能看到项目,Vite 更适合追求开发效率、想用 Vue 3 最新特性的项目,现在很多新项目都优先选它。

响应式数据原理是啥,日常开发怎么用?

Vue 能自动更新页面,核心靠响应式系统——数据变了,页面自动跟着变。

原理层面(Vue 2 vs Vue 3)

  • Vue 2 用 Object.defineProperty 拦截对象属性的读取和修改(getter/setter),但对数组下标、对象新增属性监测不友好,得用 $set 这类 API 手动触发更新。
  • Vue 3 换成 Proxy,能直接监听整个对象,数组、对象新增属性都能自动响应,还支持 Map、Set 这些复杂数据结构,性能和灵活性都更强。

日常开发怎么用?

写组件时,data 里返回的对象、ref/reactive 包裹的变量都是响应式的,举个例子:

<script setup>  
import { ref, computed } from 'vue'  
const count = ref(0) // ref 让基本类型变响应式  
const double = computed(() => count.value * 2) // 计算属性自动依赖追踪  
function increment() {  
  count.value++ // 修改响应式数据,页面自动更新  
}  
</script>  
<template>  
  <button @click="increment">{{ count }} → {{ double }}</button>  
</template>  

watch 能监听数据变化做异步操作(比如接口请求);watchEffect 会自动收集依赖,适合处理副作用,要注意:Vue 2 里直接修改数组下标(如 arr[0] = 1)不触发更新,Vue 3 用 Proxy 就没这问题,所以新项目优先用 Vue 3 更省心。

组件化开发要注意哪些关键点?

组件化是 Vue 开发的核心——把页面拆成小组件,维护起来更轻松,这几个点要重点关注:

组件的定义与复用

单文件组件(.vue 文件),一个组件包含 <template>(结构)、<script>(逻辑)、<style>(样式),比如写个 <Button> 组件,多处复用按钮样式和逻辑,减少重复代码。

Props 与 Emits:父子通信

父组件给子组件传数据用 props,子组件触发父组件方法用 emits,示例:

<!-- 子组件 Button.vue -->  
<script setup>  
const props = defineProps(['label'])  
const emit = defineEmits(['click'])  
</script>  
<template><button @click="emit('click')">{{ label }}</button></template>  
<!-- 父组件 -->  
<script setup>  
function handleClick() { console.log('按钮被点了') }  
</script>  
<template><Button label="提交" @click="handleClick" /></template>  

Props 要注意类型验证(defineProps({ label: String })),避免传错数据类型。

插槽(Slot):内容分发

想让组件更灵活(比如弹窗的标题、内容由父组件决定),用插槽,分默认插槽、具名插槽、作用域插槽,示例具名插槽

<!-- 子组件 Modal.vue -->  
<template>  
  <div class="modal">  
    <header><slot name="title">默认标题</slot></header>  
    <main><slot>默认内容</slot></main>  
  </div>  
</template>  
<!-- 父组件使用 -->  
<template>  
  <Modal>  
    <template #title><h1>自定义标题</h1></template>  
    <p>这是自定义内容</p>  
  </Modal>  
</template>  

跨组件通信(非父子)

兄弟组件、隔多层的组件通信,可选方案:

  • Provide / Inject:祖先组件用 provide 提供数据,后代组件用 inject 接收,适合深层嵌套场景。
  • 事件总线(Event Bus):Vue 2 常用,Vue 3 可自己实现(比如用 mitt 库),但项目大了容易乱,不如用状态管理。
  • Pinia / Vuex:全局状态管理(后面单独讲)。

Vue Router 怎么上手,路由守卫有啥用?

单页应用(SPA)要实现页面跳转,得用路由工具 Vue Router。

基础配置(以 Vue 3 + Vue Router 4 为例)

先装依赖 npm install vue-router,然后新建 router/index.js

import { createRouter, createWebHistory } from 'vue-router'  
import Home from '../views/Home.vue'  
import About from '../views/About.vue'  
const routes = [  
  { path: '/', name: 'Home', component: Home },  
  { path: '/about', name: 'About', component: About },  
  { 
    path: '/user/:id', 
    name: 'User', 
    component: () => import('../views/User.vue') // 动态路由 + 懒加载 
  }  
]  
const router = createRouter({  
  history: createWebHistory(),  
  routes  
})  
export default router  

然后在主入口 main.js 里注册路由:

import { createApp } from 'vue'  
import App from './App.vue'  
import router from './router'  
createApp(App).use(router).mount('#app')  

页面里用 <router-link to="/">首页</router-link> 跳转,<router-view> 显示匹配的组件。

路由守卫(导航守卫)

跳转前、后做权限判断、加载动画、埋点等,常用的有:

  • 全局守卫router.beforeEach((to, from, next) => { ... }),每次路由跳转前触发,比如判断用户是否登录,没登录跳登录页:
    router.beforeEach((to, from) => {  
      if (to.meta.requiresAuth && !isLogin()) {  
        return { name: 'Login' } // 没登录跳登录页  
      }  
    })  
  • 组件内守卫onBeforeRouteEnteronBeforeRouteUpdateonBeforeRouteLeave(Vue 3 组合式 API),在组件里写更内聚。
  • 独享守卫:在路由配置里加 beforeEnter,只对当前路由生效。

Vuex/Pinia 状态管理该选哪个,怎么用?

当组件间共享数据(比如用户信息、购物车),用状态管理库更高效。

Vuex vs Pinia:怎么选?

  • Vuex 是 Vue 官方传统状态管理,分 statemutations(同步)、actions(异步)、getters,适合 Vue 2 项目或大型团队严格流程,但写法繁琐,TS 支持一般。
  • Pinia 是 Vue 官方推荐的新一代状态管理,API 更简洁,天生支持 TS,去掉了 mutations,只有 stategettersactions,体积更小,Vue 3 项目优先选它。

Pinia 快速上手

装依赖 npm install pinia,在 main.js 注册:

import { createApp } from 'vue'  
import { createPinia } from 'pinia'  
import App from './App.vue'  
const app = createApp(App)  
app.use(createPinia())  
app.mount('#app')  

新建 stores/counter.js

import { defineStore } from 'pinia'  
export const useCounterStore = defineStore('counter', {  
  state: () => ({ count: 0 }),  
  getters: {  
    double: (state) => state.count * 2  
  },  
  actions: {  
    increment() { this.count++ }  
  }  
})  

组件里使用:

<script setup>  
import { useCounterStore } from '../stores/counter'  
const store = useCounterStore()  
</script>  
<template>{{ store.count }} → {{ store.double }} <button @click="store.increment">+</button></template>  

异步操作直接在 actions 里写 async 函数(比如请求接口更新 state),比 Vuex 简洁太多。

Vue 3 新特性(Composition API)怎么学?

Vue 3 推出的 Composition API(组合式 API),和之前的 Options API(选项式)并行,解决了大型组件逻辑分散、复用难的问题。

核心语法:setup 与响应式 API

<script setup> 语法糖(推荐),不用写 export default,更简洁,响应式 API 包括:

  • ref:处理基本类型(string/number/boolean),访问要 .value,模板里不用。
  • reactive:处理对象/数组,返回 Proxy 代理对象,深度响应式。
  • computedwatchwatchEffect:功能和之前一致,用法更灵活。

示例:

<script setup>  
import { ref, reactive, computed, watch } from 'vue'  
// 基本类型响应式  
const count = ref(0)  
// 对象响应式  
const user = reactive({ name: '小明', age: 18 })  
// 计算属性  
const isAdult = computed(() => user.age >= 18)  
// 监听  
watch(count, (newVal) => { console.log('count 变了:', newVal) })  
watchEffect(() => { console.log('user 变化时触发:', user.name) })  
function increment() {  
  count.value++  
  user.age++  
}  
</script>  
<template>{{ count }} | {{ user.name }} {{ isAdult ? '成年' : '未成年' }}</template>  

生命周期钩子

组合式 API 里的钩子要导入,onMountedonUpdated,和 Options API 的生命周期对应:

<script setup>  
import { onMounted } from 'vue'  
onMounted(() => {  
  console.log('组件挂载完成,请求接口')  
})  
</script>  

自定义 Hook:逻辑复用

把重复逻辑抽成自定义 Hook,比如封装接口请求:

// hooks/useFetch.js  
import { ref, onMounted } from 'vue'  
export function useFetch(url) {  
  const data = ref(null)  
  const error = ref(null)  
  onMounted(async () => {  
    try {  
      const res = await fetch(url)  
      data.value = await res.json()  
    } catch (e) {  
      error.value = e  
    }  
  })  
  return { data, error }  
}  
// 组件里用  
<script setup>  
import { useFetch } from '../hooks/useFetch'  
const { data, error } = useFetch('https://api.example.com/data')  
</script>  

这种方式比 Options API 的 mixin 更清晰,不会有命名冲突,逻辑溯源更简单。

项目开发中遇到性能问题怎么优化?

Vue 项目越做越大,难免遇到加载慢、渲染卡,这些优化技巧能救命:

路由懒加载

不用把所有组件打包到一个 JS 文件,用动态 import 拆分代码:

{ path: '/about', component: () => import('../views/About.vue') }  

访问 /about 时才加载对应的 JS,首屏加载更快。

Keep-Alive 缓存组件

列表页→详情页→返回列表,用 <keep-alive> 缓存列表组件实例,避免重复请求和渲染:

<router-view v-slot="{ Component }">  
  <keep-alive>  
    <component :is="Component" />  
  </keep-alive>  
</router-view>  

虚拟列表(长列表优化)

渲染 thousands 条数据时,DOM 太多会卡死,用虚拟列表只渲染可视区域的 DOM,可以用 vue-virtual-scroller 库,原理是计算滚动位置,动态替换显示的列表项。

减少不必要的响应式

有些数据不需要响应式(比如纯展示的静态数据),用 shallowRef(浅响应式,只监听 .value 的变化)、markRaw(标记对象永远不是响应式):

import { shallowRef, markRaw } from 'vue'  
const staticData = markRaw({ list: [1,2,3] }) // 永远不响应式  
const shallowData = shallowRef({ count: 0 }) // 只有.count 变化才触发更新  

打包优化

  • 用 Vite 的话,默认 Tree Shaking 很高效,去掉没用到的代码。
  • 第三方库用 CDN 加速(比如把 axios、element-plus 放到 index.html 的 CDN 链接,vite.config.js 里配置 external)。
  • 压缩图片、开启 gzip(服务器配置或 Vite 插件)。

UI 组件库(Element Plus、Ant Design Vue)怎么选和用?

做后台管理系统、表单页面,直接用 UI 组件库能省大量时间,主流选择:

Element Plus

原 Element UI 的 Vue 3 版本,组件丰富(表格、表单、弹窗等),文档友好,中文社区活跃,适合中后台项目。按需引入能减小打包体积:

// vite.config.js 配置按需引入  
import { defineConfig } from 'vite'  
import AutoImport from 'unplugin-auto-import/vite'  
import Components from 'unplugin-vue-components/vite'  
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'  
export default defineConfig({  
  plugins: [  
    AutoImport({ resolvers: [ElementPlusResolver()] }),  
    Components({ resolvers: [ElementPlusResolver()] })  
  ]  
})  

然后直接用组件:<el-button>按钮</el-button>,不用手动 import

Ant Design Vue

阿里系的 UI 库,设计风格更现代,组件功能强大(ProTable 带查询表单),TS 支持好,适合对设计和扩展性要求高的项目,用法类似,也支持按需引入。

选择建议

团队熟悉 Element 就选 Element Plus;喜欢 Ant Design 风格或需要更复杂的企业级组件(比如流程设计、可视化)选 Ant Design Vue,小项目也可以用 Naive UI(轻量、TS 优先)、Vuetify(Material Design 风格)等。

测试和部署 Vue 项目要注意什么?

项目开发完,得测试稳了再上线,部署也有讲究:

测试:单元测试 + E2E 测试

  • 单元测试:测组件、函数逻辑,用 Vue Test Utils + Jest/Vitest,比如测 Button 组件的点击事件:

    import { mount } from '@vue/test-utils'  
    import Button from '../Button.vue'  
    test('Button click emits event', () => {  
      const wrapper = mount(Button,

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

热门