第一次发布文章~有点小激动,哈哈~~~~
最近面试总结的这些面试题, 这只是一部份,面试中除了问这些基本知识,还问到了项目中的一些功能是如何实现的,当场也会出一两个需求让你想想有什么思路去实现,以下有哪些写的不对的地方,望各位多多指出~
一.谈一谈vue
vue是动态构建用户界面的渐进式框架,项目中一般会用到vuex,vue-router技术,采用模块化开发
1.vuex是做什么用的呢?主要是为了实现多个组件共享数据的集中式管理工具,在数据通信中会使用到vuex,可以实现任意组件间通信,它包含了几个核心,state,actions,mutations,getters; state是用来初始化数据, mutations是用来直接操作数据的方法, actions是间接操作数据,一般用来发送请求, getters是用来计算只读性属性,若组件要使用到vuex的数据,可以通过this,$store.state/dispacth actions/commit mutations/getters或mapState,mapActions,mapMutations,mapGetters可以获取到
2.vue-router是为了实现单页面应用,点击页面不会刷新,只会局部更新,使用router-link相当于a标签实现路由跳转,router-view可以显示路由组件,然而项目中路由传参方式一般用的比较多的是params,和query参数,通过this.$route.params/query可以获取到,是在route路由配置中设置,也可以使用props,命名路由,给相同层级的路由组件传递公共参数,route是用来获取参数,router是可以用来跳转,项目中用的比较多还有全局路由守卫是为了路径发生变化时,通过数据劫持,监视是否发生变化,通过routes寻找对应的组件
3.MVVM设计模式:
m:model数据层,v:view视图层,vm:viewmodel视图模型层,数据由viewmodel控制,可以从数据层读取数据,加载到页面,这时由model--->view层,也可以从view层读取要修改的数据,修改数据层的数据,此时由view--->model层,这样就实现了双向数据绑定
4.vue响应式原理
分为三个部份,第一是数据代理,第二是数据劫持,最后是模板解析
简单版本:数据发生变化,页面也会变
1.数据代理:将data中数据代理到实例对象上,遍历所有数据,通过object.definedProperty()方法重新定义属性,内部通过get方法获取数据,set方法设置新值,实际操作是原数据的数据
2.数据劫持:遍历所有data中的数据,将其定义为响应式数据,通过object.defineProperty重新定义get和set方法,这个时候通过闭包可以保存一个dep对象,get中将来通过dep会建立响应式联系,set可以触发响应式更新
3.模板解析
(1)将元素节点转换成文档碎片节点
(2)解析模板
取出当前节点进行遍历,判断是元素节点还是文本节点
若是元素节点就要编译,并且取出所有属性,判断是否是指令属性,若是再判断是否是事件指令
若是,就给元素绑定事件,回调函数可以通bind方法强制改变this指向
若是普通指令,new watcher触发响应式联系
若是文本节点,就解析插值语法
(3)将解析完的模板代码添加到页面中生效
5.双向数据绑定原理
是通过v-model实现数据绑定
是给元素绑定value属性和input事件
当用户输入数据时,会触发input事件,将data中值为e.target.value实现双向数据绑定
二.谈一谈ajax
使用ajax发送请求与服务器进行交互,不会刷新整个页面,只会局部更新,但是会存在跨域问题 什么是跨域?违背了同源策略(协议,域名,端口号都相同)
解决跨域问题的方法:
1.jsonp是通过创建script标签,src属性添加一个回调,再把script标签添加到body中
2.cors是在响应头那里设置字段,设置access-control-allow-origin允许跨域的地址
3.proxy数据代理在vue.config.js文件中配置,devserve对象中配置
ajax请求会返回promise对象
promise有三个状态,pending,resolved,rejected,调用resove函数,会由pending状态变成resoved状态,调用reject函数,会由pending状态变成rejected状态,状态只能修改一次,promise它有then方法和catch方法,then方法中return一个值,或是一个promise对象,或没有return,那最终会返回成功状态的promise对象,若return一个失败的promise对象或抛出错误,那会返回失败状态的promise对象,
一般项目中用的比较多的还是async和await,因为它会返回一个promise对象,async是声明函数是异步的,await是只等待promise对象执行,等异步执行完成,这样就可以利用promise的一些方法去判断返回值,若等待的是返回成功状态的promise对象,则就返回promise对象,若是失败状态的则不执行
三.谈谈localStorage,sessionStorage,
这两个是为了缓存数据,还有一个cookie也是
cookie只能存储4kb左右大小的文件,若没有设置超时时间,关闭浏览器就会失效,若设置了超时时间则等到了超时间时才会失效,会存在内存中
sessionStorage可以存储5Mb左右的文件,临时性存储,存在内存中,关闭浏览器就失效了
localStorage永久性存储,存储文件大小是20mb,只要用户不清除缓存,可以永久保存,存在硬盘中
项目中一般在设置token也就是用户登录的标识那里,会把token保存在缓存中,以便用户下次无需重新登录,可以从缓存中读取数据了
四.bom和dom以及es6新特性
javascript是由bom,dom,ECMA组成的,bom是浏览器模型,操作浏览器的,dom是文档对象模型,用于操作dom节点,ECMA是语法规范,项目中可以创建节点,插入节点,复制节点,获取元素等操作 es6新特性: 我一般用的比较多的是解析对象,解析数组,通过rest扩展运算符,获取参数,就不会使用arguments获取了 数组的方法(push后添加,pop后删除,unshift前添加,shift前删除,filter过滤,map映射,reduce,split切割数组,join添加变成字符串等)通过模板字符串,对一些数据引入使用,箭头函数这个用的比较多
箭头函数没有this指向,它的this是距离包裹它的函数,若是普通函数或自调用,那this指向window,若是实例化调用,那指向实例化对象,若是隐式调用则this指向上下文对象,若是call,apply绑定那就是call,apply所规定的那个对象
call,apply都是可以this指向的,只是写法上有些不同,call是用逗号隔开参数,apply是用数组隔开参数,还有bind方法也是改变this指向,但没有调用,会返回一个新函数
还有let,const声明变量的方法,都是只能在块级作用域中生效,不能重复声明,声明了必须赋值,但是let声明的值是可以修改的,const声明的值是不能修改的
在js中用到var声明变量,是可以重复声明,后面的会覆盖前面的,可以分为全局变量和局部变量
可能会问什么是作用域?(那可以延伸到原型链)
它就是查找所有变量和函数的一系的过程,若自己身上没有这个变量,可以通过作用域往上一层作用域查找,直到找到为止,若没有找到就会报错,其实它底层实现跟原型链类似,因为构造函数会有prototype属性指向它的原型对象,原型对象的constructor构造器会指回构造函数,其实只要是new出来的就是构造函数,那实例对象上会有一个__proto__属性指向构造函数的原型对象,通过__proto__这种隐式原型的方式 就形成了原型链,若查找变量时自身上没有就可以沿着原型链去查到,最终找到object构造函数的原型对象,因为它的proto是为null
五.数据类型
那基本数据类型包含:string,number,boolean,null,undefined,symbol,bigint
引用,复杂数据类型有:object,function,array
六布局
响应式布局就是采用@media媒体查询方法使页面能够随着屏幕的大小发生变化
左边固定右边自适应布局
1.可以通过position定义,父元素relative,子元素absolute,left:z-index:1,right:margin-left:xxxpx
2.可以通过float浮动,left,right都向left浮动,然后left:margin-left:-100%;right:margin-left:xxxpx
3.也可以通过flex布局,父元素display:flex,子元素display:flex,flex-direction:column
七.后台项目动态添加路由如何实现的
根据用户权限来动态展示路由,其实就是获取用户数据做判断是否有权限,有权限就可以展示相应路由,然后用户对应的路由列表就可以渲染出来
八.深度克隆的方法
1.const newObj=JSON.parse(JSON.strigify(obj))
2.function checkType(obj){
return Object.prototype.toString.call(obj).slice(8,-1)//获取原型上的方法并
}
function deepClone(obj){
let re;
if(checkType(obj)===object){
re={}
}else if(checkType(obj)===Array){
re=[]
}else{
return obj
}
for (let in obj){
re[i]=deepClone(obj[i])
}
return re
}
九.pc端支付页面如何实现的?
提交订单跳转到支付页面,选择支付方式,若你选择支付宝,发送请求把当前的订单数据传给服务器,跳转到支付宝的页面;如果用户扫码支付成功,支付宝会通知服务器支付结果,同时把重定向到我们的页面,重定向地址需要后端人员提前配置;重定向到订单页面,会在mounted中发送请求,请求最新的订单信息,在这个时候请求回来的数据就能看到所有订单的支付状态
十.封装过什么组件,怎么实现的?
轮播图,引入轮播图进行二次封装,三级分类列表,分页器
分页器组件的实现
首先设置好当前页,每页的显示的条数,显示的按钮数量
其次用watch监视页码发生的变化(组件中使用绑定事件,封装组件中触发)
用computed计算属性,计算总页数,中间显示的按钮值(计算开始和结尾的数进行判断)
进行遍历,得到按钮数量
十一.小程序opendId
通过wx.login获取code,用wx.request发送请求并把code携带上到服务器上
这时服务端可以向微信调用登录凭证校验的接口,然后返回session_key,opendId
若是自定义状态就和session_key,opendId关联起来,返回自定义登录的状态,把它存在storage中
若用户再次登录时,通过wx.request发起业务请求,携带自定义登录的状态,通过自定义状态查询到opendId,session_key,返回数据
十二.小程序支付流程
客户端下单支付发送请求给商家服务器
商家和微信服务器对接唯一标识
商家服务器根据opendId生成商户订单
商家服务器发送请求调用api获取支付订单信息
商家对预支付信息签名加密后返回小程序客户端
用户确认支付调用接口
微信服务器返回支付结果给小程序客户端
微信服务器推送支付结果给商家服务端
十三工作中遇到的难题:
之前有在computed直接修改data的数据,发现页面不会发生变化,应该使用get和set方法去获取和设置data那个变量,当computed监听数组变化的时候,要对数组进行操作的话,需要通过this.$set方法去修改数组,这样页面才会触发更新
十四.如何实现promise
创建new Promise
通过then,catch捕获promise对象的状态
通过返回值返回的状态
异步编程的优缺点:
非阻塞的IO更大程度的利用资源
十五.js事件轮询机制
同步代码:绑定事件,定时器,发送ajax
异步代码:事件回调函数,定时器的回调函数,ajax的回调函数
先执行同步代码再执行异步代码
原理:执行完同步代码之后,把相应的回调添加到管理模块中,事件回调添加到事件管理模块,ajax回调添加到ajax管理模块,等事件发生或计时器到期等,就会把相应的回调函数添加回调队列中等待执行,等初始化同步代码执行完毕之后,js引擎会循环检查回调队列中的回调函数,并执行
十六.http协议由哪些构成
请求方式,url,协议版本,请求体,响应体
缓存:dns缓存,计算机缓存,路由器缓存,运营商缓存
十七.水平垂直居中的方法
行内元素:line-height:xxxpx; text-align:center;
块元素:position:relative;top,left:50%;transform:translate(-50%,-50%)
display:flex;justify-content:center;align-items:center;
十八..sync怎么实现通信的
原来是父向子通信,后期在它的基础上实现子向父通信,通过绑定事件,接收子组件的数据,并触发事件,将最新数据更新到父组件中
十九.路由勾子函数
全局前置守卫beforeEach,全局解析守卫beforeResolve,全局后置钩子afterEach
路由独享守卫beforeEnter
组件内的守卫beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave
二十.keep-alive的实现
若组件需要缓存,通过keep-alive包裹起来,并设置include或exclude,缓存不活动的组件实例
keep-alive的生命周期顺序:
created-->mounted-->activated--->deactivated-->activated
二一.虚拟dom和真实dom的区别
真实dom会导致页面重绘重排,性能极低,体积大,无用元素多,占用内存大
虚拟dom不会引起重绘重排,渲染次数少,体积小,无用属性少,占用内存小
重绘重排:只要样式或尺寸发生了变化那就会引起重绘重排
二十二mixin混入
将组件中可复用的功能,定义一个混合文件写在一个js文件中,组件通过混合mixins:[xxx]引入并使用
二十三.自定义指令
除了内置指令,v-model,v-bind等
对普通dom元素进行底层操作,注册一个全局指令,或注册局部指令
若要创建一个自定义指令,可以用固定布局将元素固定在页面上,可以通过指令值去更新自定义指令
若props数据不能修改,可以设置dataset自定义属性