Vue 基础理论 & API 使用

Vue 基础理论 & API 使用

本文主要记录 Vue 的基础理论、核心概念与常用 API 使用方法,面向面试和日常开发参考。


原文地址

墨渊书肆/Vue 基础理论 & API 使用


Vue 简介

Vue 是一个渐进式 JavaScript 框架,由尤雨溪于 2014 年创建。Vue 核心库聚焦于视图层,易于学习和集成,同时能够驱动复杂的单页应用程序(SPA)开发。

核心特点:

  • 响应式数据绑定 (MVVM 模式)
  • 组件化开发
  • 虚拟 DOM
  • 指令系统
  • 渐进式架构

安装与项目创建

Vite(推荐)

bash 复制代码
# 创建 Vue3 项目
npm create vue@latest

# 或使用 Vite 直接创建
npm create vite@latest my-vue-app -- --template vue

Vue CLI

bash 复制代码
npm install -g @vue/cli
vue create my-project

基础指令

v-model 双向绑定

v-model 是 Vue 中用于表单输入和数据双向绑定的核心指令,本质是 v-bind + v-on 的语法糖。

基本用法:

html 复制代码
<input v-model="message">
<p>{{ message }}</p>

修饰符:

修饰符 说明
.lazy 在 change 事件时更新,而非 input
.number 自动转换为数值
.trim 去除首尾空白

自定义 v-model(Vue 3.4+):

javascript 复制代码
// 子组件
defineProps(['modelValue'])
defineEmits(['update:modelValue'])

// 父组件
<MyInput v-model:title="title" />

v-if / v-show 条件渲染

特性 v-if v-show
DOM 操作 创建/销毁 display: none
初始渲染 惰性 立即渲染
切换性能 低 高
适用场景 很少切换 频繁切换
html 复制代码
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>C</div>

v-for 列表渲染

html 复制代码
<li v-for="(item, index) in items" :key="item.id">
  {{ index }} - {{ item.name }}
</li>

注意事项:

  • 必须使用 :key 绑定唯一标识
  • 不建议使用数组索引作为 key
  • Vue2 中 v-for 优先级高于 v-if,Vue3 中相反

v-bind / v-on 属性与事件

html 复制代码
<!-- 绑定属性 -->
<img :src="url">

<!-- 绑定多个属性 -->
<img v-bind="attrs">

<!-- 事件监听 -->
<button @click="handleClick">Click</button>

<!-- 事件修饰符 -->
<button @click.stop="handle">阻止冒泡</button>
<button @click.prevent="handle">阻止默认行为</button>

组件选项

data

组件的响应式数据源,必须返回纯对象:

javascript 复制代码
export default {
  data() {
    return {
      count: 0,
      user: { name: 'Vue' }
    }
  }
}

props

父子组件通信的重要方式,支持类型校验 和默认值:

javascript 复制代码
export default {
  props: {
    // 基础类型
    title: String,
    // 多个类型
    age: [Number, String],
    // 带默认值
    size: {
      type: String,
      default: 'medium'
    },
    // 必需
    id: {
      type: Number,
      required: true
    },
    // 自定义校验
    score: {
      validator: (value) => value >= 0 && value <= 100
    }
  }
}

Vue3 组合式 API:

javascript 复制代码
const props = defineProps({
  title: String,
  count: { type: Number, default: 0 }
})

computed 计算属性

缓存计算结果,只在依赖变化时重新计算:

javascript 复制代码
export default {
  data() { return { count: 1 } },
  computed: {
    // 只读
    doubled() { return this.count * 2 },
    // 可写
    plusOne: {
      get() { return this.count + 1 },
      set(val) { this.count = val - 1 }
    }
  }
}

methods 方法

处理业务逻辑,每次渲染都会重新创建:

javascript 复制代码
export default {
  methods: {
    handleClick() { /* ... */ }
  }
}

watch 监听器

监听数据变化并执行回调:

javascript 复制代码
export default {
  data() { return { count: 0 } },
  watch: {
    count(newVal, oldVal) {
      console.log(`变化: ${oldVal} → ${newVal}`)
    },
    // 深度监听
    'obj.data': {
      handler() { /* ... */ },
      deep: true
    },
    // 立即执行
    name: {
      handler() { /* ... */ },
      immediate: true
    }
  }
}

Composition API

Vue3 引入的组合式 API,提供了更灵活的逻辑组织方式。

ref / reactive 响应式

javascript 复制代码
import { ref, reactive } from 'vue'

// ref - 原始类型
const count = ref(0)
count.value++

// reactive - 对象
const state = reactive({
  user: { name: 'Vue' }
})
state.user.name = 'Vue3'

区别:

| 特性 | ref | reactive | | ----- -| ----- | ---------- | | 适用类型 | 任意类型 | 对象/数组 | | 访问方式 | .value | 直接属性 | | 重新赋值 | 响应式 | 替换整个对象 |

toRefs / toRef

将 reactive 对象解构为独立的 ref:

javascript 复制代码
import { reactive, toRefs } from 'vue'

const state = reactive({ name: 'Vue', age: 25 })
const { name, age } = toRefs(state)

// 或创建单个 ref
const nameRef = toRef(state, 'name')

computed() 计算属性

javascript 复制代码
import { ref, computed } from 'vue'

const count = ref(0)
const doubled = computed(() => count.value * 2)

watch / watchEffect

javascript 复制代码
import { ref, watch, watchEffect } from 'vue'

// watch - 显式监听
watch(count, (newVal, oldVal) => { /* ... */ })
watch(() => state.name, (newVal) => { /* ... */ })

// watchEffect - 自动收集依赖
watchEffect(() => {
  console.log(count.value) // 自动追踪
})

执行时机控制:

  • watch:默认同步执行
  • watchEffect:默认 pre(在组件更新前)
  • watchPostEffect:在组件更新后执行
  • watchSyncEffect:同步执行

生命周期钩子

javascript 复制代码
import { 
  onMounted, 
  onUpdated, 
  onUnmounted 
} from 'vue'

export default {
  setup() {
    onMounted(() => { console.log('mounted') })
    onUpdated(() => { console.log('updated') })
    onUnmounted(() => { console.log('unmounted') })
  }
}

组件通信

Props / $emit

javascript 复制代码
// 父组件
<Child :count="count" @update="handleUpdate" />

// 子组件
const props = defineProps({ count: Number })
const emit = defineEmits(['update'])
emit('update', props.count + 1)

Provide / Inject

祖先向后代跨级传值:

javascript 复制代码
// 祖先组件
provide('key', 'value')

// 后代组件
const value = inject('key')

响应式:

javascript 复制代码
// 祖先
const count = ref(0)
provide('count', count)

// 后代 - 修改会影响所有后代
const count = inject('count')

a t t r s / attrs / attrs/listeners

透传属性和事件:

html 复制代码
<!-- 透传所有 -->
<Child v-bind="$attrs" v-on="$listeners" />

Pinia 状态管理

Vue3 推荐的状态管理方案:

javascript 复制代码
import { defineStore } from 'pinia'

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

内置组件

Transition

为元素添加过渡动画:

html 复制代码
<Transition name="fade">
  <div v-if="show">Content</div>
</Transition>
css 复制代码
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

过渡类名:

  • v-enter-from / v-leave-from:起始状态
  • v-enter-active / v-leave-active:过渡中
  • v-enter-to / v-leave-to:结束状态

KeepAlive

缓存组件实例:

html 复制代码
<KeepAlive include="A,B" exclude="C">
  <component :is="current" />
</KeepAlive>

生命周期:

  • activated:激活时
  • deactivated:停用时

Teleport

渲染到指定 DOM 位置:

html 复制代码
<Teleport to="#modal-root">
  <div class="modal">Content</div>
</Teleport>

Suspense

处理异步组件(实验性):

html 复制代码
<Suspense>
  <template #default>
    <AsyncComponent />
  </template>
  <template #fallback>
    Loading...
  </template>
</Suspense>

生命周期

Options API

阶段 钩子 说明
初始化 beforeCreate 实例创建前
初始化 created 数据观测完成
挂载 beforeMount 模板编译完成
挂载 mounted DOM 挂载完成
更新 beforeUpdate 数据变化,DOM 未更新
更新 updated DOM 更新完成
销毁 beforeUnmount 实例销毁前
销毁 unmounted 实例已销毁

父子组件执行顺序

挂载:父 created → 子 created → 子 mounted → 父 mounted

更新:父 beforeUpdate → 子 beforeUpdate → 子 updated → 父 updated

销毁:父 beforeUnmount → 子 beforeUnmount → 子 unmounted → 父 unmounted


常用技巧

动态类名

html 复制代码
<div :class="{ active: isActive, 'text-center': isCenter }">
<div :class="[activeClass, errorClass]">

条件类名

html 复制代码
<div :class="[isActive && 'active']">

动态绑定 style

html 复制代码
<div :style="{ color: textColor, fontSize: fontSize + 'px' }">

函数式组件

javascript 复制代码
export default {
  functional: true,
  props: { msg: String },
  render(h, context) {
    return h('div', context.props.msg)
  }
}

异步组件

javascript 复制代码
import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent({
  loader: () => import('./Async.vue'),
  loadingComponent: Loading,
  errorComponent: Error,
  delay: 200,
  timeout: 3000
})

面试常见问题

1. v-model 的原理?

本质是 v-bind:value + @input 的语法糖,监听 input 事件并更新数据。

2. v-for 中 key 的作用?

帮助 Vue 识别节点身份,实现高效的 DOM 复用。推荐使用数据唯一 ID,避免使用数组索引。

3. computed 和 watch 的区别?

  • computed:计算属性,依赖变化自动计算,缓存结果
  • watch:监听器,监听数据变化,执行异步或复杂逻辑

4. Vue2 和 Vue3 的区别?

  • 响应式:Object.defineProperty → Proxy
  • API:Options API → Composition API
  • 多根节点:不支持 → 支持
  • 生命周期:beforeDestroy → beforeUnmount

5. 组件通信方式有哪些?

  • props / $emit:父子
  • provide / inject:祖先-后代
  • a t t r s / attrs / attrs/listeners:透传
  • 事件总线:兄弟/任意
  • Pinia/Vuex:全局状态

6. Vue 的响应式原理?

通过 Proxy/Object.defineProperty 劫持数据访问,在 getter 中收集依赖 ,setter 中触发更新。


总结

Vue 以其简洁的 API 和渐进式的设计理念,成为前端开发的主流框架。掌握 Vue 的基础理论、常用 API 以及组件通信方式,是 Vue 开发者的必备技能。Vue3 的 Composition API 提供了更现代化的开发范式,建议在实际项目中优先使用。

相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
A黄俊辉A3 天前
uniapp webview中实现 app和内嵌的H5双向通信
vue.js·json
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
晨米酱3 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
honkun63 天前
vue 表格组件 vxe-table 配置 ajax 请求自动加载数据与表单查询
vue.js·vxe-table
彧azz3 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试