Vue.js 零基础全面教程
一、Vue 简介
Vue.js(读音 /vjuː/,类似于 view)是一个用于构建用户界面的渐进式 JavaScript 框架,由尤雨溪于2014年创建,目前最新稳定版本是 Vue 3.x 系列。Vue 的核心库只关注视图层,易于上手,也便于与其他库或已有项目整合。
主要特点详解:
-
响应式数据绑定:
- 采用Object.defineProperty(Vue2)或Proxy(Vue3)实现数据劫持
- 数据变化时自动更新DOM,无需手动操作
- 示例:当修改app.message的值时,页面会自动更新显示
-
组件化开发:
- 将UI拆分为独立可复用的组件
- 每个组件包含自己的HTML、CSS和JavaScript
- 支持单文件组件(SFC)形式:.vue文件
-
轻量高效:
- 核心库压缩后仅23KB(gzipped)
- 虚拟DOM实现高效更新
- 对比React(45KB)和Angular(65KB)更轻量
-
易学易用:
- 最低学习曲线,只需HTML+JS基础
- 详细中文文档
- 渐进式框架,可按需采用功能
<!-- 基础示例详解 -->
<div id="app">
<!-- 插值表达式:显示data中的message值 -->
{{ message }}
<!-- 可包含简单JS表达式 -->
{{ message.split('').reverse().join('') }}
</div>
<script>
// 创建Vue实例
const app = new Vue({
el: '#app', // 指定挂载的DOM元素
data: { // 定义响应式数据
message: 'Hello Vue!'
},
// 可选的生命周期钩子
created() {
console.log('实例已创建')
}
})
</script>
二、核心概念详解
1. 模板语法深入
Vue使用基于HTML的模板语法,允许开发者声明式地将DOM绑定至底层Vue实例的数据。Vue的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM的系统。
插值:
- 文本插值:
{{ }}
- 一次性插值:
v-once
只渲染一次 - 原始HTML:
v-html
指令
指令:
- 前缀
v-
表示是Vue提供的特殊属性 - 预期值为单个JavaScript表达式(
v-for
除外) - 部分指令可接收参数,用
:
表示
<p v-text="msg"></p> <!-- 等同于{{msg}} -->
<p v-html="rawHtml"></p> <!-- 解析HTML标签 -->
<!-- 动态参数 -->
<a v-bind:[attributeName]="url">链接</a>
<button v-on:[eventName]="doSomething">按钮</button>
2. 指令系统详解
指令 | 作用 | 详细说明 | 示例 |
---|---|---|---|
v-bind | 动态绑定属性 | 可简写为: | :class="{active: isActive}" |
v-on | 绑定事件 | 可简写为@ | @click.stop="handleClick" |
v-model | 表单双向绑定 | 修饰符:.lazy 、.number 、.trim | v-model.trim="text" |
v-if/v-show | 条件渲染 | v-if销毁元素,v-show切换display | v-if="isVIP" |
v-for | 列表渲染 | 必须使用:key | v-for="(item,index) in list" |
v-model实现原理:
<input :value="text" @input="text = $event.target.value">
3. 计算属性与侦听器深入
计算属性:
- 基于依赖缓存,只有相关依赖改变才重新计算
- 适用于复杂逻辑运算
- 默认getter,也可提供setter
侦听器:
- 适合执行异步操作
- 可以监听数据变化执行回调
- deep选项可深度监听对象变化
computed: {
// 全名计算属性
fullName() {
return this.firstName + ' ' + this.lastName
},
// 带setter的计算属性
computedMsg: {
get() { return this.message + '!' },
set(val) { this.message = val.replace('!', '') }
}
},
watch: {
// 监听firstName变化
firstName(newVal) {
console.log('firstName changed:', newVal)
},
// 深度监听对象
user: {
handler(newVal) { /*...*/ },
deep: true,
immediate: true
}
}
4. 组件系统详解
Vue组件是可复用的Vue实例,具有以下特点:
- 有自己的模板、逻辑和样式
- 可以接收props,触发事件
- 提供插槽(slot)机制进行内容分发
// 全局组件注册
Vue.component('button-counter', {
data() {
return { count: 0 }
},
template: `
<button @click="count++">
点击了 {{ count }} 次
</button>
`
})
// 局部组件
const TodoItem = {
props: {
// 带验证的prop
title: {
type: String,
required: true,
validator: value => value.length > 0
}
},
template: '<li>{{ title }}</li>'
}
// 使用组件
new Vue({
components: { TodoItem }
})
三、生命周期钩子详解
Vue实例从创建到销毁的完整生命周期:
-
初始化阶段:
beforeCreate
:数据观测和事件配置之前created
:实例创建完成,可访问data/methods
-
挂载阶段:
beforeMount
:模板编译完成但未挂载到DOMmounted
:实例挂载到DOM,可以访问$el
-
更新阶段:
beforeUpdate
:数据变化,DOM更新前updated
:DOM重新渲染后
-
销毁阶段:
beforeDestroy
:实例销毁前,可清理定时器destroyed
:实例销毁,所有绑定解除
new Vue({
data: { msg: 'Hello' },
beforeCreate() {
console.log('数据还未初始化') // undefined
},
created() {
console.log('可以访问data:', this.msg) // 'Hello'
},
mounted() {
console.log('DOM已挂载') // 可操作DOM
},
beforeUpdate() {
console.log('数据即将更新')
},
updated() {
console.log('DOM已更新')
},
beforeDestroy() {
console.log('即将销毁')
}
})
四、组件通信全面方案
1. 父 → 子通信:Props
<!-- 父组件 -->
<child-component
:title="parentTitle"
:user="userData"
@update="handleUpdate">
</child-component>
<!-- 子组件 -->
<script>
export default {
props: {
title: String,
user: {
type: Object,
default: () => ({})
}
}
}
</script>
2. 子 → 父通信:$emit
// 子组件
methods: {
submitForm() {
this.$emit('form-submit', formData)
}
}
// 父组件
<child-component @form-submit="handleSubmit"></child-component>
3. 兄弟组件通信:Event Bus
// eventBus.js
import Vue from 'vue'
export const EventBus = new Vue()
// 组件A
EventBus.$emit('message', 'Hello')
// 组件B
EventBus.$on('message', msg => {
console.log(msg) // 'Hello'
})
4. 跨级组件通信:provide/inject
// 祖先组件
provide() {
return {
theme: this.theme
}
}
// 子孙组件
inject: ['theme']
5. Vuex状态管理
// store.js
export default new Vuex.Store({
state: { count: 0 },
mutations: {
increment(state) {
state.count++
}
},
actions: {
incrementAsync({ commit }) {
setTimeout(() => commit('increment'), 1000)
}
}
})
五、Vue CLI脚手架详解
安装与创建项目
npm install -g @vue/cli # 全局安装Vue CLI
vue --version # 查看版本
vue create my-project # 创建新项目
# 项目启动
cd my-project
npm run serve
目录结构详解
my-project/
├── public/ # 静态资源目录
│ ├── index.html # 主HTML文件
│ └── favicon.ico # 网站图标
├── src/ # 源代码目录
│ ├── assets/ # 静态资源(图片/字体等)
│ ├── components/ # 公共组件
│ ├── views/ # 页面级组件
│ ├── router/ # 路由配置
│ ├── store/ # Vuex状态管理
│ ├── App.vue # 根组件
│ └── main.js # 应用入口文件
├── babel.config.js # Babel配置
├── package.json # 项目配置
└── vue.config.js # Vue项目配置
常用CLI命令
vue add router # 添加路由功能
vue add vuex # 添加状态管理
npm run build # 打包生产环境代码
npm run lint # 代码风格检查
六、进阶特性深度解析
1. 路由管理(Vue Router)
// router.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
Vue.use(Router)
export default new Router({
mode: 'history', // 去掉URL中的#
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: () => import('./views/About.vue') // 路由懒加载
},
{
path: '/user/:id',
component: User,
children: [ // 嵌套路由
{ path: 'profile', component: Profile }
]
}
]
})
2. 状态管理(Vuex)
// store.js
const store = new Vuex.Store({
state: {
todos: []
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
},
mutations: {
ADD_TODO(state, todo) {
state.todos.push(todo)
}
},
actions: {
addTodoAsync({ commit }, todo) {
setTimeout(() => {
commit('ADD_TODO', todo)
}, 1000)
}
},
modules: { // 模块化
user: {
state: { name: '' },
mutations: { SET_NAME(state, name) { state.name = name } }
}
}
})
3. 自定义指令实战
// 注册全局指令
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时...
inserted: function(el) {
el.focus() // 聚焦元素
}
})
// 注册局部指令
directives: {
pin: {
inserted(el, binding) {
el.style.position = 'fixed'
el.style[binding.arg || 'top'] = binding.value + 'px'
}
}
}
// 使用指令
<input v-focus>
<div v-pin:left="200">固定定位元素</div>
4. 过渡动画高级用法
<transition
name="fade"
@before-enter="beforeEnter"
@after-enter="afterEnter">
<p v-if="show">渐变内容</p>
</transition>
<script>
methods: {
beforeEnter(el) {
el.style.opacity = 0
el.style.transform = 'translateY(20px)'
},
afterEnter(el) {
// 动画完成回调
}
}
</script>
<style>
.fade-enter-active, .fade-leave-active {
transition: all 0.5s ease;
}
.fade-enter, .fade-leave-to {
opacity: 0;
transform: translateY(20px);
}
</style>
七、最佳实践指南
组件设计原则
-
单一职责原则:
- 每个组件只做一件事
- 组件文件不超过400行代码
-
组件分类:
- 展示组件(UI组件):只接收props和emit事件
- 容器组件:处理业务逻辑和数据
-
命名规范:
- 组件名:PascalCase (如UserProfile)
- 事件名:kebab-case (如user-submitted)
性能优化策略
-
列表渲染优化:
<!-- 必须使用唯一key --> <li v-for="item in items" :key="item.id">{{ item.text }}</li>
-
计算属性缓存:
- 复杂计算使用computed而非methods
- 避免在模板中使用复杂表达式
-
懒加载:
// 路由懒加载 component: () => import('./views/About.vue') // 组件懒加载 components: { MyComponent: () => import('./MyComponent.vue') }
-
其他优化:
- 频繁切换时用v-show替代v-if
- 大数据列表使用虚拟滚动(vue-virtual-scroller)
- 合理使用keep-alive缓存组件
代码规范建议
- 组件结构:
<template>
<!-- 模板 -->
</template>
<script>
export default {
name: 'MyComponent',
props: {},
data() { return {} },
computed: {},
methods: {}
}
</script>
<style scoped>
/* 组件样式 */
</style>
- Prop定义:
props: {
status: {
type: String,
required: true,
validator: value => ['success', 'warning', 'danger'].includes(value)
},
items: {
type: Array,
default: () => []
}
}
- 风格指南:
- 组件选项顺序:name > props > data > computed > watch > lifecycle > methods
- 多属性元素分行写
- 模板使用2空格缩进
八、学习路径与资源推荐
系统学习路线
-
基础阶段(1-2周):
- 模板语法、指令系统
- 组件基础、生命周期
- 表单处理、计算属性
-
中级阶段(2-4周):
- Vue Router
- Vuex状态管理
- 组件深度通信
- 自定义指令/过滤器
-
高级阶段(1-2月):
- 源码解析
- 自定义渲染器
- 插件开发
- 性能优化
优质学习资源
-
官方文档:
-
在线课程:
- Vue Mastery (付费)
- 慕课网《Vue.js高级实战》
- B站《Vue3全家桶实战》
-
开源项目:
- Vue Element Admin
- Nuxt.js (Vue SSR框架)
- Vuetify (Material UI框架)
实战项目建议
-
基础项目:
- Todo List (基础功能)
- 个人博客 (Vue + Markdown)
- 天气应用 (API调用)
-
中级项目:
- 电商网站 (商品展示、购物车)
- 后台管理系统 (权限控制)
- 即时聊天应用 (WebSocket)
-
高级项目:
- 微前端架构应用
- SSR渲染项目
- 可视化数据大屏
通过系统学习和项目实践,一般2-3周可掌握基础开发,1-2个月可达中级水平,3-6个月可进阶高级开发。建议从简单项目开始,逐步深入复杂场景。