系统、详细地梳理Vue2的核心重点知识,覆盖从基础语法到进阶应用的全流程,清晰呈现Vue2的核心体系和高频考点,方便巩固学习和实际开发。
一、Vue2核心基础
1. Vue2核心特性
- MVVM架构:Model(数据)→ ViewModel(Vue实例)→ View(视图),数据驱动视图,双向绑定,无需手动操作DOM。
- 渐进式框架:按需使用核心功能(仅渲染/加路由/加状态管理),不强制全套使用。
- 虚拟DOM:减少真实DOM操作,提升渲染性能。
- 指令系统:内置指令简化DOM操作,支持自定义指令。
- 组件化:复用UI和逻辑,降低代码耦合度。
2. 项目创建与入口
Vue2主流用Vue CLI创建,也支持CDN快速入门:
1 2 3 4 5 6 7 8
| npm install -g @vue/cli@4
vue create my-vue2-project
cd my-vue2-project npm run serve
|
CDN快速测试(新手入门):
1 2 3 4 5 6 7 8 9 10
| <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script> <div id="app">{{ message }}</div> <script> new Vue({ el: '#app', data: { message: 'Hello Vue2!' } }) </script>
|
入口文件(main.js):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store'
Vue.config.productionTip = false
new Vue({ el: '#app', router, store, render: h => h(App) })
|
3. 模板语法(Vue2核心)
Vue2模板语法是视图渲染的基础,分插值、指令、绑定三类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <template> <!-- 1. 文本插值({{}}) --> <div>{{ message }}</div> <!-- 表达式插值(仅单个表达式) --> <div>{{ count + 1 }}</div> <div>{{ isShow ? '显示' : '隐藏' }}</div> <!-- 2. 原始HTML(慎用,防XSS) --> <div v-html="htmlContent"></div> <!-- 3. 核心指令 --> <img :src="imgUrl"> <!-- v-bind缩写,单向绑定属性 --> <button @click="handleClick">点击</button> <!-- v-on缩写,绑定事件 --> <input v-model="username"> <!-- 双向绑定表单 --> <div v-if="isShow">条件渲染</div> <!-- 销毁/创建DOM --> <div v-show="isShow">条件显示</div> <!-- 切换display:none --> <li v-for="item in list" :key="item.id">{{ item.name }}</li> <!-- 列表渲染(必加key) --> </template> <script> export default { data() { return { message: 'Vue2模板', count: 0, isShow: true, htmlContent: '<h1>原始HTML</h1>', imgUrl: 'https://vuejs.org/images/logo.png', username: '', list: [{ id: 1, name: 'Vue2' }, { id: 2, name: 'Vue3' }] } }, methods: { handleClick() { console.log('点击事件') } } } </script>
|
v-model修饰符(高频):
1 2 3
| <input v-model.trim="username"> <!-- 去除首尾空格 --> <input v-model.number="age"> <!-- 转为数字 --> <input v-model.lazy="content"> <!-- 失焦后更新(默认input事件) -->
|
二、核心:Options API(选项式API)
Vue2的核心组织方式,通过不同选项划分功能,是必须掌握的核心:
1. 核心选项详解
(1)data:响应式数据
- 组件中必须是函数(返回对象),避免多个实例共享数据。
- 基于
Object.defineProperty实现响应式,存在局限性(需重点掌握)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <script> export default { data() { return { count: 0, list: [1,2,3], user: { name: '张三' } } }, mounted() { // ✅ 数组响应式更新(推荐变异方法) this.list.push(4) this.list.splice(0, 1) // ❌ 数组非响应式操作(下标赋值/改长度) this.list[0] = 100 // 无响应 this.list.length = 0 // 无响应 // 解决:Vue.set Vue.set(this.list, 0, 100) // ❌ 对象新增属性无响应 this.user.age = 20 // 无响应 // 解决:Vue.set 或 批量更新 Vue.set(this.user, 'age', 20) this.user = { ...this.user, age: 20 } } } </script>
|
(2)methods:方法
- 定义组件方法,
this指向Vue实例(禁止用箭头函数,会丢失this)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <template> <button @click="increment">+1</button> </template> <script> export default { data() { return { count: 0 } }, methods: { increment() { this.count++ this.logCount() // 调用其他方法 }, logCount() { console.log(this.count) } // ❌ 错误示例:箭头函数导致this指向错误 // increment: () => { this.count++ } } } </script>
|
(3)computed:计算属性
- 基于响应式数据派生,有缓存(依赖不变则不重新计算),替代复杂模板表达式。
- 支持getter/setter(默认仅getter)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <template> <div>{{ doubleCount }}</div> <input v-model="fullName"> </template> <script> export default { data() { return { count: 0, firstName: '张', lastName: '三' } }, computed: { // 只读计算属性 doubleCount() { return this.count * 2 }, // 可读写计算属性 fullName: { get() { return this.firstName + this.lastName }, set(val) { const [first, last] = val.split('') this.firstName = first this.lastName = last } } } } </script>
|
(4)watch:侦听器
- 监听响应式数据变化,执行副作用(请求、DOM操作),支持深度监听、立即执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <script> export default { data() { return { count: 0, user: { name: '张三', age: 20 } } }, watch: { // 基础类型监听 count(newVal, oldVal) { console.log(`count从${oldVal}变到${newVal}`) }, // 对象深度监听 user: { handler(newVal) { console.log('user变化:', newVal) }, deep: true, // 深度监听 immediate: true // 首次加载立即执行 }, // 监听对象单个属性 'user.name'(newName) { console.log('姓名变化:', newName) } } } </script>
|
2. 生命周期钩子(核心)
Vue2生命周期分4个阶段、8个核心钩子,是控制组件生命周期的关键:
| 钩子函数 |
执行时机 |
常用操作 |
| beforeCreate |
实例创建前,数据/方法未初始化 |
无(无法访问data、methods) |
| created |
实例创建后,数据/方法已初始化 |
异步请求(无需等待DOM)、初始化数据 |
| beforeMount |
挂载前,模板已编译 |
无(DOM未生成) |
| mounted |
挂载后,DOM已渲染 |
DOM操作、初始化第三方插件(如echarts) |
| beforeUpdate |
数据更新,DOM更新前 |
读取更新前的DOM状态 |
| updated |
DOM更新后 |
操作更新后的DOM(避免修改数据,防止死循环) |
| beforeDestroy |
组件销毁前 |
清理定时器、取消事件监听、销毁第三方插件 |
| destroyed |
组件销毁后 |
无(组件已销毁) |
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <script> export default { data() { return { timer: null } }, created() { console.log('实例创建完成,可访问data') }, mounted() { // 启动定时器 this.timer = setInterval(() => console.log('运行中'), 1000) }, beforeDestroy() { // 销毁前清理副作用(核心) clearInterval(this.timer) } } </script>
|
三、组件核心知识
1. 组件注册
- 全局注册:所有组件可用(适合通用组件,如按钮)。
- 局部注册:仅当前组件可用(适合业务组件,减少体积)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import Vue from 'vue' import MyButton from './components/MyButton.vue' Vue.component('MyButton', MyButton)
<template> <MyButton /> </template> <script> import MyButton from './MyButton.vue' export default { components: { MyButton } } </script>
|
2. 组件通信(Vue2核心重点)
| 方式 |
适用场景 |
实现要点 |
| props / $emit |
父子通信(最常用) |
props父传子(单向),$emit子传父(事件) |
| $parent / $children |
父子直接访问 |
$parent访问父实例,$children访问子实例数组 |
| $refs |
父访问子DOM/方法 |
子组件加ref,通过this.$refs.xxx访问 |
| eventBus |
任意组件(小型项目) |
新建Vue实例作为总线,$on监听/$emit触发 |
| provide / inject |
跨层级(祖孙) |
父provide提供,子孙inject注入 |
| Vuex |
全局状态(大型项目) |
统一管理共享数据 |
(1)props / $emit(基础)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| // 父组件 <template> <Child :msg="parentMsg" @msg-change="handleChange" /> </template> <script> import Child from './Child.vue' export default { components: { Child }, data() { return { parentMsg: '父消息' } }, methods: { handleChange(newMsg) { this.parentMsg = newMsg } } } </script>
// 子组件 <template> <div>{{ msg }}</div> <button @click="sendMsg">发消息</button> </template> <script> export default { props: { // props验证(推荐) msg: { type: String, required: true, default: '默认值' } }, methods: { sendMsg() { this.$emit('msg-change', '子消息') // 触发父组件事件 } } } </script>
|
(2)eventBus(任意组件通信)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import Vue from 'vue' export default new Vue()
<script> import bus from './bus.js' export default { methods: { send() { bus.$emit('data-change', { name: '张三' }) } } } </script>
<script> import bus from './bus.js' export default { mounted() { this.listener = bus.$on('data-change', (data) => { console.log('接收:', data) }) }, beforeDestroy() { bus.$off('data-change', this.listener) } } </script>
|
3. 插槽(Slots)
用于组件内容分发,分默认插槽、具名插槽、作用域插槽:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| // 子组件 <template> <div> <slot>默认内容</slot> <!-- 默认插槽 --> <slot name="header"></slot> <!-- 具名插槽 --> <slot name="item" :data="list"></slot> <!-- 作用域插槽 --> </div> </template> <script> export default { data() { return { list: [1,2,3] } } } </script>
// 父组件 <template> <Child> <div>默认插槽内容</div> <template v-slot:header> <!-- 具名插槽(Vue2.6+) --> <h1>头部</h1> </template> <template v-slot:item="slotProps"> <!-- 作用域插槽 --> <div>{{ slotProps.data }}</div> </template> </Child> </template>
|
四、响应式原理(底层核心)
Vue2响应式基于Object.defineProperty实现,是面试高频考点:
- 初始化:遍历
data所有属性,用Object.defineProperty重定义getter/setter。
- 依赖收集:访问属性触发
getter,将当前Watcher(视图更新函数)收集到Dep(依赖容器)。
- 派发更新:修改属性触发
setter,通知Dep中的Watcher执行更新,重新渲染视图。
核心局限性:
- 无法监听数组下标赋值、修改长度(如
this.list[0] = 100)。
- 无法监听对象新增/删除属性(如
this.user.age = 20)。
- 解决方案:
Vue.set(target, key, value) 或数组变异方法(push/splice等)。
五、状态管理:Vuex 3(Vue2官方)
用于管理全局共享状态,核心5个概念:
1. 核心配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)
export default new Vuex.Store({ state: { count: 0 }, mutations: { INCREMENT(state, payload) { state.count += payload || 1 } }, actions: { incrementAsync({ commit }, payload) { setTimeout(() => commit('INCREMENT', payload), 1000) } }, getters: { doubleCount: state => state.count * 2 }, modules: { user: { namespaced: true, state: { name: '张三' }, mutations: { UPDATE_NAME(state, name) { state.name = name } } } } })
|
2. 组件中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <script> import { mapState, mapMutations, mapActions, mapGetters } from 'vuex' export default { computed: { ...mapState(['count']), // 映射state ...mapGetters(['doubleCount']) // 映射getters }, methods: { ...mapMutations(['INCREMENT']), // 映射mutation ...mapActions(['incrementAsync']), // 映射action updateName() { this.$store.commit('user/UPDATE_NAME', '李四') // 模块化调用 } }, mounted() { this.INCREMENT(2) this.incrementAsync(3) } } </script>
|
六、路由:Vue Router 3(Vue2适配)
1. 核心配置
1
| npm install vue-router@3
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import Vue from 'vue' import Router from 'vue-router' import Home from '@/views/Home.vue'
Vue.use(Router)
export default new Router({ mode: 'history', routes: [ { path: '/', name: 'Home', component: Home }, { path: '/user/:id', name: 'User', component: () => import('@/views/User.vue') }, { path: '*', component: () => import('@/views/404.vue') } ] })
|
2. 路由使用与守卫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <template> <router-link to="/">首页</router-link> <!-- 声明式导航 --> <router-link :to="{ name: 'User', params: { id: 1 } }">用户</router-link> <router-view /> <!-- 路由出口 --> </template> <script> export default { mounted() { // 编程式导航 this.$router.push('/user/2') // 获取路由参数 console.log(this.$route.params.id) // 路由守卫(全局) this.$router.beforeEach((to, from, next) => { // 登录验证 const isLogin = localStorage.getItem('token') if (to.path === '/admin' && !isLogin) { next('/login') } else { next() } }) } } </script>
|
七、Vue2常见优化
- v-for加唯一key:避免用index,提升列表更新性能。
- v-for与v-if分离:将v-if提至父节点,避免无效遍历。
- 计算属性缓存:替代复杂模板表达式,减少重复计算。
- 异步组件:拆分大型组件,按需加载,降低首屏体积。
- 防抖节流:处理高频事件(如输入框搜索、滚动)。
- 清理副作用:定时器、事件监听需在beforeDestroy销毁。
总结
- 核心架构:Vue2基于Options API组织代码,
data(响应式)、computed(缓存)、watch(侦听)、methods(方法)是基础,需掌握各选项的用法和区别。
- 响应式:基于
Object.defineProperty实现,需掌握其局限性(数组/对象操作)及解决方案(Vue.set)。
- 组件通信:
props/$emit是基础,eventBus适合小型项目,Vuex适合大型项目全局状态管理。
- 生态核心:Vuex 3管理全局状态,Vue Router 3处理路由,需掌握核心配置和使用方式。
- 生命周期:
mounted用于DOM操作,beforeDestroy用于清理副作用,是组件开发的关键节点。