阅读量:4
文章目录
- 前言
- 正文
- 什么是 MVVC
- 什么是 MVVM
- 什么是 SPA
- 什么是SFC
- 为什么 data 选项是一个函数
- Vue 组件通讯(传值)有哪些方式
- Vue 的生命周期方法有哪些
- 如何理解 Vue 的单项数据流
- 如何理解 Vue 的双向数据绑定
- Vue3的响应式原理是什么
- 介绍一下 Vue 的虚拟 DOM
- 介绍一下 Vue 的 diff 算法
- Vue中key的作用
- 为什么列表操作中,操作数据建议传id,而不是索引
- v-if 和 v-show 的区别
- v-if 和 v-for 为什么不建议放在一起使用
- 计算属性(computed) 和 方法(methods) 的区别
- 计算属性(computed) 和 侦听器(watch) 的区别
- Vue中如何监控某个属性值的变化
- v-model 是如何实现的,语法糖实际是什么
- Vuex是什么?
- 什么情况下应该使用 Vuex?
- 路由传值的方式有哪几种
- $route 和 $router 的区别
- vue-router 有哪几种路由守卫
- Vue.$nextTick
- Vue 实例挂载过程中发生了什么
- Vue 的模版编译原理
- computed 和 watch 的区别
- keep-alive 是什么
- 什么是mixin,如何使用
- 什么是插槽,如何使用
- Vue 中的修饰符有哪些
- $forceUpdate的原理
- Vue Router中的常用路由模式和原理
- 页面刷新后Vuex 状态丢失怎么解决
- 关于 Vue SSR 的理解
- 了解哪些 Vue 的性能优化方法
- Vue3的新特性有哪些
- createApp做了哪些事情
- reactive和ref的区别是什么
- Vue3和Vue2的区别
- Vue3的新工具 vite 和 Webpack 有什么区别
前言
Vue 官推消息,Vue 2 将于 2023年12月31日 停止维护(EOL)。
Vue 2.0 发布于 2016 年,迄今为止已有7年时间。Vue 2.0 的发布是其成为主流框架过程中的一个重要里程碑。
然而随着 2020 年 9 月份发布的 Vue 3 及其生态系统的日渐成熟,Vue 2.0 也渐渐退出了我们的视线,众多开发者们也在逐渐向 Vue3 靠拢。
早在2023年初,众多公司的面试重点就已经开始向Vue3倾斜。
2024有跳槽打算的朋友,拿下Vue3是重中之重。
正文
什么是 MVVC
- MVC全名是 Model View Controller,时模型 - 视图 - 控制器的缩写,一种软件设计典范。
- Model(模型):是用于处理应用程序数据逻辑部分。通常模型对象负责在数据库中存取数据。
- View(视图):是应用程序中处理数据显示的本分。通常视图是依据模型数据创建的。
- Controller(控制器):是应用程序处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
- MVC的思想:一句话描述就是Controller负责将Model的数据用View显示出来,换句话说就是在Controller里面把Model的数据赋值给View。
什么是 MVVM
- MVVM新增了VM类。
- ViewModel层:做了两件事达到了数据的双向绑定,一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。 实现的方式时:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转换成后端的数据。实现的方式是:DOM事件监听。
- MVVM与MVC最大的区别就是:实现了View和Model的自动同步,也就是当Model的属性改变时,我们不用再手动操作Dom元素来改变View的显示。 而是改变属性后该属性对应的View层显示会自动改变(对应Vue数据驱动的思想)
- 整体看来,MVVM比MVC精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作DOM元素。因为在MVVM中,View不知道Model的存在,Model和ViewModel也察觉不到View,这种低耦合模式提高代码的可重用性。
- 注意:Vue并没有完全遵循MVVM的思想,这一点官网自己也有声明。
- 那么问题来了,为什么官方要说Vue没有完全遵循MVVM思想呢?
- 严格的MVVVM要求View不能和Model直接通信,而Vue提供了$refs这个属性,让Model可以直接操作View,违反了这一规定,所以是Vue没有完全遵循MVVM。
什么是 SPA
- 单页面应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个 HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。
- 一些应用在前端需要具有丰富的交互性、较深的会话和复杂的状态逻辑。Vue 不仅控制整个页面,还负责处理抓取新数据,并在无需重新加载的前提下处理页面切换。
什么是SFC
- Vue 的单文件组件 (即 *.vue 文件,英文 Single-File Component,简称 SFC) 是一种特殊的文件格式,使我们能够将一个 Vue 组件的模板
<template>
、逻辑<script>
与样式<style>
封装在单个文件中。 - 使用 SFC 的优点:
- 使用熟悉的 HTML、CSS 和 JavaScript 语法编写模块化的组件
- 让本来就强相关的关注点自然内聚
- 预编译模板,避免运行时的编译开销
- 组件作用域的 CSS
- 在使用组合式 API 时语法更简单
- 通过交叉分析模板和逻辑代码能进行更多编译时优化
- 更好的 IDE 支持,提供自动补全和对模板中表达式的类型检查
- 开箱即用的模块热更新 (HMR) 支持
- SFC 的主要场景:
- 单页面应用 (SPA)
- 静态站点生成 (SSG)
- 任何值得引入构建步骤以获得更好的开发体验 (DX) 的项目
为什么 data 选项是一个函数
- 组件的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一分新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。
- 而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。
Vue 组件通讯(传值)有哪些方式
- 组件通信常用方式有以下几种
- props / $emit:适用 父子组件通信
- 父组件向子组件传递数据是通过 prop 传递
- 子组件传递数据给父组件是通过 $emit 触发事件来做到
- ref 与 $parent:适用 父子组件通信
- ref,如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素
- ref,如果用在子组件上,引用就指向组件实例
- $parent:访问访问父组件的属性或方法
- EventBus ($emit / $on):适用于 父子、隔代、兄弟组件通信
- $attrs:适用于 隔代组件通信
- $attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。
- 当一个组件没有声明任何 prop时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind=“$attrs” 传入内部组件。
- provide / inject:适用于 隔代组件通信
- 祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。
- provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系
- $root:适用于 隔代组件通信 访问根组件中的属性或方法,是根组件,不是父组件。
- Vuex 或 Pinia:适用于 父子、隔代、兄弟组件通信
- props / $emit:适用 父子组件通信
- 根据组件之间关系讨论组件通信最为清晰有效
- 父子组件:props / $emit / $parent / ref
- 兄弟组件:$parent / eventbus / vuex
- 跨层级关系:eventbus / vuex / provide+inject / $attrs / $root
Vue 的生命周期方法有哪些
- beforeCreate 在组件实例初始化完成之后立即调用。
- 会在实例初始化完成、props 解析之后、data() 和 computed 等选项处理之前立即调用。
- 在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问。
- created 在组件实例处理完所有与状态相关的选项后调用。
- 在这一步,以下内容已经设置完成:响应式数据、计算属性、方法和侦听器。
- 然而,此时挂载阶段还未开始,因此 $el 属性仍不可用。
- beforeMount 在组件被挂载之前调用。
- 组件已经完成了其响应式状态的设置,但还没有创建 DOM 节点。
- 它即将首次执行 DOM 渲染过程。
- mounted 在组件被挂载之后调用。
- 在当前阶段,真实的 Dom 挂载完毕,数据完成双向绑定,可以访问到 Dom节点。
- beforeUpdate 在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用。
- 这个钩子可以用来在 Vue 更新 DOM 之前访问 DOM 状态。
- updated 在组件因为一个响应式状态变更而更新其 DOM 树之后调用。
- 父组件的更新钩子将在其子组件的更新钩子之后调用。
- 这个钩子会在组件的任意 DOM 更新后被调用,这些更新可能是由不同的状态变更导致的。
- 如果你需要在某个特定的状态更改后访问更新后的 DOM,请使用 nextTick() 作为替代。
- **beforeUnmount **实例被卸载之前调用。
- 在这一步,实例仍然完全可用。
- 我们可以在这时进行 善后收尾工作,比如清除定时器。
- unmounted 实例卸载后调用。
- 调用后,Vue实例指示的东西都会卸载,所有的事件监听器会被移除,所有的子实例也会被卸载。
- activated 若组件实例是
<KeepAlive>
缓存树的一部分,当组件被插入到 DOM 中时调用。 - deactivated 若组件实例是
<KeepAlive>
缓存树的一部分,当组件从 DOM 中被移除时调用。
异步请求在哪一步发起?
- 可以在钩子函数 created、beforeMount、mounted 中进行异步请求,因为在这三个钩子函数中,data已经创建,可以将服务器端返回的数据进行赋值。
- 如果异步请求不需要依赖 DOM,推荐加载 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:
- 能更快获取到服务端数据,减少页面loading时间;
- ssr 不支持 beforeMount、mounted 钩子函数,所以放在 created 中有助于一致性。
如何理解 Vue 的单项数据流
- 数据总是从父组件传到子组件,子组件没有权利修改父组件传过来的数据,只能请求父组件对原始数据进行修改。这样可以防止从子组件意外改变父组件的状态,从而导致你的应用的数据流向难以理解。
- 注意:在子组件直接用 v-model 绑定父组件传过来的 props 这样是不规范的写法,开发环境会报警告。
- 如果实在要改变父组件的 props 值可以再data里面定义一个变量,并用 prop 的值初始化它,之后用$emit 通知父组件去修改。
如何理解 Vue 的双向数据绑定
- Vue.js 3中的双向数据绑定可以通过使用
v-model
指令来实现。在Vue.js 2及之前版本中,我们需要手动编写事件处理函数来更新视图或模型,而在Vue.js 3中,这些工作已经被自动化了。 - 当我们将
v-model
应用于表单元素(如输入框、复选框等)时,Vue会为该元素创建一个名为"value"的属性,并且还会为其添加相关的事件监听器。 - 当用户与表单交互时,比如修改文本内容或切换复选框状态,Vue会自动触发对应的事件,然后更新绑定到该元素上的数据。同样地,当我们在JavaScript中直接修改绑定的数据时,也能立即反映在视图上。
- 双向数据绑定的原理,参考下一题:Vue3响应式原理
Vue3的响应式原理是什么
- vue3采用数据代理+数据劫持+发布订阅模式的方法。
- 在初始化vue实例时,通过Proxy进行数据代理,用Proxy对象来代理目标对象,并且对目标对象中的所有属性动态地进行数据劫持,动态地指定一个getter、setter,并通过Reflect操作对象内部数据。
- 当Proxy对象属性或Proxy数组元素发生变化时,会触发Proxy属性的setter方法,然后通过Reflect操作目标对象属性,同时触发它Dep实例的notify方法进行依赖分发,通知所有依赖的Watcher实例执行内部回调函数
介绍一下 Vue 的虚拟 DOM
- 虚拟dom顾名思义就是虚拟的dom对象,它本身就是一个JavaScript对象,只不过它是通过不同的属性去描述一个视图结构,相比于真实dom只保留了核心属性,进而使后续操作更加快速;
- 通过引入vdom我们可以获得如下好处:
- 将真实元素节点抽象成VNode,有效减少直接操作dom次数,从而提高程序性能;
- 直接操作 dom 是有限制的,比如:diff、clone等操作,一个真实元素上有许多的内容,如果直接对其进行diff操作,会去额外diff一些没有必要的内容;同样的,如果需要进行clone,那么需要将其全部内容进行复制,这也是没必要的。但是,如果将这些操作转移到 JavaScript 对象上,那么就会变得简单了;
- 操作 dom 是比较昂贵的,频繁的dom操作容易引起页面的重绘和回流,但是通过抽象VNode进行中间处理,可以有效减少直接操作dom的次数,从而减少页面重绘和回流;
- 方便实现跨平台
- 同一VNode节点可以渲染成不同平台上的对应的内容,比如:渲染在浏览器是dom元素节点,渲染在Native(iOS、Android)变为对应的控件、可以实现SSR(服务端渲染)、渲染到WebGL中等等;
- Vue3中允许开发者基于VNode实现自定义渲染器(renderer),以便于针对不同平台进行渲染;
- vdom如何生成,又如何成为真实dom?以及在diff中的作用
- 在vue中我们常常会为组件编写模板template,这个模板会被编译器compiler编译为渲染函数(render function),在接下来的挂载(mount)过程中会调用render函数,返回的对象就是虚拟dom。但它们还不是真正的dom,会在后续的patch过程中进一步转化为真实dom:
- 挂载过程结束后,vue程序进入更新流程。如果某些响应式数据发生变化,将会引起组件重新render,此时就会生成新的vdom,和上一次的渲染结果diff就能得到变化的地方,从而转换为最小量的dom操作,高效更新视图。
介绍一下 Vue 的 diff 算法
- DOM操作是非常昂贵的,因此我们需要尽量地减少DOM操作。这就需要找出本次DOM必须更新的节点来更新,其他的不更新,这个找出的过程,就需要应用 diff 算法
- vue的diff算法是平级比较,不考虑跨级比较的情况。
- 内部采用深度递归的方式+双指针(头尾都加指针)的方式进行比较。
- Vue 中的 diff 算法称为 patching 算法,它由 Snabbdom 修改而来,虚拟 DOM 要想转化为真实 DOM 就需要通过 patch 方法转换
- 最初 Vue1.x 视图中每个依赖均有更新函数对应,可以做到精准更新,因此并不需要虚拟 DOM 和 patching 算法支持,但是这样粒度过细导致 Vue1.x 无法承载较大应用;Vue 2.x 中为了降低 Watcher 粒度,每个组件只有一个 Watcher 与之对应,此时就需要引入 patching 算法才能精确找到发生变化的地方并高效更新
- vue 中 diff 执行的时刻是组件内响应式数据变更触发实例执行其更新函数时,更新函数会再次执行 render 函数获得最新的虚拟 DOM,然后执行 patch 函数,并传入新旧两次虚拟 DOM,通过比对两者找到变化的地方,最后将其转化为对应的 DOM 操作
- patch 过程是一个递归过程,遵循深度优先、同层比较的策略;以 vue3 的 patch 为例:
- 首先判断两个节点是否为相同同类节点,不同则删除重新创建
- 如果双方都是文本则更新文本内容
- 如果双方都是元素节点则递归更新子元素,同时更新元素属性
- 更新子节点时又分了几种情况
- 新的子节点是文本,老的子节点是数组则清空,并设置文本;
- 新的子节点是文本,老的子节点是文本则直接更新文本;
- 新的子节点是数组,老的子节点是文本则清空文本,并创建新子节点数组中的子元素;
- 新的子节点是数组,老的子节点也是数组,那么比较两组子节点,更新细节 blabla
- vue3中引入的更新策略:静态节点标记等
Vue中key的作用
- key 是为Vue中Vnode的唯一标识,通过这个key,我们的diff操作可以更准确、更快速。
- 如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。
- 更准确:因为带key就不是就地复用了,在sameNode函数 a.key === b.key 对比中可以避免就地复用的情况。所以更加准确。
- 更快速:利用key的唯一性生成map对象来获取对应节点,比遍历方式块。
为什么列表操作中,操作数据建议传id,而不是索引
- 在列表渲染中,如果复杂数据中有异步数据或开销比较大的数据计算或DOM更新,vue会先在虚拟DOM中合并操作,从而导致数据更新和真实DOM存在不同步现象,此时DOM中获取的索引和数据的索引如果无法实时对应,就会有很大的隐患(数据更新了,但是DOM没更新)
v-if 和 v-show 的区别
- 规则
- v-show 隐藏规则是为该元素添加css属性display:none,dom元素依旧还在。
- v-if 显示隐藏是将dom元素整个添加或删除
- 编译过程:
- v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;
- v-show只是简单的基于css切换
- 编译条件:
- v-if是真正的条件渲染,它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。只有渲染条件为假时,并不做操作,直到为真才渲染
- 生命周期:
- v-show 由false变为true的时候不会触发组件的生命周期
- v-if由false变为true的时候,触发组件的beforeCreate、create、beforeMount、mounted钩子,由true变为false的时候触发组件的beforeDestory、destoryed方法
- 性能消耗:
- v-if有更高的切换消耗;
- v-show有更高的初始渲染消耗
- 使用场景:
- v-if 与 v-show 都能控制dom元素在页面的显示
- v-if 相比 v-show 开销更大的(直接操作dom节点增加与删除)
- 如果需要非常频繁地切换,则使用 v-show 较好
- 如果在运行时条件很少改变,则使用 v-if 较好
v-if 和 v-for 为什么不建议放在一起使用
- 因为 v-for 的优先级比 v-if 的优先级高,所以每次渲染时都会先将列表渲染出来,再通过条件判断进行显示隐藏,所以将 v-if 和 v-for 用在一起会特别消耗性能
- 可以通过计算属性 computed 提前过滤掉不符合条件的项
计算属性(computed) 和 方法(methods) 的区别
- 调用方式:
computed
是属性调用,在定义函数时以属性的形式调用,methods
是方法调用,在定义函数时以方法的形式调用,要加()
- 缓存功能:
computed
是计算属性,是有缓存的,当它的依赖属性改变的时候,才会进行重新计算,如果数据没有改变,它是不会运行的。methods
是方法,没有缓存功能,只要你调用一次,不管数据是否改变,它都是执行。
- 所以,同等条件下,
computed
比methods
性能好一点,避免重复执行。
计算属性(computed) 和 侦听器(watch) 的区别
- computed 是计算属性,依赖其它属性计算值,并且 computed 的值有缓存,只有当计算值变化才会返回内容,他可以设置getter和setter。
- watch 监听到值的变化就会执行回调,在回调中可以进行一系列的操作。
- 计算属性一般用在模板渲染中,某个值是依赖其它响应对象甚至是计算属性而来;
- 而侦听属性适用于观测某个值的变化去完成一段复杂的业务逻辑。
Vue中如何监控某个属性值的变化
- Vue3中使用
watch
方法来监听响应式数据的变化,并在数据变化时执行回调函数。
import { watch } from 'vue' const state = reactive({ count: 0 }) watch(() => state.count, (newValue, oldValue) => { console.log(newValue, oldValue) })
v-model 是如何实现的,语法糖实际是什么
v-model
本质上就是语法糖,在使用v-model
后既绑定了数据,又添加了一个@input
事件监听<input v-model='message' />
- 等价于
<input :value='message' @input='message = $event.target.value'>
- 当在input元素中使用
v-model
实现双数据绑定,其实就是在输入的时候触发元素的input事件,通过这个语法糖,也能够实现父子组件数据的双向绑定 - 如何实现
- 作用在表单元素上:
- 动态绑定了
input
的value
指向了messgae
变量 - 并且在触发
input
事件的时候去动态把message
设置为目标值:
- 动态绑定了
- 作用在表单元素上:
<input v-model='message' /> // 等同于 <input :value="message" @input="message=$event.target.value" >
- 作用在组件上:
- 在自定义组件中,
v-model
默认会利用名为value
的prop
和名为input
的事件 - 本质是一个父子组件通信的语法糖,通过
prop
和$.emit
实现。 因此父组件v-model
语法糖本质上可以修改为:
<child :value="message" @input="function(e){message = e}"></child>
- 在组件的实现中,可以通过
v-model
属性来配置子组件接收的prop
名称,以及派发的事件名称。
Vuex是什么?
- Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- 但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
- 对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
- 对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
- 因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
- 通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。
什么情况下应该使用 Vuex?
- Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
- 如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
路由传值的方式有哪几种
【注意】
- 在选项式API中,可以通过this关键字直接获取router对象,如:
this.$router
和this.$route
- 在setup中,需要先引入
useRoute
和useRouter
方法,创建route
和router
对象,如:import { useRoute } from "vue-router"; const route = useRoute();
1. 路由路径参数(Route Params)(动态路由)
- 在路由定义中使用动态路径参数来传递参数。例如,定义一个带有参数的路由:
{ path: '/user/:id', component: User }
- 在组件中可以通过$route.params来获取参数值:
console.log(route.params.id);
- 优缺点
- 优点:参数直接嵌入在URL中,易于理解和传递;适合传递单个参数。
- 缺点:不适合传递多个参数;参数必须在路由定义中提前声明。
- 使用场景:传递单个参数,例如用户ID、商品ID等。
2. 查询参数(Query Params):
- 在URL中使用查询字符串来传递参数。例如,定义一个带有查询参数的路由:
{ path: '/user', component: User }
- 在组件中可以通过$route.query来获取参数值:
console.log(route.query.id);
- 优缺点
- 优点:参数直接嵌入在URL中,易于理解和传递;适合传递多个参数。
- 缺点:参数较长时,URL可能会变得冗长。
- 使用场景:传递多个参数,例如搜索条件、过滤条件等。
路由元信息(Route Meta)
- 在路由定义中使用元信息来传递参数。例如,定义一个带有元信息的路由:
{ path: '/user', component: User, meta: { id: 123 } }
- 在组件中可以通过$route.meta来获取参数值:
console.log(route.meta.id);
- 优缺点
- 优点:参数可以在路由定义中灵活设置;适合传递静态参数。
- 缺点:参数无法直接嵌入在URL中,不适合传递动态参数。
- 使用场景:传递静态参数,例如页面标题、页面权限等。
命名路由(Named Routes)
- 在路由定义中给每个路由设置一个唯一的名称,然后通过名称来传递参数。例如,定义一个带有命名路由的路由:
{ path: '/user', name: 'user', component: User }
- 在组件中可以通过$router.push或的to属性来传递参数:
router.push({ name: 'user', params: { id: 123 } })
- 优缺点
- 优点:参数通过路由名称传递,不依赖具体的URL;适合传递动态参数。
- 缺点:需要提前定义路由名称。
- 使用场景:传递动态参数,并且不依赖具体的URL。
Props传递参数
- 在路由定义中使用props属性来传递参数。例如,定义一个带有props的路由:
{ path: '/user', component: User, props: true }
- 在组件中可以通过props来接收参数:
props: ['id']
- 优缺点
- 优点:参数通过组件的props属性传递,易于理解和传递;适合传递组件需要的数据。
- 缺点:需要在路由定义中设置props为true,并在组件中接收props。
- 使用场景:传递组件需要的数据。
Vuex状态管理
- 使用Vuex来管理应用程序的状态,并在不同组件之间共享参数。
- 通过在Vuex store中定义和更新参数,然后在组件中使用mapState或mapGetters来获取参数的值。
- 优缺点:
- 优点:参数通过Vuex store管理,可以在整个应用程序中共享和更新;适合共享状态和数据。
- 缺点:需要引入Vuex并设置store。
- 使用场景:共享状态和数据,例如用户登录状态、购物车数据等。
$route 和 $router 的区别
- $router是VueRouter的一个实例,是当前项目全局的路由对象,主要用来操作路由,他包含了所有的路由,包括路由的跳转方法,钩子函数等
- $route是一个跳转的路由对象(路由信息对象),是一个局部的路由对象,表示当前路由,主要用来获取当前路由信息
- $router的常用方法
// 跳转方法,会产生历史记录 this.$router.push("/login"); // 跳转方法,不会产生提示记录 this.$router.replace("/login"); // 跳转方法,同:window.history.go() // 参数:正:前进,负:后退,0:刷新 this.$router.go(-1)
- $route的常用属性
// 字符串,等于当前路由对象的路径,会被解析为绝对路径,如/home/ews this.$route.path // 对象,包含路由中的动态片段和全匹配片段的键值对,不会拼接到路由的url后面 this.$route.params // 对象,包含路由中查询参数的键值对。会拼接到路由url后面 this.$route.query // 路由规则所属的路由器 this.$route.router // 当前路由的名字,如果没有使用具体路径,则名字为空 this.$route.name
vue-router 有哪几种路由守卫
Vue.$nextTick
- 等待下一次 DOM 更新时才会执行的方法。
- 如果在修改数据之后立即执行这个方法,并使用await等待返回的Promise结束,就可以获取更新后的 DOM内容。
- Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 当中观察到数据变化的 watcher 推送进这个队列。如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和DOM操作。而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新
Vue 实例挂载过程中发生了什么
Vue 的模版编译原理
computed 和 watch 的区别
keep-alive 是什么
什么是mixin,如何使用
什么是插槽,如何使用
Vue 中的修饰符有哪些
Vue中常用的修饰符有以下几种:
- .prevent
- 阻止默认事件的触发,例如表单提交、超链接跳转等。
- .stop
- 阻止事件冒泡,在事件处理函数中调用 event.stopPropagation() 方法来实现。
- .capture
- 捕获模式,在事件处理过程中先触发祖先元素的事件处理函数,然后再触发子孙元素的事件处理函数。
- .self
- 限制事件只能在绑定该事件的元素上触发,而不是在其子元素上触发。
- .once
- 只触发一次事件处理函数。
- .passive
- 声明事件处理函数永远不会调用 event.preventDefault() 方法,以提高页面滚动的性能。
- .keyCode / .keyAlias
- 监听按键的特定键码或别名,例如.enter、.esc等。
- .native
- 监听组件根元素的原生事件,而不是组件内部的事件。
$forceUpdate的原理
$forceUpdate
是Vue.js中的一个实例方法,用于强制组件重新渲染。它的原理是触发组件的更新流程,将组件的虚拟 DOM 树重新生成,并对比新旧虚拟 DOM 树的差异,最终将变化的部分更新到真实的 DOM 上。
具体的实现流程如下:$forceUpdate
方法被调用后,会触发组件的更新标记(dirty);- Vue.js 会异步执行更新队列(update queue),对所有标记为 dirty 的组件进行更新;
- 对于需要更新的组件,Vue.js 会重新生成其虚拟 DOM 树,并与之前的虚拟 DOM 树进行比较,找出差异(diff);
- 对于有差异的部分,Vue.js 会将其更新到真实的 DOM 上,完成组件的重新渲染。
Vue Router中的常用路由模式和原理
页面刷新后Vuex 状态丢失怎么解决
关于 Vue SSR 的理解
了解哪些 Vue 的性能优化方法
Vue3的新特性有哪些
createApp做了哪些事情
- 执行 createApp 首先会创建渲染器,这里要注意的是存在2种渲染器类型,并且它们都是通过延迟创建的,主要目的是当用户只引用reactive响应式框架的时候,方便进行tree-shaking优化。且两种渲染器都是基于 baseCreateRender 方法来实现。
- baseCreateRender 函数执行后会返回 render 渲染函数和 createApp 方法,其中 render 函数是组件创建、更新和卸载的主要核心逻辑实现。createApp则用于创建应用实例,进行应用实例的初始化。
- createAppAPI用于生成默认的应用上下文 context,这里定义了应用实例具备的属性和方法,并通过重写扩展 context.app 属性,让用户能够进行对上下文的自定义操作,比如自定义组件、指令、mixin、插件安装等一系列操作。并存在mount方法完成将根组件转为虚拟节点 vNode,并通过render 函数完成对 vNode 的渲染
reactive和ref的区别是什么
Vue3和Vue2的区别
Vue3的新工具 vite 和 Webpack 有什么区别
- webpack会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。
- 而vite是直接启动开发服务器,请求哪个模块再对该模块进行实时编译。
- 由于现代浏览器本身就支持ES Module,会自动向依赖的Module发出请求。vite充分利用这一点,将开发环境下的模块文件,就作为浏览器要执行的文件,而不是像webpack那样进行打包合并。
- 由于vite在启动的时候不需要打包,也就意味着不需要分析模块的依赖、不需要编译,因此启动速度非常快。当浏览器请求某个模块时,再根据需要对模块内容进行编译。这种按需动态编译的方式,极大的缩减了编译时间,项目越复杂、模块越多,vite的优势越明显。
- 在HMR方面,当改动了一个模块后,仅需让浏览器重新请求该模块即可,不像webpack那样需要把该模块的相关依赖模块全部编译一次,效率更高。
- 当需要打包到生产环境时,vite使用传统的rollup进行打包,因此,vite的主要优势在开发阶段。另外,由于vite利用的是ES Module,因此在代码中不可以使用CommonJS