• 2019 前端面试题汇总(主要为 Vue)


    原文链接:点我

    由于我的技术栈主要为Vue,所以大部分题目都是Vue开发相关的。

    1. 谈谈你对MVVM开发模式的理解

    MVVM分为Model、View、ViewModel三者。

    • Model:代表数据模型,数据和业务逻辑都在Model层中定义;

    • View:代表UI视图,负责数据的展示;

    • ViewModel:负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作;

    Model和View并无直接关联,而是通过ViewModel来进行联系的,Model和ViewModel之间有着双向数据绑定的联系。因此当Model中的数据改变时会触发View层的刷新,View中由于用户交互操作而改变的数据也会在Model中同步。

    这种模式实现了Model和View的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作dom。

    2. Vue 有哪些指令?

    v-html、v-show、v-if、v-for等等。

    3. v-if 和 v-show 有什么区别?

    v-show 仅仅控制元素的显示方式,将 display 属性在 block 和 none 来回切换;而v-if会控制这个 DOM 节点的存在与否。当我们需要经常切换某个元素的显示/隐藏时,使用v-show会更加节省性能上的开销;当只需要一次显示或隐藏时,使用v-if更加合理。

    4. 简述Vue的响应式原理

    当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的watcher程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。

    5. Vue中如何在组件内部实现一个双向数据绑定?

    假设有一个输入框组件,用户输入时,同步父组件页面中的数据。

    具体思路:父组件通过props传值给子组件,子组件通过 $emit 来通知父组件修改相应的props值,具体实现如下:

     1 import Vue from 'vue'
     2 
     3  
     4 
     5 const component = {
     6 
     7  props: ['value'],
     8 
     9  template: `
    10 
    11    <div>
    12 
    13      <input type="text" @input="handleInput" :value="value">
    14 
    15    </div>
    16 
    17  `,
    18 
    19  data () {
    20 
    21    return {
    22 
    23    }
    24 
    25  },
    26 
    27  methods: {
    28 
    29    handleInput (e) {
    30 
    31      this.$emit('input', e.target.value)
    32 
    33    }
    34 
    35  }
    36 
    37 }
    38 
    39  
    40 
    41 new Vue({
    42 
    43  components: {
    44 
    45    CompOne: component
    46 
    47  },
    48 
    49  el: '#root',
    50 
    51  template: `
    52 
    53    <div>
    54 
    55      <comp-one :value1="value" @input="value = arguments[0]"></comp-one>
    56 
    57    </div>
    58 
    59  `,
    60 
    61  data () {
    62 
    63    return {
    64 
    65      value: '123'
    66 
    67    }
    68 
    69  }
    70 
    71 })

    可以看到,当输入数据时,父子组件中的数据是同步改变的:

    我们在父组件中做了两件事,一是给子组件传入props,二是监听input事件并同步自己的value属性。那么这两步操作能否再精简一下呢?答案是可以的,你只需要修改父组件:

     1 template: `
     2 
     3    <div>
     4 
     5      <!--<comp-one :value1="value" @input="value = arguments[0]"></comp-one>-->
     6 
     7      <comp-one v-model="value"></comp-one>
     8 
     9    </div>
    10 
    11  `

    v-model 实际上会帮我们完成上面的两步操作。

    6. Vue中如何监控某个属性值的变化?

    比如现在需要监控data中, obj.a 的变化。Vue中监控对象属性的变化你可以这样:

     1 watch: {
     2 
     3      obj: {
     4 
     5      handler (newValue, oldValue) {
     6 
     7        console.log('obj changed')
     8 
     9      },
    10 
    11      deep: true
    12 
    13    }
    14 
    15  }

    deep属性表示深层遍历,但是这么写会监控obj的所有属性变化,并不是我们想要的效果,所以做点修改:

     1 watch: {
     2 
     3   'obj.a': {
     4 
     5      handler (newName, oldName) {
     6 
     7        console.log('obj.a changed')
     8 
     9      }
    10 
    11   }
    12 
    13  }

    还有一种方法,可以通过computed 来实现,只需要:

    
    
    1. computed: {

    2.    a1 () {

    3.      return this.obj.a

    4.    }

    5. }

     

    利用计算属性的特性来实现,当依赖改变时,便会重新计算一个新值。

    7. Vue中给data中的对象属性添加一个新的属性时会发生什么,如何解决?

    示例:

     1 <template>
     2 
     3  <div>
     4 
     5    <ul>
     6 
     7      <li v-for="value in obj" :key="value">
     8 
     9        {{value}}
    10 
    11      </li>
    12 
    13    </ul>
    14 
    15    <button @click="addObjB">添加obj.b</button>
    16 
    17  </div>
    18 
    19 </template>
    20 
    21 <script>
    22 
    23 export default {
    24 
    25  data () {
    26 
    27    return {
    28 
    29      obj: {
    30 
    31        a: 'obj.a'
    32 
    33      }
    34 
    35    }
    36 
    37  },
    38 
    39  methods: {
    40 
    41    addObjB () {
    42 
    43      this.obj.b = 'obj.b'
    44 
    45      console.log(this.obj)
    46 
    47    }
    48 
    49  }
    50 
    51 }
    52 
    53 </script>
    54 
    55 <style></style>

    点击button会发现, obj.b 已经成功添加,但是视图并未刷新:

    原因在于在Vue实例创建时, obj.b 并未声明,因此就没有被Vue转换为响应式的属性,自然就不会触发视图的更新,这时就需要使用Vue的全局api—— $set()

    1 addObjB () {
    2 
    3      // this.obj.b = 'obj.b'
    4 
    5      this.$set(this.obj, 'b', 'obj.b')
    6 
    7      console.log(this.obj)
    8 
    9    }

    $set() 方法相当于手动的去把 obj.b 处理成一个响应式的属性,此时视图也会跟着改变了:

    8. delete和Vue.delete删除数组的区别

    delete只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。

    Vue.delete 直接删除了数组 改变了数组的键值

     1  var a=[1,2,3,4]
     2 
     3    var b=[1,2,3,4]
     4 
     5    delete a[1]
     6 
     7    console.log(a)
     8 
     9    this.$delete(b,1)
    10 
    11    console.log(b)

    9.如何优化SPA应用的首屏加载速度慢的问题?

    • 将公用的JS库通过script标签外部引入,减小 app.bundel 的大小,让浏览器并行下载资源文件,提高下载速度;

    • 在配置 路由时,页面和组件使用懒加载的方式引入,进一步缩小 app.bundel 的体积,在调用某个组件时再加载对应的js文件;

    • 加一个首屏loading图,提升用户体验;

    10. 前端如何优化网站性能?

    1、减少 HTTP 请求数量

    在浏览器与服务器进行通信时,主要是通过 HTTP 进行通信。浏览器与服务器需要经过三次握手,每次握手需要花费大量时间。而且不同浏览器对资源文件并发请求数量有限(不同浏览器允许并发数),一旦 HTTP 请求数量达到一定数量,资源请求就存在等待状态,这是很致命的,因此减少 HTTP 的请求数量可以很大程度上对网站性能进行优化。

    CSS Sprites

    国内俗称CSS精灵,这是将多张图片合并成一张图片达到减少HTTP请求的一种解决方案,可以通过CSS的background属性来访问图片内容。这种方案同时还可以减少图片总字节数。

    合并 CSS 和 JS 文件

    现在前端有很多工程化打包工具,如:grunt、gulp、webpack等。为了减少 HTTP 请求数量,可以通过这些工具再发布前将多个CSS或者多个JS合并成一个文件。

    采用 lazyLoad

    俗称懒加载,可以控制网页上的内容在一开始无需加载,不需要发请求,等到用户操作真正需要的时候立即加载出内容。这样就控制了网页资源一次性请求数量。

    2、控制资源文件加载优先级

    浏览器在加载HTML内容时,是将HTML内容从上至下依次解析,解析到link或者script标签就会加载href或者src对应链接内容,为了第一时间展示页面给用户,就需要将CSS提前加载,不要受 JS 加载影响。

    一般情况下都是CSS在头部,JS在底部。

    3、利用浏览器缓存

    浏览器缓存是将网络资源存储在本地,等待下次请求该资源时,如果资源已经存在就不需要到服务器重新请求该资源,直接在本地读取该资源。

    4、减少重排(Reflow)

    基本原理:重排是DOM的变化影响到了元素的几何属性(宽和高),浏览器会重新计算元素的几何属性,会使渲染树中受到影响的部分失效,浏览器会验证 DOM 树上的所有其它结点的visibility属性,这也是Reflow低效的原因。如果Reflow的过于频繁,CPU使用率就会急剧上升。

    减少Reflow,如果需要在DOM操作时添加样式,尽量使用 增加class属性,而不是通过style操作样式。

    5、减少 DOM 操作
    6、图标使用 IconFont 替换

    11. 网页从输入网址到渲染完成经历了哪些过程?

    大致可以分为如下7步:

    1. 输入网址;

    2. 发送到DNS服务器,并获取域名对应的web服务器对应的ip地址;

    3. 与web服务器建立TCP连接;

    4. 浏览器向web服务器发送http请求;

    5. web服务器响应请求,并返回指定url的数据(或错误信息,或重定向的新的url地址);

    6. 浏览器下载web服务器返回的数据及解析html源文件;

    7. 生成DOM树,解析css和js,渲染页面,直至显示完成;

    12. jQuery获取的dom对象和原生的dom对象有何区别?

    js原生获取的dom是一个对象,jQuery对象就是一个数组对象,其实就是选择出来的元素的数组集合,所以说他们两者是不同的对象类型不等价。

    原生DOM对象转jQuery对象:

    1 var box = document.getElementById('box');
    2 
    3 var $box = $(box);

    jQuery对象转原生DOM对象:

    1 var $box = $('#box');
    2 
    3 var box = $box[0];

    13. jQuery如何扩展自定义方法

     1 (jQuery.fn.myMethod=function () {
     2 
     3       alert('myMethod');
     4 
     5 })
     6 
     7 // 或者:
     8 
     9 (function ($) {
    10 
    11        $.fn.extend({
    12 
    13             myMethod : function () {
    14 
    15                  alert('myMethod');
    16 
    17             }
    18 
    19        })
    20 
    21 })(jQuery)

    使用:

    $("#div").myMethod();
    

      

  • 相关阅读:
    day 28 客户端服务端架构介绍,互联网协议,互联网协议补充,三次握手与四次挥手
    day25 单例模式实现方法一 单例模式实现方法二
    day24 反射/定制__str__方法控制对象的打印格式/定制__del__方法回收系统资源/元类介绍以及默认元类type创造类的过程/自定义元类控制类的创建过程/自定义元类控制类的调用过程
    day 23 封装之如何隐藏、封装之隐藏属性的底层原理、封装的真正意义、property特性、绑定方法与非绑定方法
    day22 组合、菱形继承问题、C3算法与mro介绍、在子类派生的新方法中重用父类功能的两种方式、super()严格以来继承关系、多态与鸭子类型
    day21 对象定制自己独有的属性/属性查找/绑定方法/小结/继承介绍/继承与派生
    day19 正泽表达式,sys模块,打印进度条,subprocess模块
    day18 logging模块的补充/jason序列化与反序列化/json补充/pickle序列化与反序列化/time模块/datetime模块/random模块/os模块
    day17 包的使用 logging模块的基本用法
    day16 面向过程编程/模块介绍/import导入模块/ from...import导入模块/循环导入问题/模块的搜索路径/区分python文件的两种用途/软件开发的目录规范
  • 原文地址:https://www.cnblogs.com/myfate/p/10552863.html
Copyright © 2020-2023  润新知