1

最近在找工作,记录一下遇到的面试题和我整理后的答案。

- vue

  1. vue-router知道吗?有哪几种不同的模式?
    https://www.jianshu.com/p/4c5...
    https://www.jianshu.com/p/557...
    https://blog.csdn.net/weixin_...

    • vue-router
      vue-router 就是vue深度集成的单页面应用的路径管理器,在vue的单页面应用中,由它建立起url和页面的映射关系。
    • hash/history
      vue-router 在实现单页面应用前端路由时,提供了两种方式:hash和history,根据mode参数来决定采用哪一种。
      hash模式

      • url里会带#号,#号是url的的锚点,代表页面的一个位置,vue-router组件跳转的时候只改变#号后的部分,所以不会向后端发送请求和重新加载页面,只会对dom的指定位置进行渲染。
      • 每次改变#号后部分,浏览器会在历史列表中新增一条记录,所以按后退会返回上一个位置。
      • hash模式的本质原理是wendow的onhashchange时间,利用它来监控url hash的改变来更新组件渲染。

        history模式

      • url里不带#号。
      • 原理是利用了h5中的pushState或replaceState api,实现了只在浏览器历史中新增记录,改变location地址栏后不重新向服务器请求的功能。
      • 但这个模式下刷新页面时会发请求,服务器如果需要特殊配置来避免返回404。

  2. 说一下vue里面的组件传参。
    https://www.jianshu.com/p/85b...

    1. 父组件传递给子组件:

      • 父组件通过组件标签内冒号参数名(:paramsName )传递,子组件通过props参数接住。
      • 子组件内调用this.$parent.paramsName 直接访问父组件参数/方法
    2. 子组件传递给父组件

      • 通过事件传递 this.$emit()
      • 父组件通过this.$refs直接调用子组件参数
      • 父组件通过this.$children[i]直接调用子组件参数。
    1. 兄弟组件传递

      • 通过事件总线传递
      • 通过vuex传递


  3. 说下vue组件的生命周期。
    https://www.cnblogs.com/qidh/...
    https://www.jianshu.com/p/410...

    • beforeCreate
      第一个生命周期函数,vue实例初始化时调用这个函数,这时data和methods跟dom都没有初始化。
    • created
      vue实例创建创建完成时调用这个函数,这时data和methods已经可以用,但dom模板还没渲染。可以在这个阶段向后台请求数据。
    • beforeMount
      挂载开始前被调用,此时data对象里面的数据和vue语法写的模板已编译成HTML,但未开始挂载。
    • mounted
      dom树完整渲染到页面后调用,用户此时可以看到真实数据,组件创建阶段结束。这个阶段可以进行dom操作,可以初始化一些第三方ui插件。
    • beforeUpdate
      数据被更新时调用,但是未呈现到页面上。
    • updated
      数据更新后虚拟dom重新渲染后调用。
    • beforeDestroy
      实例被销毁前调用,组件data、methods等仍然可以被正常访问。
    • destroyed
      组件销毁完成后调用,data、methods都不可使用了。


  4. 说一说vue的双向绑定。
    https://github.com/DMQ/mvvm
    https://blog.51cto.com/zhoulu...
    双向绑定指的的是即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。
    vue2是通过js的defineProperty中的set和get函数发布-订阅者模式来完成双向绑定的。

    • vue在创建实例的时候,会对实例的data对象进行一次数据初始化,给每个data的属性通过defineProperty都设置上get/set进行监听拦截,并分配一个dep订阅者的管理数组dep。
    • 编译的时候会为属性的数组dep中添加对应的订阅者,v-model,{{}},v-bind都会添加订阅者。
    • 一旦data属性值修改时,就会触发属性的set方法通知订阅者数组dep,订阅者数组循环调用各订阅者的update方法去更新视图。


  5. 说一说vue2 getter/setter方法拦截数据的不足以及解决办法。
    https://blog.51cto.com/zhoulu...

    • 当对象增删的时候,是监控不到的。因为在observe data的时候,会遍历data已有的每个属性,添加getter/setter,而后面设置的属性并没有机会设置getter/setter,所以检测不到变化。同样的,删除对象属性的时候,getter/setter会跟着属性一起被删除掉,拦截不到变化。vm.$set/Vue.set和vm.$delete/Vue.delete这样的api来解决这个问题
    • getter/setter是针对对象的。对于数组的修改,vue通过改写Array的默认方法,在调用这些方法的时候发布更新消息。一般无需关注,但是对于如下两种情况:

      • 当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
      • 当你修改数组的长度时,例如:vm.items.length = newLength

      需要vm.$set/Vue.set和vm.items.splice(newLength)解决,具体参看官方说明


    • 每次给数据设置值得时候,都会调用setter函数,这个时候就会发布属性更新消息,即使数据的值没有变。从性能方便考虑我们肯定希望值没有变化的时候,不更新模板。


  6. 父子/兄弟组件间,页面间跳转时生命周期是什么顺序的?
    https://blog.csdn.net/qq_1685...

    • 父子、兄弟组件的生命周期顺序
      图片.png
    • 不同页面跳转时各页面生命周期的执行顺序
      图片.png


  7. v-for用数组的index作为key会有哪些问题吗?
    https://segmentfault.com/a/11...

    • 更新DOM的时候会出现性能问题
    • 会发生一些状态bug

    - js

  8. 操作数组的api都有哪些?

    • 一般方法
      join():项目间添加分隔符,返回字符串。
      pop():删除最后一项,返回删除的值。
      push():添加值到最后一项,返回添加后数组长度。
      shift():删除第一项,返回删除的值。
      unshift():添加值到第一项,返回添加后数组长度。
      splice():拼接/删除一段数组,返回删除项组成的数组。
      slice():截取一段数组,返回截取的数组,不修改原数组。
      concat():拼接数组。
      sort():排序
    • 数组迭代
      forEach 对每个项目调用一次函数
      map 对每个项目调用一次函数返回新数组
      filter 对每一个项目做筛选,返回符合要求的新数组
      reduce/reduceRight 对每个项目运行函数返回单个值
      every 检查每个元素当所有元素符合要求返回true否则false
      some 检查每个元素当有一个元素符合要求返回true否则false
      indexOf/lastIndexOf 查找指定元素在数组内的第一个下标,没有返回-1

  9. 高阶函数

  10. 引用类型的深拷贝/浅拷贝
    对于普通类型变量,值直接存在栈内存中,不存在浅拷贝问题。
    对于引用类型变量,值存在堆内存中,栈内存只存了值的内存地址的引用值,会存在浅拷贝问题。

    • 浅拷贝
      拷贝的只是引用,修改拷贝后的数据会影响原来的数据,使得数据不安全。

      • 普通for...in,
      • Object.assign(),
      • 直接赋值

      是常见的浅拷贝。

    • 深拷贝
      拷贝的时候会生成一份新的数据,修改拷贝以后的数据不会原数据。

      • Json.stringify()/Json.parse()(对于对象内方法不能拷贝),
      • jquery里的$.extend(true,[],array),
      • lodash里_.deepclone(item),
      • 手写递归循环,

      都可以实现深拷贝。


  11. js里的异步请求有哪几种实现方式?
    https://blog.csdn.net/CYS_zxc...

    1. XMLHttpRequest
    2. jquery中实现了封装过的ajax
    3. fetch

- CSS

  1. 盒子模型

  2. 块级元素跟行内元素都有哪些,有什么区别。

  3. 移动端设备兼容

    1. viewport
    2. rem
      rem是css3新增的一个相对单位。rem为相对HTML根元素的大小。
    3. vm/vh
      vh、vw方案即将视觉视口宽度 window.innerWidth 和视觉视口高度 window.innerHeight 等分为 100 份。
    4. flex
      关于flex弹性布局的用法可以参考阮一峰老师的这篇文章Flex 布局教程:语法篇。在更大的屏幕上,flex布局可以完美地为用户呈现更多内容。

- 浏览器相关

  1. 跨域是什么?有哪些解决方案?
    指一个域下的文档或脚本试图去访问另一个域下的资源,由于浏览器同源策略限制而产生,如果不同源,则禁止脚本对资源进行访问。

    • 解决方案

      1. CORS(跨域资源共享)
        普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。
      2. jsonp
        浏览器的script、img、iframe标签是不受同源策略限制的 ,所以通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的callback函数,并把把我们需要的json数据作为参数传入。在服务器端,当req.params参数中带有callback属性时,则把数据作为callback的参数执行,并拼接成一个字符串后返回。

        • 优点:兼容性好,在很古老的浏览器中也可以用,简单易用,支持浏览器与服务器双向通信。
        • 缺点:只支持GET请求,且只支持跨域HTTP请求这种情况(不支持HTTPS)
      1. 反向代理
        通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

linglingj0
1 声望0 粉丝