【Vue2】基础知识汇总与实战指南

文章目录

一、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 生命周期流程图(核心阶段)

  1. 初始化阶段:beforeCreate → created → beforeMount → mounted

  2. 更新阶段:beforeUpdate → updated

  3. 销毁阶段: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>
相关推荐
czq_26867194876 小时前
Python打卡第46天
开发语言·python
卸任6 小时前
Vibe coding工具使用心得
前端·ai编程
brien96 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance7 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M7 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写7 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李7 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易7 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马7 小时前
前沿视界
前端
kyriewen7 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员