当前位置:   article > 正文

vue常见面试题_vue面试常考

vue面试常考

目录

 

v-if与v-show的区别:

对MVVM开发模式的理解:

VUE组件data为什么必须是函数

methods,computed,watch

为何要在v-for中使用key

描述Vue组件生命周期(父子组件)

vue组件如何通讯

描述组件和渲染的过程

何时要使用beforeDestory

什么是作用域插槽

Vuex中action和mutation有何区别:

vue-router常用的路由模式

如何配置vue-router异步加载

请用vnode描述一个DOM结构

监听data变化的核心的API是什么?

请描述响应式原理

简述diff算法过程

Vue为何是异步渲染,$nextTick何用

Vue常见性能优化:


v-if与v-show的区别:

  • v-showv-show通过CSS dispaly控制显示和隐藏
  • v-if组件真正的渲染和销毁,而不是显示和隐藏
  • 频繁切换状态使用v-show,否则使用v-if

对MVVM开发模式的理解:

  • Model 代表数据模型,数据和业务逻辑都在Model层中定义;
  • View 代表UI视图,负责数据的展示;
  • ViewModel 负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作
  •  Model 中的数据改变时会触发 View 层的刷新,View 中由于用户交互操作而改变的数据也会在 Model 中同步

VUE组件data为什么必须是函数

  • vue组件可能存在多个实例,如果使用对象形式定义data,则会导致它们共用一个data对象,那么状态变更将会影响所有组件实例,这是不合理的

methods,computed,watch

  • computed:可以进行缓存,只有在它的相关依赖发生改变时才会重新计算值,常适用于与一个数据受多个数据影响
  • method:只要发生重新渲染,methods调用总会执行该函数
  • watch:一般用于一个数据影响多个数据,或者在数据变化时来执行异步操作

为何要在v-for中使用key

  • 必须使用key,且不能是index和random
  • diff算法中通过tag和key来判断,是否sanmeNode
  • 减少渲染次数,提升渲染性能(如果发现是sameNode,那么会将node的位置进行移动)

描述Vue组件生命周期(父子组件)

  • beforeCreate(创建前) 在数据观测和初始化事件还未开始
  • created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来
  • beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
  • mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
  • beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
  • updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
  • beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
  • destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

vue组件如何通讯

  • 父子组件传值:父组件给子组件传值,子组件通过props进行接受;子组件向父组件传值,通过$emit方法传递参数,在父组件中穿件子组件时,需要监听$emit的事件
  • 兄弟组件传值:eventBus,创建一个事件中心(是new的一个vue实例),通过event.$on和$event.$emit发布订阅的方式实现通讯,可参考(vue - 组件之间的通信
  • vuex

描述组件和渲染的过程

  • 初次渲染:
    • 解析模板为render函数(或在开发环境下已完成,vue-loader)
    • 触发响应式,监听data属性,setter和getter
    • 执行render函数,返回生成vnode,再执行patch(elem, vnode),页面渲染(在执行render函数时,就已经执行了data的getter,但不会引起视图变化的不会触发get) 
  • 更新过程
    • 修改data,触发setter(此前在getter中已被监听)
    • 重新执行render函数,生成newVnode
    • 执行patch(vnode, newVnode)
  • 流程图参考如下:

 

何时要使用beforeDestory

  • 解绑自定义事件event.$off
  • 清除定时器
  • 解绑自定义的DOM事件,如window scroll等

什么是作用域插槽

  • 作用域插槽给了子组件将数据返回组组件的能力,子组件一样可以复用,同时父组件也可以重新组织内容和样式
  • 一下是一个简单的demo:

Vuex中action和mutation有何区别:

  • action处理异步,mutation不可以
  • mutation专注于修改state,而action是提交的mutation,而不直接变更状态
  • action可以整合多个mutation

vue-router常用的路由模式

  • hash(默认):hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误
  • H5 history:且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误

如何配置vue-router异步加载

 

请用vnode描述一个DOM结构

监听data变化的核心的API是什么?

  • Object.defineProperty
  • Object.defineProperty有和缺点
    • 深度监听,需要递归到底,计算量大
    • 对删除的属性和新增的属性无法实现监听,需要使用Vue.set和Vue.delete
    • 无法监听数组,需要特殊处理
  • 实现如下:该实现通过重写数组的常用方法实现数组的监听
  1. const data = {
  2. name: 'zhangsan',
  3. age:21,
  4. info: {
  5. address: 'BeiJing'
  6. },
  7. num: [1,2,3]
  8. }
  9. // 重新定义数组的原型,不建议直接重写数组的方法,否则就会污染全局的原型方法
  10. let oldArrayProperty = Array.prototype;
  11. var arrProto = Object.create(oldArrayProperty);
  12. ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {
  13. arrProto[methodName] = function(){
  14. updateView ();
  15. oldArrayProperty[methodName].call(this, ...arguments);
  16. }
  17. })
  18. function updateView(){
  19. console.log('update view');
  20. }
  21. function observer(target){
  22. if (typeof target !== 'object' || target === null){
  23. return target;
  24. }
  25. if (Array.isArray(target)){
  26. target.__proto__ = arrProto;
  27. }
  28. for (let key in target){
  29. defineReactive(target, key, target[key])
  30. }
  31. }
  32. function defineReactive(target, key, value){
  33. // 深度监听
  34. observer(value);
  35. Object.defineProperty(target, key, {
  36. get(){
  37. return value
  38. },
  39. set(newValue){
  40. // 设置的新值可能还是一个object
  41. observer(newValue);
  42. if (newValue !== value){
  43. value = newValue
  44. updateView();
  45. }
  46. }
  47. })
  48. }
  49. // 执行observer必须等数组方法重写后进行监听
  50. observer(data);
  51. data.name = 'lisi';
  52. data.age = 20;
  53. data.info.address = 'ShangHai';
  54. data.num.push(4)

请描述响应式原理

  • 当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为 getter/setter,在属性被访问和修改时通知变化。
  • 每个组件实例都有相应的 watcher 程序实例,当data发生变化是,之后setter 被调用,会通知 watcher 重新计算,从而执行render函数,致使它关联的组件得以更新。
  • 可参考上面题目的流程图:“描述组件和渲染的过程”

简述diff算法过程

  • patch函数:patch(elem, vnode)   和   patch(vnode, newVnode)
    • 当第一个参数不是vnode时,创建一个空的vnode关联到dom元素上
    • 当两个vnode不一致时,创建新的vnode,将旧的vnode删除
    • 当两个vnode一致时,执行patchVnode函数
  • patchVnode函数:
    • 该函数主要用于对旧vnode和新vnode中的children进行对比,从而进行对应操作
    • 当旧vnode的children和新vnode的children同时存在,执行updateChildren
    • 当新的children有,旧的text有,那么将旧的vnode的text设置为空,添加新的children
    • 当新的children无,旧的children有,删除旧的children
    • 当新的vnode有text时,且不等于旧的vnode的text时,将旧的children移除,设置新的text
  • updateChildren
    • 该函数主要用于对children进行更新,分别从旧的children和新的children中每一项对比,如果有发现同样的vnode,那么再次执行patcVnode函数
  • sameVnode:
    • 用于判断是否是相同的vnode,通过key和sel进行比较,这也是为什么for循环中一定要有key

Vue为何是异步渲染,$nextTick何用

  • 异步渲染(以及合并data修改),以提高渲染性能,否则每次更新数据都会对当前组件进行重新渲染
  • $nextTick用于在DOM更新完之后,触发回调

keep-alive

  • keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们
  • 属性:
    • include:  字符串或正则表达式,只有名称匹配的组件会被缓存
    • exclude: 字符串或正则表达式,名称匹配的组件不会被缓存》
    • max:     数字,最多可以缓存多少组件实例
  • 生命周期:
    • activated和deactivated会在keep-alive树内所有嵌套的组件中触发
        如:B页面是缓存页面
          当A页面跳到B页面时,B页面的生命周期:activated(可在此时更新数据)
          B页面跳出时,触发deactivated
          B页面自身刷新时,会触发created-mouted-activated

  •  router.meta 属性来实现

  1. export default {
  2. name: 'hello',
  3. //keep-alive钩子函数:组件被激活时调用
  4. activated() {
  5. console.log('首页被激活');
  6. },
  7. //keep-alive钩子函数:组件消失,被缓存时调用
  8. deactivated() {
  9. console.log('首页被缓存');
  10. },
  11. beforeRouteLeave(to, from, next) {
  12. //设置下一个路由的meta(即首页)
  13. to.meta.keepAlive = true; // 让首页缓存,即不刷新
  14. next();
  15. }
  16. }

Vue常见性能优化:

  • 合理使用v-if和v-show
  • 合理使用computed
  • v-for加key,以及避免和v-if同时使用(v-for比v-if的优先级高,所以每次都要v-for之后再v-if,所以避免使用)
  • 自定义事件,DOM事件,定时即使销毁
  • 合理使用异步组件
  • 合理使用keep-alive(对需要进行缓存的时候keep-alive)
  • data层级不要太深
  • webpack层面的性能优化

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/164550
推荐阅读
相关标签
  

闽ICP备14008679号