Vue相关知识点
13、如何自己实现v-model?以及双向数据绑定v-model的实现原理
17、多个层级间重用相同的props时,避免每个层级重复定义相通的props,如何将组件所有props传递给子组件?
23、vuex 中 action 和 mutation 区别
24、 Vue-router 常用的路由模式?以及他们实现的原理? hash 和 history两者有何区别?如何配置vue-router异步加载?
26、监听data 变化的核心API是什么?如何深度监听、监听数组?有何缺点?
28、diff算法时间复杂度?
Vue的优点(优势)是什么?
- 轻量级框架:大小只有几十kb
- 简单易学:国人开发,中文文档,易于理解和学习
- 双向数据绑定:通过MVVM思想实现数据的双向绑定
- 组件化模式:提高代码利用率,且让代码更好维护
- 使用虚拟DOM:原生js对DOM频繁操作时,浏览器会不停地渲染新的DOM,导致页面非常卡顿。vue是预先通过js进行各种计算把最总得DOM操作计算出来并优化,最后在计算完毕才真正将DOM操作变化反应到DOM树上
- 单页面应用:提升用户体验,页面局部刷新,不用每次跳转都重新加载页面,加快了访问速度
- vue第三方UI库很多,节省开发时间 (饿了吗的element-ui,有赞的vant,滴滴公司的cube-ui等等)
说说你对SPA单页面的理解,它的优缺点是什么
SPA是什么?
单页面应用SPA(single-page-application)是将所有的活动都局限于一个web页面中,在该页面初始化时加载相应的html、javascript和css。一旦加载完成,页面不会因为用户的操作而尽心页面的重载或者跳转,取而代之的是利用JavaScript动态变化HTML的内容,从而实现UI与用户交互
SAP优点:快,内容的改变不需要重新加载整个页面。用户体验好
SAP缺点:
1.首次加载时间过长
2.不利于SEO(搜索引擎)抓取。由于所有内容都是在一个页面中动态显示,所以在搜索引擎上有天然的弱势
Vue框架的MVVM模式
1.M:模型(model): vue中的data,为一个对象
2.V:视图(view):模板代码
3.VM:视图模型(viewmodel):为Vue的实例,即new Vue()。所以我们通常把Vue的实例定义为vm 即const vm = new Vue()
用网上一张图来表示会更清晰一些
简单来说,数据Model变化会通过ViewModel处理(实现方法:数据绑定)后展示到页面上。操作页面DOM后,会通过ViewModel处理(实现方式:DOM监听)将数据Model进行改变
Vue中computed和watch的区别,以及适用场景
一:computed:计算属性
-
- computed 用于计算产生出新的数据
- 支持缓存,只有依赖数据发生改变,才会重新进行计算(methods中没有缓存,多次调用仍会重新计算)
- 不支持异步
- 场景:
- 当多个属性影响一个属性的时候
- 一个数据需要经过复杂计算
二:watch:监听属性
-
- watch 用于监听现有数据
- 不支持缓存,数据变化,会直接触发相应的操作
- 支持异步操作
- 场景:
- 当一个属性变化影响了多个属性的变化
- 一个属性发生变化后,需要执行某些具体业务逻辑操作,或者需要执行异步操作的情况
Vue生命周期有哪些?每个生命周期适合那些场景?
1.创建beforeCreate:vue实例创建前,此时props,data,computed,watch,methods上的方法均不能访问。
适用场景:添加loading事件
2.创建后created:vue实例创建完成,props,data,methods,watch,computed都初始化完成,可以访问了
适用场景:1)请求数据2)结束loading事件
3.挂载前beforeMount:模板挂载到页面前,此时vue已经将模板字符串编译成内存虚拟DOM,模板已经版已完成,已经完成了渲染树,还没有渲染到页面上
4.挂载后mounted:模板挂载到页面后,DOM渲染完成。可以后取到DOM节点
适用场景:1)请求数据 2)获取dom节点
5.更新前beforeUpdate:修改数据的时候,更新渲染视图之前会触发
6.更新后updated:修改数据的时候,更新渲染视图之后触发
7.销毁前beforeDestory:销毁组件之前,此时data,methods,cumputed,watch 都处于可用状态
适合场景:销毁定时器
8.销毁后destroyed:销毁组件后,此时组件中的数据data,methods,watch,computed都不可用
vue第一次页面加载会触发哪些钩子函数
beforeCreated 、created 、beforeMounted 、mounted
请求数据放到created和mounted那个阶段比较好?
请求数据放到created阶段比较好,因为这个时候数据观测完毕。若在mounted阶段可能会发出现闪屏问题
父子组件生命周期的顺序
1.渲染过程
父 beforeCreate -> 父 created ->父 beforeMount ->子 beforeCreated -> 子 cerated -> 子 beforeMount ->子mounted ->父 mounted
2.更新过程
父 beforeUpate -> 子 beforeUpdate -> 子 updated ->父 updated
3.销毁过程
父 beforeDestory ->子 beforeDestory -> 子 destoryed -> 父 destoryed
注:规律就是父组件要等子组件加载完成才能完,所以开始阶段是父组件先加载开始执行,然后等到子组件执行完成,父组件收尾。
如果是子组件是异步组件的话,他们的执行书序会发生变化。会先执行完父组件的生命周期然后再执行子组件的生命周期。
父组件如何监听子组件的生命周期
方法一:子组件通过$emit 发布事件,父组件绑定自定义事件监听
子组件:
export default{ ... mounted(){ this.$emit('mounted','mounted 触发了') } }
父组件:
1 2 3 4 5 6 7 8 9 10 11 12 | <child @mounted= "doSomething" > export default { ... methods:{ doSomething(data){ console.log( '监听到子组件的生命周期钩子函数mounted时,触发该回调' ,data) } }, components:{ child } } |
方法二:使用@hook:钩子函数名=“函数名”
@hook可以监听到子组件的任何生命周期
父组件:
1 2 3 4 5 6 7 8 9 10 11 12 | <child @hook:mounted= "doSomething" > export default { ... methods:{ doSomething(){ console.log( '监听到子组件的生命周期钩子函数mounted时,触发该回调' ) } }, components:{ child } } |
-
- v-if 只有条件为true时才会渲染;v-show无论条件真假都会被渲染,只是为元素添加了display:none
- 切换时,v-if条件区块内的事件监听和组件都会被销毁或者重建;而v-show是通过css中的display 控制显示和隐藏
- v-if 由false变为true时,触发组件的beforeCreate、create、beforeMount、mounted等钩子。有true 变为false时,触发了beforeDestory、destoryed等钩子方法
- v-show 切换不会触发组件的生命周期
- v-if 有更高的切换消耗;v-show 有更高的初始渲染消耗
-
- 必须用key,且不能是index 和 random
- diff 算法中通过 tag和 key来判断是否是相同的节点 sameNode
- 可以减少渲染次数,提升渲染性能
- 缓存,data不变不会重新计算
- 提高性能
-
- 避免数据共享
- 我们知道在JS中,对象是引用类型,变量保存的是对象的内存地址
- 所以如果data是对象,多个组件实例会共享同一份数据,实例间修改数据将互相影响
- 数据隔离和独立性
- 我们知道在JS中,函数返回值在每次调用函数都会返回新的内存空间
- 所以,如果data是函数,则每个组件实例都调用data函数,返回全新的对象。从而确保每个组件实例都拥有自己的独立数据,实现数据隔离
- 避免数据共享
十七、多个层级间重用相同的props时,避免每个层级重复定义相通的props,如何将组件所有props传递给子组件?
如果想将一个组件的所有props传递给子组件,可以使用 v-bind="$attrs"
-
- 使用 v-bind="$attrs"
<template> <ChildComponent v-bind="$attrs" /> </template>
- 该方法在某些情况下很有用,比如想在父组件中定义一些props,然后在子组件中将这些props传递给下一个子组件
- 如果子组件也接收了相同的prop,那么父组件传递给子组件的prop将会覆盖子组件内部定义的prop
- 使用 v-bind="$attrs"
-
- 使用mixin混入 进行逻辑抽离
- mixin 并不是完美的解决方案,会有一些问题
-
- 加载大组件时使用异步组件
- 在路由中使用异步加载
-
- 缓存组件,不需要重复渲染
- 多个静态 tab页的切换
- 使用keep-alive 可以优化性能
-
- 解绑自定义事件 event.$off
- 清除定时器
- 解绑自定义的DOM事件,如window scroll 等等
二十三、vuex 中 action 和 mutation 区别
-
- action 中处理异步,mutation不可以
- mutation 做原子操作,即每次只可以做一个操作
- action 可以整合多个 mutation
vue.js 响应式原理是其核心之一,它使得数据和试图能自动保持同步。vue实现这一功能主要通过一下几个关键技术:
- 1. 数据劫持(Observer)
- new Vue 一个实例时,会将 data 选项返回的对像进行初始化,vue会遍历所有属性,使用Object.defineProperty()方法将它们转化为getter/setter
- 这样当属性被访问或者修改时就会触发响应的依赖更新
- 2.依赖收集(Dep)
- 组件在渲染过程中,会执行render函数生成Vnode
- 执行render函数的同时,每当遇到一个模板中用到的响应式数据, 会触发getter。
- 在getter中,会调用dep.depend() 实现依赖收集
- vue 就会将当前的Watcher(一个观察者对象)添加到这个数据的依赖集合中。这个过程称之为依赖收集
- 3.派发更新(Watcher)
- 当响应式数据发生变化时,其中setter会被触发
- 在setter 中会调用 dep.notify() 通知依赖于该数据的watcher
- watcher 会执行它们绑定的回调函数,通常是组件的重新渲染
- 4.虚拟DOM (virtual DOM)
- vue 使用虚拟DOM来优化DOM的更新过程
- 当组件数据发生变化,执行重新渲染函数,会生成一个新的虚拟DOM 3
- 新旧虚拟DOM树进行diff比较,计算出最小更新范围
- 5.组件更新队列(Next Tick)
- 为了优化性能,vue维护了一个队列来收集需要更新的组件
- 在某个时间点,例如事件循环的下一个tick,vue 会批量执行这些更新操作,可以避免不必要的多次重绘和回流
-
- diff算法降低了复杂度,从O(n^3) 降低到O(n)
- 就提优化方案:
- 只比较同一层级,不跨级比较
- tag不相同 或者 tag相同但key不同 ,则认为是不同的节点,删掉重新创建
- tag和key都相同,则认为是相同节点。不在深度比较
- 异步渲染可以合并多次 data修改,统一更新,提高了渲染性能
- $nextTick 在DOM 更新完成之后触发回调,这样就可以获取到新的DOM元素了
-
- 合理使用v-if 和 v-show
- 合理使用computed,computed有缓存功能提高性能
- v-for 加key,以及避免与v-if同时在同一个元素中使用
- 自定义事件、自定义DOM事件要及时销毁。否则会出现内存泄漏
- 合理使用异步组件,大组件可以使用异步组件
- 合理使用keep-alive,不需要重复渲染的时候可以使用,例如静态的tab页切换效果
- data层级不要太深,尽量扁平一些
- 使用vue-loader 在开发环境做模板编译(预编译)
- webpack层面的优化
- 前端通用的性能优化,如图片懒加载
- 使用SSR,即服务端渲染,有效地缩短页面的可见时间
三十二、
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南