最近在找工作,记录一下遇到的面试题和我整理后的答案。
- vue
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。
- vue-router
说一下vue里面的组件传参。
https://www.jianshu.com/p/85b...父组件传递给子组件:
- 父组件通过组件标签内冒号参数名(:paramsName )传递,子组件通过props参数接住。
- 子组件内调用this.$parent.paramsName 直接访问父组件参数/方法
子组件传递给父组件
- 通过事件传递 this.$emit()
- 父组件通过this.$refs直接调用子组件参数
- 父组件通过this.$children[i]直接调用子组件参数。
兄弟组件传递
- 通过事件总线传递
- 通过vuex传递
说下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都不可使用了。
- beforeCreate
说一说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方法去更新视图。
说一说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函数,这个时候就会发布属性更新消息,即使数据的值没有变。从性能方便考虑我们肯定希望值没有变化的时候,不更新模板。
父子/兄弟组件间,页面间跳转时生命周期是什么顺序的?
https://blog.csdn.net/qq_1685...- 父子、兄弟组件的生命周期顺序
- 不同页面跳转时各页面生命周期的执行顺序
- 父子、兄弟组件的生命周期顺序
v-for用数组的index作为key会有哪些问题吗?
https://segmentfault.com/a/11...- 更新DOM的时候会出现性能问题
- 会发生一些状态bug
- js
操作数组的api都有哪些?
- 一般方法
join():项目间添加分隔符,返回字符串。
pop():删除最后一项,返回删除的值。
push():添加值到最后一项,返回添加后数组长度。
shift():删除第一项,返回删除的值。
unshift():添加值到第一项,返回添加后数组长度。
splice():拼接/删除一段数组,返回删除项组成的数组。
slice():截取一段数组,返回截取的数组,不修改原数组。
concat():拼接数组。
sort():排序 - 数组迭代
forEach 对每个项目调用一次函数
map 对每个项目调用一次函数返回新数组
filter 对每一个项目做筛选,返回符合要求的新数组
reduce/reduceRight 对每个项目运行函数返回单个值
every 检查每个元素当所有元素符合要求返回true否则false
some 检查每个元素当有一个元素符合要求返回true否则false
indexOf/lastIndexOf 查找指定元素在数组内的第一个下标,没有返回-1
- 一般方法
- 高阶函数
引用类型的深拷贝/浅拷贝
对于普通类型变量,值直接存在栈内存中,不存在浅拷贝问题。
对于引用类型变量,值存在堆内存中,栈内存只存了值的内存地址的引用值,会存在浅拷贝问题。浅拷贝
拷贝的只是引用,修改拷贝后的数据会影响原来的数据,使得数据不安全。- 普通for...in,
- Object.assign(),
- 直接赋值
是常见的浅拷贝。
深拷贝
拷贝的时候会生成一份新的数据,修改拷贝以后的数据不会原数据。- Json.stringify()/Json.parse()(对于对象内方法不能拷贝),
- jquery里的$.extend(true,[],array),
- lodash里_.deepclone(item),
- 手写递归循环,
都可以实现深拷贝。
js里的异步请求有哪几种实现方式?
https://blog.csdn.net/CYS_zxc...- XMLHttpRequest
- jquery中实现了封装过的ajax
- fetch
- CSS
- 盒子模型
- 块级元素跟行内元素都有哪些,有什么区别。
移动端设备兼容
- viewport
- rem
rem是css3新增的一个相对单位。rem为相对HTML根元素的大小。 - vm/vh
vh、vw方案即将视觉视口宽度 window.innerWidth 和视觉视口高度 window.innerHeight 等分为 100 份。 - flex
关于flex弹性布局的用法可以参考阮一峰老师的这篇文章Flex 布局教程:语法篇。在更大的屏幕上,flex布局可以完美地为用户呈现更多内容。
- 浏览器相关
跨域是什么?有哪些解决方案?
指一个域下的文档或脚本试图去访问另一个域下的资源,由于浏览器同源策略限制而产生,如果不同源,则禁止脚本对资源进行访问。解决方案
- CORS(跨域资源共享)
普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。 jsonp
浏览器的script、img、iframe标签是不受同源策略限制的 ,所以通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的callback函数,并把把我们需要的json数据作为参数传入。在服务器端,当req.params参数中带有callback属性时,则把数据作为callback的参数执行,并拼接成一个字符串后返回。- 优点:兼容性好,在很古老的浏览器中也可以用,简单易用,支持浏览器与服务器双向通信。
- 缺点:只支持GET请求,且只支持跨域HTTP请求这种情况(不支持HTTPS)
- 反向代理
通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
- CORS(跨域资源共享)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。