Vue.js面试题(三)https://developer.aliyun.com/article/1399431?spm=a2c6h.13148508.setting.14.3a524f0eDMRXfg
61.★★★★★ nextTick知道吗、实现的原理是什么?是宏任务还是微任务?
微任务
原理:
nextTick方法主要是使用了宏任务和微任务,定义了一个异步方法,多次调用nextTick会将方法存入队列中,通过这个异步方法清空队列。
作用:
nextTick用于下次Dom更新循环结束之后执行延迟回调,在修改数据之后使用nextTick用于下次Dom更新循环结束之后执行延迟回调,在修改数据之后使用nextTick用于下次Dom更新循环结束之后执行延迟回调,在修改数据之后使用nextTick,则可以在回调中获取更新后的DOM。
62.★★★ 介绍下vue单页面和多页面区别
单页应用 页面跳转---->js渲染 优点:页面切换快 缺点:首屏加载稍慢,seo差
多页应用 页面跳转---->返回html 优点:首屏时间快,seo效果好 缺点:页面切换慢
63.★★★★ 虚拟 dom 为什么会提高性能?
虚拟DOM其实就是一个JavaScript对象。通过这个JavaScript对象来描述真实DOM,真实DOM的操作,一般都会对某块元素的整体重新渲染,采用虚拟DOM的话,当数据变化的时候,只需要局部刷新变化的位置就好了 ,
虚拟dom相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能
具体实现步骤如下:
- 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
- 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
- 把所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新
64.★★★ Vue中key的作用?不加会怎么样?
vue中列表循环需加:key=“唯一标识” 唯一标识可以是item里面id index等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM
65.★★★ Vue的常用修饰符
v-model修饰符
1、.lazy:输入框改变,这个数据就会改变,lazy这个修饰符会在光标离开input框才会更新数据
2、.trim:输入框过滤首尾的空格
3、.number:先输入数字就会限制输入只能是数字,先字符串就相当于没有加number,注意,不是输入框不能输入字符串,是这个数据是数字
事件修饰符
4、.stop:阻止事件冒泡,相当于调用了event.stopPropagation()方法
5、.prevent:阻止默认行为,相当于调用了event.preventDefault()方法,比如表单的提交、a标签的跳转就是默认事件
6、.self:只有元素本身触发时才触发方法,就是只有点击元素本身才会触发。比如一个div里面有个按钮,div和按钮都有事件,我们点击按钮,div绑定的方法也会触发,如果div的click加上self,只有点击到div的时候才会触发,变相的算是阻止冒泡
7、.once:事件只能用一次,无论点击几次,执行一次之后都不会再执行
8、.capture:事件的完整机制是捕获-目标-冒泡,事件触发是目标往外冒泡
9、.async对prop进行双向绑定
10、.keyCode:监听按键的指令,具体可以查看vue的键码对应表
66.★★★ Vue计算属性和 Watch 的区别
methods(方法):只要进行调用就会执行,不管依赖的值有没有改变。无缓存。
computed(计算属性):监听其所有依赖的变化,如果有变化会执行,没有变化不执行。有缓存,不用每次重新算。不支持异步。
详解:在vue的 模板内({{}})是可以写一些简单的js表达式的 ,很便利。但是如果在页面中使用大量或是复杂的表达式去处理数据,对页面的维护会有很大的影响。这个时候就需要用到computed 计算属性来处理复杂的逻辑运算。
优点:在数据未发生变化时,优先读取缓存。computed 计算属性只有在相关的数据发生变化时才会改变要计算的属性,当相关数据没有变化是,它会读取缓存。而不必想 motheds方法 和 watch 方法是否每次都去执行函数。
setter 和 getter方法:(注意在vue中书写时用set 和 get)setter 方法在设置值是触发。getter 方法在获取值时触发。
watch(侦听属性):观察某一个变量,发生变化会执行。支持异步。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。
小结:
1.主动调用的方法写在methods里,依据某些变量的更新进行某种操作用computed或者watch。
2.computed和watch:如果要异步,只能用watch。如果是计算某个值推荐用computed,比如购物车全选单选功能,购物车计算总价小计功能。
67.★★★ Vue 中 v-on 可以绑定多个方法吗?
<p v-on="{click:dbClick,mousemove:MouseClick}"></p>
68.★★★ Vue 中 template 的编译过程
vue template模板编译的过程经过parse()生成ast(抽象语法树),optimize对静态节点优化,generate()生成render字符串 之后调用new Watcher()函数,用来监听数据的变化,render 函数就是数据监听的回调所调用的,其结果便是重新生成 vnode。 当这个 render 函数字符串在第一次 mount、或者绑定的数据更新的时候,都会被调用,生成 Vnode。 如果是数据的更新,那么 Vnode 会与数据改变之前的 Vnode 做 diff,对内容做改动之后,就会更新到 我们真正的 DOM
69.★★★ 说一下Vue-router守卫有哪些。如何实现路由懒加载?
router.beforeEach 全局前置守卫 进入路由之前
router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用
router.afterEach 全局后置钩子 进入路由之后
70.★★★ 简述Vue每个生命周期具体适合哪些场景
71.★★★ 什么是v-model?它的原理是什么?
- v-model本质上是一个语法糖,可以看成是value + input 方法的语法糖。可以通过model的prop属性和event事件来进行自定义。
- v-model是vue的双向绑定的指令,能将页面上控件输入的值同步更新到相关绑定的data属性, 也会在更新data绑定属性时候,更新页面上输入控件的值。
72.★★★ 简单说一下 微信小程序 与 Vue 的区别
1、生命周期:
小程序的钩子函数要简单得多 。 vue的钩子函数在跳转新页面时,钩子函数都会触发,但是小程序的钩子函数,页面不同的跳转方式,触发的钩子并不一样。
在页面加载请求数据时,两者钩子的使用有些类似,vue一般会在created或者mounted中请求数据,而在小程序,会在onLoad或者onShow中请求数据。
2、数据绑定:
vue动态绑定一个变量的值为元素的某个属性的时候,会在变量前面加上冒号:
小程序 绑定某个变量的值为元素属性时,会用两个大括号括起来,如果不加括号,为被认为是字符串
3、列表循环
4、显示与隐藏元素
vue中,使用v-if 和v-show控制元素的显示和隐藏
小程序中,使用wx-if和hidden控制元素的显示和隐藏
5、事件处理
vue:使用v-on:event绑定事件,或者使用@event绑定事件,小程序中,全用bindtap(bind+event),或者catchtap(catch+event)绑定事件
6、数据的双向绑定
在vue中,只需要再表单元素上加上v-model,然后再绑定data中对应的一个值,当表单元素内容发生变化时,data中对应的值也会相应改变 。
当表单内容发生变化时,会触发表单元素上绑定的方法,然后在该方法中,通过this.setData({key:value})来将表单上的值赋值给data中的对应值 。
7、绑定事件传参
在vue中,绑定事件传参挺简单,只需要在触发事件的方法中,把需要传递的数据作为形参传入就可以了
在小程序中,不能直接在绑定事件的方法中传入参数,需要将参数作为属性值,绑定到元素上的data-属性上,然后在方法中,通过e.currentTarget.dataset.*的方式获取
8、父子组件通信
父组件向子组件传递数据,只需要在子组件通过v-bind传入一个值,在子组件中,通过props接收,即可完成数据的传递
父组件向子组件通信和vue类似,但是小程序没有通过v-bind,而是直接将值赋值给一个变量 在子组件properties中,接收传递的值
73.★★★ Vue的组件通信
1、props和$emit
父组件向子组件传递数据是通过prop传递的,子组件传递数据给父组件是通过$emit触发事件
2、a t t r s 和 attrs和attrs和listeners
3、中央事件总线 bus
上面两种方式处理的都是父子组件之间的数据传递,而如果两个组件不是父子关系呢?这种情况下可以使用中央事件总线的方式。新建一个Vue事件bus对象,然后通过bus.e m i t 触发事件, b u s . emit触发事件,bus.emit触发事件,bus.on监听触发的事件。
4、provide和inject
父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。
5、v-model
父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit(‘input’,val)自动修改v-model绑定的值
6、p a r e n t 和 parent和parent和children
7、boradcast和dispatch
8、vuex处理组件之间的数据交互 如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。
74.★★★ 谈谈你对Vue3.0有什么了解?
一、六大亮点
性能比vue2.x快1.2~2倍
支持tree-shaking,按需编译,体积比vue2.x更小
支持组合API
更好的支持TS
更先进的组件
二、性能比vue2.x快1.2~2倍如何实现的呢
1.diff算法更快
vue2.0是需要全局去比较每个节点的,若发现有节点发生变化后,就去更新该节点
vue3.0是在创建虚拟dom中,会根据DOM的的内容会不会发生内容变化,添加静态标记, 谁有flag!比较谁。
2、静态提升
vue2中无论元素是否参与更新,每次都会重新创建,然后再渲染 vue3中对于不参与更新的元素,会做静态提升,只被创建一次,在渲染时直接复用即可
3、事件侦听缓存
默认情况下,onclick为动态绑定,所以每次都会追踪它的变化,但是因为是同一函数,没有必要追踪变化,直接缓存复用即可
在之前会添加静态标记8 会把点击事件当做动态属性 会进行diff算法比较, 但是在事件监听缓存之后就没有静态标记了,就会进行缓存复用
三、为什么vue3.0体积比vue2.x小
在vue3.0中创建vue项目 除了vue-cli,webpack外还有 一种创建方法是Vite Vite是作者开发的一款有意取代webpack的工具,其实现原理是利用ES6的import会发送请求去加载文件的特性,拦截这些请求,做一些预编译,省去webpack冗长的打包时间
四、vue3.0组合API
说一说vue3.0的组合API跟之前vue2.0在完成业务逻辑上的区别:
在vue2.0中: 主要是往data 和method里面添加内容,一个业务逻辑需要什么data和method就往里面添加,而组合API就是 有一个自己的方法,里面有自己专注的data 和method。
再说一下组合API的本质是什么: 首先composition API(组合API) 和 Option API(vue2.0中的data和method)可以共用 composition API(组合API)本质就是把内容添加到Option API中进行使用
五、ref和reactive的简单理解
1.ref和reactive都是vue3的监听数据的方法,本质是proxy
2.ref 基本类型复杂类型都可以监听(我们一般用ref监听基本类型),reactive只能监听对象(arr,json)
3.ref底层还是reactive
六、对生命周期的监听(ref获取属性)
七、proxy响应式本质
75.★★★ Vue如何在用户没登陆的时候重定向登录界面?
现在 我们需要实现这样 一个功能,登录拦截,其实就是 路由拦截,首先在定义路由的时候就需要多添加一个自定义字段requireAuth,用于判断该路由的访问是否需要登录。如果用户已经登录,则顺利进入路由, 否则就进入登录页面。在路由管理页面添加meta字段
{ path:'/manage', name:'manage', component:manage, meta:{requireAuth:true} }
在入口文件中,添加路由守卫
1、先判断该路由是否需要登录权限
2、判断本地是否存在token,如果存在token就next(),不存在token重定向到登录页
76.★★★★★ Vue项目常见优化点
1、首屏加载优化
2、路由懒加载
{ path: '/', name: 'home', component: () => import('./views/home/index.vue'), meta: { isShowHead: true } }
3、开启服务器 Gzip
开启 Gzip 就是一种压缩技术,需要前端提供压缩包,然后在服务器开启压缩,文件在服务器压缩后传给浏览器,浏览器解压后进行再进行解析。首先安装 webpack 提供的compression-webpack-plugin进行压缩,然后在 vue.config.js:
const CompressionWebpackPlugin = require('compression-webpack-plugin') const productionGzipExtensions = ['js', 'css']......plugins: [ new CompressionWebpackPlugin( { algorithm: 'gzip', test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), threshold: 10240, minRatio: 0.8 } )]....
4、启动 CDN 加速
我们继续采用 cdn 的方式来引入一些第三方资源,就可以缓解我们服务器的压力,原理是将我们的压力分给其他服务器点。
5、代码层面优化
- computed 和 watch 区分使用场景
computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值。当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
watch:类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
- v-if 和 v-show 区分使用场景 v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。这里要说的优化点在于减少页面中 dom 总数,我比较倾向于使用 v-if,因为减少了 dom 数量。
- v-for 遍历必须为 item 添加 key,且避免同时使用 v-if v-for 遍历必须为 item 添加 key,循环调用子组件时添加 key,key 可以唯一标识一个循环个体,可以使用例如 item.id 作为 key 避免同时使用 v-if,v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度。
6、Webpack 对图片进行压缩
7、避免内存泄漏
8、减少 ES6 转为 ES5 的冗余代码
77.★★★ Vuex和redux有什么区别?他们的共同思想。
Redux和Vuex区别
- Vuex改进了Redux中的Action和Reducer函数,以mutations变化函数取代Reducer,无需switch,只需在对应的mutation函数里改变state值就可以
- Vuex由于Vue自动重新渲染的特性,无需订阅重新渲染函数,只要生成新的state就可以
- Vuex数据流的顺序是:View调用store.commit提交对应的请求到Store中对应的mutation函数 – store改变(vue检测到数据变化自动渲染)
共同思想
- 单一的数据源
- 变化可以预测
- 本质上:Redux和Vuex都是对MVVM思想的服务,将数据从视图中抽离的一种方案
- 形式上:Vuex借鉴了Redux,将store作为全局的数据中心,进行数据管理