Vue前端面试题
- 1 Vue 生命周期
- 2 Vue 组件通信方式有哪些
- 3 v-show 和 v-if区别
- 4 v-if 和 v-for为什么不能一起使用
- 5 computed 和 watch区别
- 6 vue-router作用
- 7 hash 和 history区别
- 8 路由导航守卫有哪些
- 9 to from next 区别
- 10 路由跳转方式有哪些
- 11 路由传值方式有哪些
- 12 query 和 params区别
- 13 route 和 router区别
- 14 介绍一下keep-alive
- 15 介绍一下Vuex
- 16 介绍一下插槽
- 17 介绍一下Mixin混入
- 18 介绍一下Hook
- 19 Vue 常用的修饰符有哪些
- 20 Vue 常用指令有哪些
- 21 怎么理解 Vue 的单向数据流
- 22 Vue 中为什么data是个函数
- 23 说说你对 SPA 单页面的理解,它的优缺点分别是什么?
- 24 MVC 和 MVVM区别
- 25 Vue 数据双向绑定原理?(响应式原理)
- 26 Vue 是如何实现数据双向绑定的?
- 27 v-model 的原理
- 28 Vue 中 key 的作用
- 29 VNode 是什么?虚拟 DOM 是什么?
- 30 Diff 算法是什么?
- 31 Vue 的 nextTick 的原理是什么?
- 32 如何对 Vue 组件进行封装的?
- 33 Vue3 和 Vue2 的区别
- 34 说一下 Composition API
- 35 Vue 项目优化的解决方案都有哪些?
1 Vue 生命周期
vue生命周期就是vue实例从创建到销毁的过程,也就是从开始创建、初始化数据、编译模板、挂载Dom->渲染、更新->渲染、销毁等一系列过程。
vue生命周期大致可以分为三个阶段:
- 创建阶段
beforeCreate->Created->beforeMount->Mounted - 更新阶段
beforeUpdate->Updated - 销毁阶段
beforeDestroy->destroyed
在项目中,常用的生命周期函数有:
Created
:发起异步请求获取数据,此时还不能操作Dom
Mounted
:这时Dom
已被创建,可以基于ref
获取Dom
,还可以在这里设置定时器、绑定自定义事件beforeDestroy
:在Vue实例销毁之前,清除定时器、解绑自定义事件
Vue3相对于Vue2来说有一些变化,比如:
beforeCreate
和Created
生命周期函数被setUp
函数替换了- 其他周期函数改成以
on
开头,例如Mounted
改成了onMounted
- 销毁的周期函数改成了
onBeforeUnmount
和onUnmounted
2 Vue 组件通信方式有哪些
-
props
与$emit / $on
适用于父子组件通信
父组件在子组件上绑定需要传递的数据和事件方法
子组件通过 props 接收父组件传递过来的数据,并且通过绑定事件的方式调用 $emit 触发父组件的自定义事件,实现父组件数据的更新 -
ref
与$parent
/$children
适用于父子组件通信
ref:获取 DOM 元素或者子组件实例的属性和方法
$parent / $children:访问父 / 子组件实例 -
EventBus
($emit / $on) 适用于 父子、隔代、兄弟组件通信
EventBus主要是用到发布者-订阅者的设计模式,这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件 -
provide
/inject
适用于隔代组件通信
多层级嵌套的组件,通过 props 逐级传递数据比较麻烦。祖先组件中通过 provider 来提供数据/方法,然后在子孙组件中通过 inject 来注入数据/方法。 -
$attrs
/$listeners
适用于隔代组件通信
$attrs: 用于传递非 props 属性 v-bind=“$attrs”
$listeners:用于传递非原生事件方法 v-on=“$listeners” -
Vuex
适用于任意组件之间传值,实现数据共享
3 v-show 和 v-if区别
v-show / v-if:都是用来控制元素的显示和隐藏的
区别:
v-show:本质是通过设置css中display属性为none来控制隐藏
v-if:是动态添加或者移除DOM元素
编译区别:
v-show:只会编译一次,本质就是控制css
v-if:初始值为false时,就不会编译;v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件
性能比较:
v-show:适用于频繁操作某个节点时使用(初始开销大,切换开销较小)
v-if:适用于少次操作某个节点时使用(因为懒加载,初始化时不会渲染,v-if 是不停地创建和销毁DOM元素,初始开销小,切换开销较大)
4 v-if 和 v-for为什么不能一起使用
v-if 和 v-for 应该避免在同一个元素上同时使用,因为会造成不必要的内存消耗,影响性能
vue2: v-for 的优先级比 v-if的优先级高,如果嵌套使用的话,每次v-for 都会执行一次v-if,会造成重复计算的问题,影响性能
vue3:v-if 的优先级高于v-for,会导致 for循环的索引还没拿到,控制台会报错,且什么都不渲染
如何避免渲染应该被隐藏的项?
外层嵌套template(页面渲染不生成DOM节点),先进行 v-if 判断,然后在内部进行 v-for 循环
如何过滤列表中的项?
如果条件出现在循环内部,则通过 computed 计算属性提前过滤掉那些不需要显示的项
5 computed 和 watch区别
computed / watch:都是用来观察页面数据变化的
区别:
- 缓存功能
computed :支持缓存,只有依赖的数据发生了变化,才会重新计算
watch:不支持缓存,数据变化时,直接触发相应的操作 - 是否支持异步
computed :不支持异步,当computed内有异步操作时,无法监听数据的变化
watch:支持异步操作,适用于监听路由和定时器等 - 数据影响
computed :一个属性是由其他属性计算而来的,其中任何一个属性发生变化时,该值能及时更新。所以computed属性不能与data属性命名冲突
watch:一个属性影响其他属性,当这个值发生变化时,能及时更新所有依赖它值
总的来说
computed :更注重数据变化得出的结果,一定要有返回值
watch :更注重数据变化时执行的过程,可以没有返回值作为结果,,更适用于数据变化时的异步操作
6 vue-router作用
vue-router
是vue.js
官方的路由插件,它和vue.js
是深度集成的,适用于构建单页面应用- vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。传统的页面应用,一般是通过超链接实现页面的切换和跳转
- 在
vue-router
单页面应用中,则是路径之间的切换,也就是组件之间的切换。路由模块的本质就是建立起url和页面之间的映射关系 - vue路由主要有
hash
和history
两种模式,都能使视图更新而不需要重新加载页面
7 hash 和 history区别
原理:
hash
:利用了window.onhashchange
事件,监听url中#
后面哈希值的变化,找到对应的页面进行加载
history
:通过pushHash
方法新增记录和replaceHash
方法替换当前记录的方式改变url,然后监听popHash事件来监听url的变化,触发视图更新
区别:
hash
模式地址栏后面有#
符号,history
模式没有hash
模式地址中#
后的哈希值变化不会发起HTTP请求,对后端完全没有影响,所以改变哈希值不会重新加载页面;history
模式斜杠后的路径变化会发起HTTP请求,如果前后端的路径不一致会返回404错误hash
模式兼容性比history
好,可达到 IE8
8 路由导航守卫有哪些
路由导航守卫:是路由跳转过程中的生命周期函数,也称为钩子函数,可以帮助实现不同的业务需求或者处理不同的业务逻辑
路由导航守卫大致可以分为三种:
- 全局导航守卫
beforeEach
路由跳转之前做一些验证,比如登录验证beforeResolve
路由解析守卫afterEach
路由跳转之后,不能使用next
- 路由独享守卫
beforeEnter
- 组件路由守卫
beforeRouteEnter
组件实例还未创建,不能使用this,可以回调给next来访问组件实例beforeRouteUpdate
beforeRouteLeave
离开路由之前执行操作,比如草稿箱的暂存
9 to from next 区别
to
:即将进入的目标路由对象
from
: 即将离开的路由对象
next
:
next()
:一定要调用next方法进行下一个钩子;否则直接中断当前导航,会导致路由组件无法渲染,页面出现空白next(false)
:中断当前的导航next('/...')
或者next({ path: '/...' })
:跳转到指定的路由地址next(error)
:导航终止,router.onError()
捕获处理异常
10 路由跳转方式有哪些
路由跳转方式有两种:
- 声明式导航
<router-link :to="需要跳转的页面路径" />
- 编程式导航
有三种方式:push()
: 跳转到指定的页面路径,会向history中添加记录,点击回退返回上个页面replace()
: 替换当前页面路径,不会向history中添加记录,点击回退返回上上个页面go(n)
:n可以是正数或者负数,表示向前或者向后跳转n个页面
11 路由传值方式有哪些
无论是声明式导航还是编程式导航,都可以通过字符串
或者对象
两种方式进行传值
字符串
:直接传递路由路径,不能携带参数
对象
:可以通过 query
或者 params
两种方式传递参数
12 query 和 params区别
query
用path
引入,params
用name
引入,params
一定不能和path
一起使用query
刷新页面不会丢失参数,params
刷新页面会丢失参数,可以通过在路径斜杠后添加:参数名
动态路由方式,使参数显示在url上- 地址栏参数显示不同
query
:路径?name=xxx&key=xxx
params
:路径/参数1/参数2
13 route 和 router区别
route
:路由信息对象,可以获取query
、name
、params
、path
等路由信息参数
router
:路由实例对象,可以调用路由跳转方式、钩子函数等
14 介绍一下keep-alive
keep-alive
:是 Vue 内置的一个组件,用来实现组件缓存,可以使被包含的组件保留状态,避免重新渲染
有三个属性:
include
:表示只有匹配的组件会被缓存
exclude
:表示匹配的组件不会被缓存
max
:定义组件最大的缓存个数
有两个钩子函数(生命周期函数)
activated
:缓存的组件被激活时触发
deactivated
:缓存的组件被移除时触发
执行顺序:
- 不使用keep-alive:beforeRouteEnter -> created -> mounted -> destroyed
- 使用keep-alive,首次进入:beforeRouteEnter -> created -> mounted -> activated -> deactivated
- 使用keep-alive,缓存进入:beforeRouteEnter ->activated -> deactivated
15 介绍一下Vuex
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。
特点:
- 存储在Vuex中的数据都是响应式的,能够实时保持数据与页面的同步
- Vuex能够集中管理组件之间的数据,实现数据共享,易于开发和维护
大致有五个模块:
State
:用于存放组件之间共享的数据
Getter
:相当于 state 的计算属性,用于对 Store 中的数据进行加工处理形成新的数据,当 Store 中数据发生变化,getter 的数据也会跟着变化
Mutation
:用于改变 store 中状态的方法,且必须是同步函数。
Action
:用于提交 mutation,而不是直接修改state中的数据,可以处理任意异步操作。
Module
:允许将store分割成模块 (Module),且每个模块都有自己的state、getters、mutation、action等,甚至是嵌套子模块
16 介绍一下插槽
插槽:相当于组件模板中的占位符,父组件通过插槽向子组件内部指定位置传递内容。插槽分为三种:匿名插槽、具名插槽、作用域插槽
匿名插槽:默认情况下,提供的内容都会被填充到名字为 default (或默认不写) 的插槽之中,一个组件只能有一个匿名插槽
具名插槽:将提供的内容填充到具体名称的插槽之中
使用方法:<template v-slot:插槽名></template>
- 需要使用 v-slot: 这个指令
- v-slot: 后面要跟上插槽的名字
- v-slot: 不能直接用在元素上,必须使用template标签包裹
- template 标签只起到包裹作用,不会被渲染为html元素
- v-slot: 可简写为 #
作用域插槽:能够把⼦组件的数据传递给⽗组件使⽤,子组件在 <slot>
元素上通过v-bind绑定数据,父组件通过 v-slot:
或者 #
获取子组件传递过来的数据
17 介绍一下Mixin混入
Mixin混入:能够将多个组件的公共代码,包括数据对象、钩子函数、方法等抽离出来,减少代码冗余,达到复用效果。Mixin混入方式有两种:全局混入、局部混入。
全局混入:只需要把mixin.js文件引入到main.js中,然后将mixin放入到Vue.mixin()方法中,在需要的使用的页面直接使用,不需要再引入
局部混入:新建mixin.js文件,注册一个mixin对象,里面定义公共数据和方法,在需要的页面引入,使用mixins混入,数组可以接收多个mixin
选项冲突处理:
- 生命周期钩子函数同名:
都会触发,但是mixin会先触发
同名钩子函数将合并为一个数组,因此都将被调用,但是混入对象的钩子函数优先执行。 - 数据对象data同名:
data对象的内部会进行递归合并,当发生冲突时,以组件为主。 - 对象类型的选项(methods、components、computed、directives、watch等)同名:
当发生冲突时,组件会覆盖mixin。
Mixin混入和Vuex的区别:
- Vuex:用来做状态管理的,Vuex中的所有变量和方法都是可以使用和更改并且会相互影响。
- Mixins:用来定义公共变量,在不同组件中各个变量是相互独立的,值的修改在组件中不会相互影响。
vue3.0中已经将mixin作为备选方案,推荐使用hook,也是复用的。因为mixin覆盖容易产生冲突、滥用的话后期维护比较麻烦。
18 介绍一下Hook
Hook:类似于 mixin ,能够实现代码复用,自定义的 hooks 一定要是 use 开头。
Hook 和 Mixin 的区别:
mixin 缺点:
- mixin中的变量和方法是隐式引入,变量来源不明确,不利于代码维护
- 一个组件中引入多个mixin,容易出现变量和方法重名,就会导致冲突或覆盖现象
Hook 优点:
- Hook函数的变量和方法是显示传入,数据来源明确
- 自定义Hook可以在引入的时候对同名变量重命名,代码易维护
19 Vue 常用的修饰符有哪些
v-on:
- .prevent: 调用 event.preventDefault() ,阻止提交事件重载页面
- .stop:调用 event.stopPropagation() ,阻止单击事件冒泡
- .self:只触发元素本身的事件,不会触发子元素的事件
- .capture: 与事件冒泡相反,事件捕获由外向内
- .once:事件只会触发一次
- .native:监听组件根元素的原生事件
v-model:
- .lazy:让光标离开输入框再同步数据
- .number:输入字符串转为有效的数字
- .trim:输入首尾空格过滤
v-bind:
- .sync:语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器
20 Vue 常用指令有哪些
- v-model:多用于表单元素实现数据双向绑定
- v-bind:动态绑定属性、样式
- v-on:绑定事件
- v-show:元素显示与隐藏
- v-if:元素显示与隐藏
- v-for:循环遍历生成元素
- v-text:解析文本
- v-html:解析html标签
- v-once:只渲染一次,后续不再更新
- v-pre:原位输出标签内部的元素
- v-clock:防止闪烁
21 怎么理解 Vue 的单向数据流
- 数据从父组件传递给子组件,只能单向绑定
- 子组件内部不能直接修改从父级传递过来的数据
- 所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
- 父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值
- 子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改
22 Vue 中为什么data是个函数
- 因为每个组件都是 Vue 实例, Vue组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值就会相互影响
- 如果组件中 data 选项是一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回新的 data ,类似于给每个 Vue 组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据,组件实例之间的 data 属性值就不会互相影响
为什么 new Vue 实例里,data 可以直接是一个对象?
因为 new Vue 的实例不会被复用,它只会 new 一次,因此不存在引用对象的问题
23 说说你对 SPA 单页面的理解,它的优缺点分别是什么?
SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制动态的变换 HTML 内容,从而实现 UI 与用户的交互,避免页面的重新加载。
优点:
- 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染
- 前后端分离,分工更明确,前端进行交互逻辑,后端负责数据处理
缺点:
- 首次渲染速度相对较慢
- 不利于搜索引擎的抓取
24 MVC 和 MVVM区别
MVC:就是 Model-View-Controller 对应模型-视图-控制层,Controller控制层,负责接收视图发送过来的数据,同时控制 Model 数据;思想就是Controller 将 Model 的数据展示在 View 上
MVVC:就是 Model-View-ViewModel 对应模型-视图-视图模型,ViewModel 是 Model 和 View之间的桥梁,通过双向数据绑定把 View 层和 Model 层连接起来,使 View 数据的变化会同步到Model,Model 数据的变化也会反应到 View 上;思想是 View 和 Model 实现数据同步,不需要手动更新
区别:
- MVC是单向的,而MVVC是双向,并且是自动的,监听到数据发生改变会让视图重新渲染,监听到视图发生改变会让对应数据变化
- MVVM解决了MVC中大量的DOM操作使页面渲染性能降低的问题,在数据频繁更新的时候,采用了虚拟DOM,减少页面过度渲染,从而提高性能
25 Vue 数据双向绑定原理?(响应式原理)
Vue2:采用数据劫持结合发布订阅者模式的方式,通过Object.defineProperty()
数据劫持,来劫持各个属性的 getter、setter ,在数据更新时发布消息给 getter、setter,触发相应的监听回调,从而使关联的组件重新渲染
优点:
- 兼容性好,支持 IE9
缺点:
- 对象直接添加属性或者删除已有属性,页面不会更新(可通过
$set
、$delete
、$forceUpdate()
的方法解决) - 数组通过直接索引下标替换元素,页面不会更新(可通过数据的七个方法解决:
push
、pop
、shift
、unshift
、splice
、sort
、reserve
)
Vue3:用 Proxy
代理监听劫持对象的操作,然后通过 Reflect 动态的对被代理对象进行相应操作
优点:
- Proxy 可以直接监听对象而非属性,可以直接监听数组的变化
- Proxy 有多达 13 种拦截方法,例如:
apply
、ownKeys
、deleteProperty
、has
等是 Object.defineProperty() 不具备的 - Proxy 返回的是一个新对象,可以只操作新的对象达到目的,而Object.defineProperty 只能遍历对象属性直接修改
缺点:
- 浏览器兼容性较差,而且无法用 polyfill 磨平
26 Vue 是如何实现数据双向绑定的?
Vue 数据双向绑定主要是指:数据变化更新视图,视图变化更新数据。
Vue 主要通过以下 4 个步骤来实现数据双向绑定的:
- 实现一个监听器 Observer:用来监听劫持数据对象的所有属性,在数据变动时可以拿到最新值并通知订阅者。
- 实现一个解析器 Compile:用来对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦监听到数据有变动,就会通知更新视图。
- 实现一个订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observer 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。
- 实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。
27 v-model 的原理
在 vue 项目中主要使用 v-model 指令在表单 input
、textarea
、select
等元素上创建双向数据绑定,v-model 本质上就是一个、
语法糖,能够在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 元素使用 value 属性和 input 事件;
- checkbox 和 radio 使用 checked 属性和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
28 Vue 中 key 的作用
- 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。
- 如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
- key 的作用是为 Vue 中 vnode 添加唯一标记,通过 key 可以更快找到新旧 vnode 的变化,从而更高效地更新虚拟DOM。
29 VNode 是什么?虚拟 DOM 是什么?
- VNode的全称是Virtual Node,表示虚拟节点,VNode的本质是一个JavaScript的对象,用来描述如何创建真实的DOM节点,而虚拟DOM就是多个VNode形成的树结构。
- 在vue.js中,渲染视图的过程是先创建VNode,然后使用VNode生成真实的DOM元素,最后插入到页面渲染视图。
- 在数据频繁更新的时候,利用虚拟DOM通过一定的算法优化后快速渲染页面,能够有效避免真实DOM频繁更新,减少页面的回流和重绘,提高性能。
30 Diff 算法是什么?
Diff算法是一种对比算法。对比两者是旧虚拟DOM和新虚拟DOM,对比出是哪个虚拟节点更改了,找出并更新这个虚拟节点所对应的真实节点,而不用更新其他数据没发生改变的节点,实现精准地更新真实DOM,从而提高效率。
- vue 在内部通过一个叫做 patch 的函数来完成新旧虚拟DOM比对过程。vue 采用深度优先遍历,只比较同一层级,不跨层级比较,如果标签名不同,直接删除,不会继续深度比较;如果标签名相同,key相同,则认为是相同节点,不继续深度比较。
- 当数据发生变化时,会触发setter方法,并通知所有订阅者watcher调用patch方法,给真实DOM打补丁,更新相应的视图。
31 Vue 的 nextTick 的原理是什么?
作用:
nextTick 是Vue 提供的一个全局API,用于处理DOM 更新的操作。 Vue 采用异步更新策略,当监听到数据发生变化的时候不会立即去更新DOM,而是将这些操作都缓存在一个任务队列,在事件循环结束之后,刷新队列,统一执行DOM更新操作。
nextTick 接收一个回调函数作为参数,并将这个回调函数延迟到DOM更新之后再执行。
原理:
- 将传入的回调函数包装成异步任务,异步任务又分为宏任务和微任务,为了尽快执行所以优先选择微任务
- nextTick 提供了四种异步方法
Promise.then
、MutationObserver
、setImmediate
、setTimeout(fn,0)
使用场景:
- 想要操作基于最新数据生成的DOM时,就将这个操作放在nextTick 的回调中。
- 想要在created() 生命周期的created() 操作DOM,一定要放在nextTick 的回调函数中,因为此时模板还没有被渲染,无法进行DOM操作。
32 如何对 Vue 组件进行封装的?
组件封装能够把页面抽象成多个相对独立的模块,实现代码复用,提高开发效率。
- 分析需求:确定业务需求,把页面中可以复用的结构、样式以及功能,单独抽离成一个文件,实现复用。
- 具体步骤:
- 使用 Vue.component 方法注册组件,子组件需要数据,可以在 props 中接收定义,而子组件修改好数据后,想把数据传递给父组件,可以采用$emit 方法向外抛数据。
- 如果需要给组件传入模板,可以使用 slot 插槽 。
33 Vue3 和 Vue2 的区别
- 响应式原理
- 生命周期
- Vue3 支持多个根节点,Vue2 不支持
- Vue3 是组合式API (Composition API),Vue2 是选项API(Options API)
- 新增组件:
<Teleport>
传送门、<Suspense>
异步组件 - 更好的支持TypeScript
- 打包优化:引入 tree-shaking 技术打包时移除无用的代码。
34 说一下 Composition API
Composition API 是 vue3 新增的功能,比 mixin 更强大。它可以把各个功能模块独立开来,提高代码逻辑的可复用性,同时代码也更容易压缩。Composition Api将某个逻辑关注点相关的代码全都放在一个函数里,这样,当需要修改一个功能时,就不再需要在文件中跳来跳去。
setup:
setup() 函数是一个新的组件选项, 替代了 Vue2中 beforeCreated()
和 created()
生命周期函数,Vue3 中定义的 methods、watch、computed、data数据等都放在了 setup() 函数中。
ref:
ref 函数用来创建响应式数据,可以接收原始数据类型与引用数据类型。模板中可直接使用,JS中需要通过 .value
的形式才能使用。
reactive:
reactive 函数只能接收引用数据类型,模板和JS中可直接使用
readonly:
readonly 用来接收一个只读对象
computed:
- 传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象
- 传入一个拥有 get 和 set 函数的对象,创建一个可手动修改的计算状态
watch:
watch监听器,需要监听指定的数据,默认情况是懒执行的,只有监听的数据发生改变才执行回调
watchEffect
watchEffect是一个副作用函数,会立即执行,不需要指定监听的数据,依赖项发生改变就会执行回调。
35 Vue 项目优化的解决方案都有哪些?
- 路由懒加载。有效拆分应用大小,访问时才异步加载。
- keep-alive缓存页面。避免重复创建组件实例,且能保留缓存组件状态。
- 事件销毁。组件销毁后把全局变量和定时器销毁。
- 图片懒加载,小图片使用 base64
- 子组件分割。较重的状态组件适合拆分。
- 使用 mini-css-extract-plugin 插件抽离 css
- 配置 optimization 把公共的 js 代码抽离出来
- 通过 webpack 处理文件压缩
- 不打包框架、库文件,通过 cdn 的方式引入
- 开启 Gzip 压缩
- 长列表性能优化,可采用虚拟列表。