文章目录
-
- [一、Vue2 入门准备](#一、Vue2 入门准备)
-
- [1.1 什么是 Vue2](#1.1 什么是 Vue2)
- [1.2 安装与环境搭建](#1.2 安装与环境搭建)
-
- [方式 1:CDN 引入(快速入门)](#方式 1:CDN 引入(快速入门))
- [方式 2:Vue-CLI 搭建项目(工程化开发)](#方式 2:Vue-CLI 搭建项目(工程化开发))
- [1.3 第一个 Vue 实例](#1.3 第一个 Vue 实例)
- 二、核心语法:模板与数据
-
- [2.1 模板语法](#2.1 模板语法)
-
- 插值语法(双大括号)
- [指令语法(v - 开头)](#指令语法(v - 开头))
- [2.2 数据绑定](#2.2 数据绑定)
- [2.3 事件处理](#2.3 事件处理)
- [2.4 条件与列表渲染](#2.4 条件与列表渲染)
-
- [条件渲染(v-if vs v-show)](#条件渲染(v-if vs v-show))
- 列表渲染(v-for)
- 三、组件系统:复用与通信
-
- [3.1 组件注册](#3.1 组件注册)
- [3.2 单文件组件(.vue)](#3.2 单文件组件(.vue))
- [3.3 组件通信](#3.3 组件通信)
-
- [1. 父传子(Props)](#1. 父传子(Props))
- [2. 子传父(emit)](#2. 子传父(emit))
- [3. 兄弟组件通信(事件总线)](#3. 兄弟组件通信(事件总线))
- 四、生命周期:实例的一生
-
- [4.1 生命周期流程图(核心阶段)](#4.1 生命周期流程图(核心阶段))
- [4.2 常用钩子函数](#4.2 常用钩子函数)
- 五、进阶特性:提升开发效率
-
- [5.1 计算属性(computed)](#5.1 计算属性(computed))
- [5.2 侦听器(watch)](#5.2 侦听器(watch))
- [5.3 过滤器(filter)](#5.3 过滤器(filter))
- [5.4 自定义指令](#5.4 自定义指令)
- 六、生态工具:路由与状态管理
- 七、避坑技巧与学习资源
-
- [7.1 常见坑点](#7.1 常见坑点)
-
- [1. 响应式数据问题](#1. 响应式数据问题)
- [2. v-for 与 v-if 混用](#2. v-for 与 v-if 混用)
一、Vue2 入门准备
1.1 什么是 Vue2
Vue2 是尤雨溪开发的渐进式 JavaScript 框架,专注于构建用户界面,具有以下特点:
-
遵循 MVVM 模式,实现数据与视图分离
-
编码简洁,体积小(生产版本约 33KB)
-
支持组件化开发,复用性强
-
借鉴 Angular 模板语法与 React 虚拟 DOM 技术
1.2 安装与环境搭建
方式 1:CDN 引入(快速入门)
javascript
<!-- 开发环境 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<!-- 生产环境(压缩版) -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
方式 2:Vue-CLI 搭建项目(工程化开发)
javascript
# 安装 Vue-CLI(需 Node.js 8.9+)
npm install -g @vue/cli@4.x
# 创建项目
vue create vue2-demo
# 运行项目
cd vue2-demo && npm run serve
1.3 第一个 Vue 实例
javascript
<div id="app">{{ message }}</div>
<script>
new Vue({
el: '#app',
data() {
return {
message: 'Hello Vue2!'
}
}
})
</script>
二、核心语法:模板与数据
2.1 模板语法
插值语法(双大括号)
用于解析标签体内容,支持 JS 表达式:
javascript
<div>
文本:{{ name }}
计算:{{ 1 + 1 }}
三元运算:{{ isShow ? '可见' : '隐藏' }}
</div>
指令语法(v - 开头)
用于操作标签属性、绑定事件等,部分指令可简写:
| 指令 | 简写 | 功能 |
|---|---|---|
| v-bind:attr | :attr | 单向数据绑定 |
| v-on:event | @event | 事件绑定 |
| v-model | - | 双向数据绑定 |
2.2 数据绑定
单向绑定(v-bind)
javascript
<!-- 绑定属性 -->
<img :src="imgUrl" :alt="imgTitle">
<!-- 绑定对象 -->
<div :class="{ active: isActive, disabled: isDisabled }"></div>
双向绑定(v-model)
仅适用于表单元素,本质是 v-bind:value + v-on:input 的语法糖:
javascript
<input v-model="username" placeholder="请输入用户名">
<script>
new Vue({
el: '#app',
data() {
return {
username: '' // 输入框内容实时同步到这里
}
}
})
</script>
2.3 事件处理
基础用法
javascript
<!-- 无参数 -->
<button @click="handleClick">点击</button>
<!-- 带参数 -->
<button @click="handleDelete(id)">删除</button>
<!-- 传递事件对象 -->
<button @click="handleEvent($event, id)">事件对象</button>
事件修饰符
javascript
<!-- 阻止默认行为(如表单提交) -->
<form @submit.prevent="handleSubmit"></form>
<!-- 停止事件冒泡 -->
<div @click.stop="handleParent">
<button @click="handleChild"></button>
</div>
<!-- 按键修饰符(按回车触发) -->
<input @keyup.enter="handleSearch">
2.4 条件与列表渲染
条件渲染(v-if vs v-show)
| 特性 | v-if | v-show |
|---|---|---|
| 原理 | 动态创建 / 销毁元素 | 控制 display 样式 |
| 切换成本 | 高 | 低 |
| 初始隐藏 | 不渲染元素 | 渲染元素(隐藏) |
| 适用场景 | 切换不频繁 | 频繁切换 |
javascript
<!-- v-if 系列 -->
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>C</div>
<!-- v-show -->
<div v-show="isVisible">可见/隐藏</div>
列表渲染(v-for)
javascript
<!-- 遍历数组 -->
<ul>
<li v-for="(item, index) in list" :key="item.id">
{{ index + 1 }}. {{ item.name }}
</li>
</ul>
<!-- 遍历对象 -->
<div v-for="(value, key) in user" :key="key">
{{ key }}: {{ value }}
</div>
注意:必须加
key属性(推荐唯一 ID),避免 DOM 复用导致的问题。
三、组件系统:复用与通信
3.1 组件注册
全局注册(全项目可用)
javascript
// 注册全局组件
Vue.component('my-button', {
template: '<button @click="handleClick">{{ text }}</button>',
props: ['text'],
methods: {
handleClick() {
this.$emit('btn-click') // 触发自定义事件
}
}
})
局部注册(仅当前组件可用)
javascript
// 导入组件
import MyButton from './MyButton.vue'
export default {
components: {
MyButton // 局部注册
}
}
3.2 单文件组件(.vue)
标准结构包含模板、脚本、样式三部分:
javascript
<template>
<div class="my-component">{{ msg }}</div>
</template>
<script>
export default {
name: 'MyComponent',
data() {
return {
msg: '单文件组件'
}
}
}
</script>
<style scoped>
/* scoped 表示样式仅作用于当前组件 */
.my-component {
color: #333;
}
</style>
3.3 组件通信
1. 父传子(Props)
javascript
<!-- 父组件 -->
<child :user="parentUser" :age="18"></child>
<!-- 子组件 -->
<script>
export default {
props: {
user: {
type: Object,
required: true
},
age: {
type: Number,
default: 0
}
}
}
</script>
2. 子传父($emit)
javascript
<!-- 子组件 -->
<template>
<button @click="sendData">传递数据</button>
</template>
<script>
export default {
methods: {
sendData() {
// 触发事件并传参
this.$emit('child-data', '子组件数据')
}
}
}
</script>
<!-- 父组件 -->
<child @child-data="handleChildData"></child>
<script>
export default {
methods: {
handleChildData(data) {
console.log('接收子组件数据:', data)
}
}
}
</script>
3. 兄弟组件通信(事件总线)
javascript
// 1. 全局创建事件总线
Vue.prototype.$bus = new Vue()
// 2. 发送方
this.$bus.$emit('brother-event', '兄弟数据')
// 3. 接收方(在 mounted 中监听)
mounted() {
this.$bus.$on('brother-event', (data) => {
console.log('接收兄弟数据:', data)
})
},
// 4. 销毁时移除监听
beforeDestroy() {
this.$bus.$off('brother-event')
}
四、生命周期:实例的一生
4.1 生命周期流程图(核心阶段)
-
初始化阶段:beforeCreate → created → beforeMount → mounted
-
更新阶段:beforeUpdate → updated
-
销毁阶段:beforeDestroy → destroyed
4.2 常用钩子函数
| 钩子函数 | 触发时机 | 常用操作 |
|---|---|---|
| created | 实例创建完成(数据观测完成) | 发送 Ajax 请求、初始化数据 |
| mounted | 实例挂载到 DOM 后 | 操作 DOM、初始化插件 |
| beforeDestroy | 实例销毁前 | 清除定时器、解绑事件 |
javascript
export default {
data() {
return {
timer: null
}
},
created() {
// 发送请求
this.fetchData()
},
mounted() {
// 启动定时器
this.timer = setInterval(() => {
console.log('定时器运行中')
}, 1000)
},
beforeDestroy() {
// 清除定时器
clearInterval(this.timer)
},
methods: {
fetchData() {
// 模拟 Ajax 请求
setTimeout(() => {
this.data = '请求结果'
}, 1000)
}
}
}
五、进阶特性:提升开发效率
5.1 计算属性(computed)
缓存计算结果,依赖数据变化时自动更新:
javascript
export default {
data() {
return {
firstName: '张',
lastName: '三'
}
},
computed: {
// 完整写法(可设置get/set)
fullName: {
get() {
return this.firstName + this.lastName
},
set(value) {
const arr = value.split(' ')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
}
5.2 侦听器(watch)
监听数据变化,执行异步或复杂操作:
javascript
export default {
data() {
return {
username: '',
suggestList: []
}
},
watch: {
// 监听 username 变化
username(newVal, oldVal) {
// 模拟搜索建议请求
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.fetchSuggest(newVal)
}, 500)
}
},
methods: {
fetchSuggest(keyword) {
// 发送请求获取建议列表
this.suggestList = ['建议1', '建议2']
}
}
}
5.3 过滤器(filter)
格式化数据显示,不改变原数据:
javascript
// 全局过滤器
Vue.filter('dateFormat', (value) => {
const date = new Date(value)
return `${date.getFullYear()}-${date.getMonth()+1}-${date.getDate()}`
})
// 局部过滤器
export default {
filters: {
moneyFormat(value) {
return '¥' + Number(value).toFixed(2)
}
}
}
javascript
<!-- 使用过滤器 -->
<div>{{ createTime | dateFormat }}</div>
<div>{{ price | moneyFormat }}</div>
5.4 自定义指令
javascript
// 全局指令:自动聚焦输入框
Vue.directive('focus', {
// 元素插入 DOM 时触发
inserted(el) {
el.focus()
}
})
// 局部指令:设置字体颜色
export default {
directives: {
color: {
// 绑定值更新时触发
update(el, binding) {
el.style.color = binding.value
}
}
}
}
javascript
<!-- 使用自定义指令 -->
<input v-focus>
<div v-color="textColor">自定义颜色</div>
六、生态工具:路由与状态管理
6.1 路由(vue-router 3.x)
安装与配置
javascript
# 安装
npm install vue-router@3.x --save
javascript
// router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
Vue.use(VueRouter)
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
const router = new VueRouter({
mode: 'history', // 去除 URL 中的 #
routes
})
export default router
路由使用
javascript
<!-- 路由链接 -->
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<!-- 路由出口(组件渲染位置) -->
<router-view></router-view>
<!-- 编程式导航 -->
<script>
export default {
methods: {
goAbout() {
this.$router.push('/about')
}
}
}
</script>
6.2 状态管理(Vuex 3.x)
核心概念
-
State:存储状态数据
-
Mutations:修改状态的唯一途径(同步操作)
-
Actions:处理异步操作,通过 mutations 修改状态
-
Getters:计算派生状态(类似 computed)
基本使用
javascript
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
// 异步增加计数
incrementAsync({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
},
getters: {
doubleCount(state) {
return state.count * 2
}
}
})
javascript
<!-- 组件中使用 -->
<template>
<div>
计数:{{ $store.state.count }}
双倍:{{ $store.getters.doubleCount }}
<button @click="handleIncrement">同步增加</button>
<button @click="handleIncrementAsync">异步增加</button>
</div>
</template>
<script>
export default {
methods: {
handleIncrement() {
this.$store.commit('increment')
},
handleIncrementAsync() {
this.$store.dispatch('incrementAsync')
}
}
}
</script>
七、避坑技巧与学习资源
7.1 常见坑点
1. 响应式数据问题
- 直接给对象添加新属性不会触发响应:
javascript
// 错误
this.user.age = 18
// 正确(使用 Vue.set 或重新赋值)
this.$set(this.user, 'age', 18)
- 数组直接修改索引不会触发响应:
javascript
// 错误
this.list[0] = '新值'
// 正确(使用数组方法)
this.list.splice(0, 1, '新值')
2. v-for 与 v-if 混用
不建议同时使用,可先用计算属性过滤数据:
javascript
computed: {
filteredList() {
return this.list.filter(item => item.isShow)
}
}
javascript
<!-- 推荐写法 -->
<li v-for="item in filteredList" :key="item.id">{{ item.name }}</li>