当前位置: 首页 > news >正文

vue需要学习的点

对MVVM的理解

MVVM 是 Model-View-ViewModel 的缩写

  • Model 代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑。
  • View 代表 UI 组件, 它负责将数据模型转化成 UI 展现出来。
  • ViewModel 监听模型数据的改变和控制视图行为 、处理用户交互, 简单理解就是⼀个同步View 和 Model 的对象, 连接 Model 和 View

这种架构下,开发者只需关注业务逻辑,不需要手动操作DOM,不需要关注数据状态的同步问题, 复杂的数据状态维护完全由 MVVM 来统⼀管理


常用vue命令

指令作用说明典型用法示例
v-text将元素的文本内容替换为表达式的值(替代 {{}}<p v-text="msg"></p>
v-html将元素的 innerHTML 更新为表达式的内容(会有 XSS 风险)<div v-html="rawHtml"></div>
v-show根据表达式的真假切换元素的 display CSS 属性实现显示隐藏<div v-show="isVisible"></div>
v-if条件渲染,表达式为真时渲染该元素,假时销毁元素(不占 DOM)<p v-if="show">显示内容</p>
v-elsev-if 的反向条件,必须紧接 v-if 或 v-else-if 之后<p v-else>隐藏内容</p>
v-else-ifv-if 的“else if”分支,用于链式条件判断<p v-else-if="otherCondition">内容</p>
v-for列表渲染,用于遍历数组或对象生成一组元素<li v-for="item in items" :key="item.id">{{ item.text }}</li>
v-bind动态绑定 HTML 属性或组件 prop,简写为 :<img :src="imgSrc">
v-on监听 DOM 事件或组件自定义事件,简写为 @<button @click="handleClick">点我</button>
v-model双向数据绑定,通常用于表单控件(input、select、textarea 等)<input v-model="username">
v-pre跳过该元素和子元素的编译,进行原样输出(提高性能,调试时用)<span v-pre>{{ rawMustache }}</span>
v-cloak保证 Vue 编译完成之后再显示元素,避免闪烁(通常配合 CSS 使用)<div v-cloak>内容</div>
v-once元素和组件只渲染一次,之后的更新不会渲染该元素<span v-once>{{ message }}</span>

如何自定义vue命令

项目Vue 2Vue 3
注册方式Vue.directive() / 组件内 directivesapp.directive() / 组件内 directives
生命周期钩子名称bindinsertedupdatecomponentUpdatedunbindcreatedbeforeMountmountedbeforeUpdateupdatedbeforeUnmountunmounted
生命周期更多钩子较少,只匹配关键阶段更细粒度,更符合组件生命周期
指令 API 对象格式vs Vue 3 类似,只是钩子不同同 Vue 2,但钩子名称改进
参数和修饰符支持 binding.valuebinding.argbinding.modifiers同 Vue 2

vue的生命周期

1. Vue 2 生命周期钩子

Vue 2 的生命周期可以分为四个阶段:

阶段钩子函数说明
创建阶段beforeCreate实例初始化时调用,数据观测和事件未初始化
created实例已创建,数据观测和事件已初始化
挂载阶段beforeMount挂载开始之前,相关 DOM 还未渲染
mounted挂载完成,DOM 已插入页面
更新阶段beforeUpdate数据更新后,DOM 重新渲染前调用
updated组件 DOM 重新渲染并更新后调用
销毁阶段beforeDestroy实例销毁前调用
destroyed实例销毁完成,解绑所有事件,清理资源

2. Vue 3 生命周期钩子

Vue 3 基于组合式 API 升级,仍保留选项式生命周期,同时对生命周期做了更多补充。整体钩子和 Vue 2 类似,具体列表:

阶段钩子函数说明
创建阶段beforeCreateVue 3 依然支持,但在组合式 API 不常用
created同上
挂载阶段beforeMount挂载开始之前
mounted挂载完成
更新阶段beforeUpdate数据更新前,DOM 渲染之前调用
updatedDOM 更新完成后调用
卸载阶段beforeUnmount实例卸载前调用(Vue 3 新增)
unmounted实例卸载后调用(Vue 3 新增)

3. Vue 3 组合式 API 中的生命周期钩子

Vue 3 新增了组合式 API(setup 函数),通过如下函数注册生命周期钩子:

生命周期阶段组合式 API 钩子函数说明
创建onBeforeMount(() => {})挂载之前
onMounted(() => {})挂载完成
更新onBeforeUpdate(() => {})更新之前
onUpdated(() => {})更新完成
卸载onBeforeUnmount(() => {})卸载之前
onUnmounted(() => {})卸载完成
激活和停用onActivated(() => {})keep-alive 组件激活
onDeactivated(() => {})keep-alive 组件停用

vue的响应式原理

1.vue2

        核心是依赖收集 + 发布订阅模式,使用 Object.defineProperty 对对象的属性进行 getter/setter 拦截。

function defineReactive(obj, key, val) {const dep = new Dep()Object.defineProperty(obj, key, {get() {if (Dep.target) { // Dep.target 指当前扫描的 watcherdep.addDep(Dep.target)}return val},set(newVal) {if (newVal !== val) {val = newValdep.notify() // 通知所有 watcher 更新}}})
}

限制和缺点:

  • 只能监听对象已有属性,新增新属性不会自动响应式(需要用 Vue.set)
  • 数组的变化通过变异方法(push、pop等)重写实现响应式
  • 只能监听到对象的一级属性,深层嵌套需要递归监听

2.vue3

        基于 ES6 的 Proxy 实现响应式。代理整个对象,拦截所有属性的访问/修改/删除,不需要递归每个子属性。原理:对目标对象做代理,所有访问通过 get、set 拦截完成。

function reactive(target) {return new Proxy(target, {get(target, key, receiver) {// 依赖收集track(target, key)return Reflect.get(target, key, receiver)},set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver)// 触发依赖trigger(target, key)return result}})
}

3.总结

方面Vue 2 (Object.defineProperty)Vue 3 (Proxy)
技术实现对对象属性逐个用 defineProperty 拦截用 Proxy 包裹整个对象进行拦截
支持新增/删除属性不支持,需要用 Vue.set天生支持
数组响应式通过重写数组变异方法实现数组作为对象代理自然支持
依赖收集粒度只能对属性做依赖收集基于操作符拦截,更精准,按需追踪
性能需要递归遍历,性能压力大性能更好,按需依赖追踪
实现复杂度需要递归遍历、手动处理数组简洁,统一代理所有操作

vue的diff算法

        Vue 基于虚拟 DOM 实现渲染,每次状态变化产生新 VNode 树,会通过 Diff 算法比较新旧 VNode 树的差异,根据差异调用最少的 DOM 操作,实现 DOM 最小化更新。

处理方式意义操作指针变化
旧前 vs 新前顺序未变,头部对比patch,指针+1oldStart++, newStart++
旧后 vs 新后顺序未变,尾部对比patch,指针-1oldEnd--, newEnd--
旧后 vs 新前右移节点至左patch + 移动旧尾节点oldEnd--, newStart++
旧前 vs 新后左移节点至右patch + 移动旧前节点oldStart++, newEnd--
其它(key查找)复用已有节点或新增节点移动或插入节点根据具体操作调整指针
新节点剩余新增节点创建新节点newStart++ 或 newEnd--
旧节点剩余删除多余节点删除节点oldStart++ 或 oldEnd--


vue的Optional API 和Composition API

1. Options API(选项式 API)

这是 Vue 2 以及 Vue 3 依然支持的传统写法,开发者通过预定义的组件选项(Options)来组织代码,比如 datamethodscomputedwatchprops 等。

特点:

  • 代码组织结构清晰,基于 Vue 约定的选项划分功能。
  • 易于初学者理解,适合小中型项目。
  • 组件逻辑往往按功能划分,但可能导致同一功能分散在多个选项内,随着组件变复杂难以维护。

示例代码

export default {data() {return {count: 0}},computed: {doubled() {return this.count * 2}},methods: {increment() {this.count++}},watch: {count(newVal, oldVal) {console.log('count changed:', newVal)}}
}

2. Composition API(组合式 API)

Vue 3 引入的新方式,开发者通过在 setup() 函数内使用函数调用和响应式 API(如 refreactivecomputedwatch 等)组合逻辑代码。

特点:

  • 逻辑复用和组合更灵活:可以把相关代码片段封装成可复用的函数(composables)。
  • 更适合大型项目和复杂组件,避免 Options API 中不同选项间逻辑分散问题。
  • 代码布局更灵活,方便按业务功能组织代码而非选项划分。
  • 需要了解一定的响应式原理,对初学者有一定门槛。
import { ref, computed, watch } from 'vue'export default {setup() {const count = ref(0)const doubled = computed(() => count.value * 2)function increment() {count.value++}watch(count, (newVal, oldVal) => {console.log('count changed:', newVal)})return {count,doubled,increment}}
}

vue中的逻辑复用

1. Options API 的逻辑复用方式及局限

主要手段
  • mixins(混入)
  • extends(继承)

这些机制允许把一段逻辑写在一个 mixin 对象或基类组件中,然后被多个组件复用。

// mixin.js
export const myMixin = {data() {return {count: 0}},methods: {increment() {this.count++}}
}
import { myMixin } from './mixin'export default {mixins: [myMixin],mounted() {this.increment()}
}
局限和问题
  • 命名冲突:不同 mixin 可能有相同的 data、methods、computed 名称,产生冲突难以管理。

  • 隐式依赖和状态来源混乱:mixin 里面有状态和方法,组件使用后状态来自何处不直观,增加理解和维护成本。

  • 逻辑难以拆分和组合:mixin 是扁平的配置,无法像函数那样灵活接收参数、返回结果、依赖注入。

  • 追踪调用关系困难:逻辑分散在多个 mixin,调试时难以跟踪和维护。

  • 扩展继承复杂度:使用 extends 形式继承 父组件逻辑时,继承链越长越复杂,状态管理困难。

2.Composition API 的逻辑复用 —— Composable 函数

核心思想
  • 将一块响应式逻辑封装到一个普通函数中(称为 composable 函数)
  • 函数内部使用 refreactivecomputedwatch 等 API
  • 通过返回对象暴露响应式数据和方法给调用组件使用
import { ref, computed } from 'vue'export function useCounter(initialValue = 0) {const count = ref(initialValue)const doubled = computed(() => count.value * 2)function increment() {count.value++}return {count,doubled,increment}
}
import { useCounter } from './useCounter'export default {setup() {const { count, doubled, increment } = useCounter(5)return {count,doubled,increment}}
}

Vue递归组件

<script setup>
import { defineProps } from 'vue'const props = defineProps({items: {type: Array,required: true}
})
</script><template><ul><li v-for="item in items" :key="item.id">{{ item.label }}<!-- 如果有子项,则递归调用自身 --><RecursiveMenu v-if="item.children && item.children.length" :items="item.children" /></li></ul>
</template><script>
import { defineComponent } from 'vue'export default defineComponent({name: 'RecursiveMenu'
})
</script>

vue异步组件

import { defineAsyncComponent } from 'vue'const AsyncComp = defineAsyncComponent({// 必须是返回 Promise 的函数loader: () => import('./YourComponent.vue'),// 加载超时时间,超过时展示错误组件timeout: 3000,// 组件加载时显示的占位组件loadingComponent: LoadingSpinner,// 加载失败时显示的错误组件errorComponent: ErrorComponent,// 重试次数(默认 0)retries: 1
})
<template><div><h2>异步组件示例</h2><AsyncComp /></div>
</template><script setup>
import { defineAsyncComponent } from 'vue'
import LoadingSpinner from './LoadingSpinner.vue'
import ErrorComponent from './ErrorComponent.vue'const AsyncComp = defineAsyncComponent({loader: () => import('./HeavyComponent.vue'),loadingComponent: LoadingSpinner,errorComponent: ErrorComponent,timeout: 5000
})
</script>

在vue2中

export default {components: {AsyncExample: () => import('./AsyncExample.vue')}
}

vue的keep-alive

  • keep-alive 是一个 Vue全局组件
  • keep-alive 本身不会渲染出来,也不会出现在父组件链中
  • keep-alive 包裹动态组件时,会缓存不活动的组件,而不是销毁它们

keep-alive 接收三个参数:

  • include :可传字符串、正则表达式、数组 ,名称匹配成功的组件会被缓存
  • exclude :可传字符串、正则表达式、数组 ,名称匹配成功的组件不会被缓存
  • max :可传数字 ,限制缓存组件的最大数量

include 和 exclude ,传数组 情况居多。

keep-alive 主要做了以下部分:

  • created :初始化一个 cache、keys ,前者用来存缓存组件的虚拟dom集合,后者用来存缓组件的key集合
  • mounted :实时监听 include、exclude 这两个的变化,并执行相应操作
  • destroyed :删除掉所有缓存相关的东西

使用场景:

<keep-alive :include="allowList" :exclude="noAllowList" :max="amount"><router-view></router-view>
</keep-alive>
<keep-alive :include="allowList" :exclude="noAllowList" :max="amount"><component :is="currentComponent"></component>
</keep-alive>

当组件被<keep-alive>包裹时,会触发两个额外的生命周期钩子:

activated
当被缓存的组件重新激活时调用。适用于需要重新触发数据更新或DOM操作的场景,例如恢复定时器或重新请求数据。

deactivated
当被缓存的组件失活时调用。适用于清理工作,例如清除定时器或取消未完成的请求。


vuex和pinia

1. Vuex

简介
  • Vuex 是 Vue 官方推出的状态管理库,面向 Vue 2 设计,也支持 Vue 3。
  • 强调集中式存储管理,所有组件的状态集中到 store 中,使用“单一状态树”。
  • 基于 Flux 架构,采用 mutations 进行状态同步修改,actions 处理异步逻辑。
核心概念
  • State(状态):集中维护的响应式数据。
  • Mutations:唯一修改 state 的方法,必须是同步函数。
  • Actions:处理异步逻辑,通过 commit 触发 mutations。
  • Getters:类似计算属性,对 state 数据进行包装和过滤。
  • Modules:当应用复杂时,支持模块化拆分 store。
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)const store = 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}}
})export default store

2. Pinia

简介
  • Pinia 是 Vue 官方推荐的新一代状态管理库,设计更简洁友好,完美支持 Vue 3 和 Composition API。
  • 语法更接近普通的模块化 JS,更灵活且易学,支持直接调用操作状态。
核心概念
  • Store 是一个组合式的状态容器。
  • 通过 defineStore 定义 store。
  • 支持直接修改 state(因为内部用 Proxy 劫持,状态依然响应式)。
  • 支持类似计算属性的 getters,以及内置 actions 处理异步和同步逻辑。
import { defineStore } from 'pinia'// 定义 store
export const useCounterStore = defineStore('counter', {state: () => ({ count: 0 }),getters: {doubleCount: (state) => state.count * 2},actions: {increment() {this.count++},incrementAsync() {setTimeout(() => {this.increment()}, 1000)}}
})
import { useCounterStore } from './stores/counter'export default {setup() {const counter = useCounterStore()counter.increment()return { counter }}
}

3.对比

特性/维度VuexPinia
API 设计需定义 state, mutations, actions定义 state、getters、actions,更简洁
异步处理通过 actions直接在 actions 中处理异步
使用便利性比较繁琐更现代,学习曲线低
TS 支持支持但复杂原生 TypeScript 支持友好
Vue 版本Vue 2/3 都支持主要面向 Vue 3,Vue 2 有社区支持
模块化支持模块拆分自然模块化,多个 store 独立管理
生态和社区成熟且庞大新兴且快速增长
功能支持完整、稳定轻量、现代、更灵活

vue-router

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'const routes = [{ path: '/', component: Home },{ path: '/about', component: About }
]const router = createRouter({history: createWebHistory(),  // 使用 HTML5 History 模式routes
})export default router
钩子函数触发时机是否可阻止导航是否可访问组件实例
beforeEach全局路由开始切换
beforeResolve导航流程最后阶段
afterEach导航完成
beforeEnter路由独享守卫
beforeRouteEnter进入路由组件之前通过 next 访问
beforeRouteUpdate路由参数变化,组件复用
beforeRouteLeave离开路由组件时
http://www.dtcms.com/a/544474.html

相关文章:

  • Kotlin保留小数位的三种方法
  • GXDE OS 25.2.1 更新了!引入 dtk6,修复系统 bug 若干
  • Java 反序列化中的 boolean vs Boolean 陷阱:一个真实的 Bug 修复案例
  • Kotlin 类和对象
  • 内核里常用宏BUG_ON/WARN_ON/WARN_ONCE
  • 中断编程概念
  • EG1151 四开关升降压电源管理芯片技术解析
  • 腾讯云做网站教程专门做三国战纪的网站叫什么意思
  • 引航科技提供网站建设柳州企业网站建设公司
  • 钢铁行业数字化利器,TDengine 时序数据库荣获金恒科技“年度卓越供应商”
  • 分布式奇异值分解(SVD)详解
  • 线程局部存储(Thread-Local Storage, TLS)
  • 勇立潮头:优艾智合打造“一脑多态”工业具身智能新范式
  • 怕故障?怕扩展难?分布式可视化控制:给足场景安全感
  • HTML5 Audio(音频)
  • 返利网一类的网站怎么做网站设计与网页制作模板
  • CMD 的 echo 不支持像 Linux 那样用引号输出多行内容
  • 网站建设的优缺点域名换了网站需要备案么
  • 高级Web前端开发工程师2025年面试题总结及参考答案【含刷题资源库】
  • 关于 Flink 程序打包与分布式执行的详细指南
  • mysql8.4.6 LTS 主从架构搭建
  • C#实现智能提示输入,并增色显示
  • CommunityToolkit.Mvvm框架
  • 快速创建Word箱单(1/2)
  • 营销型网站建设公司易网拓做网站属于什么费用
  • 马蜂窝网络营销网站建设手机编程工具
  • iOS 抓包实战 从原理到复现、定位与真机取证全流程
  • 宝塔反向代理后就访问不到django服务中间件匹配的图片文件夹中的图片了
  • 【网络核心协议全景解析】IP、TCP、UDP与HTTP(多表格深度对比)
  • GStreamer 和 FFmpeg 两大开源工具简要对比