1、有没有单独封装过组件?(common,view)
答:有封装过,在项目的common文件夹中会存放项目的公用组件即可重用的部分放在common中,如项目的头组件,底部组件,侧边栏组件、导航栏组件等,项目里的view文件夹下存放与路由器绑定的组件。component一般存放重用的小组件,view里存放页面级组件。
2、首屏加载白屏怎么进行优化?(
答:①采用路由懒加载的方式,当用户访问的时候,再加载相应的模块。
②webpack开启gzip压缩。
③使用CDN减小代码体积加快请求速度。
④项目打包禁止生成map文件。
⑤使用外链css和js文件 。
⑥使用骨架屏,在首页加载的时候显示页面结构轮廓。
3、路由传参query和params区别
答:①引入方式不同:query使用path引入,params使用name引入
②接收方式不同:query使用this.$route.query.name,params使用this.$route.params.name
③刷新页面时,query参数不会消失,params参数会消失。
④query传过来的参数会显示在地址栏中、类似于?id=1,params传过来的参数不会显示在地址栏中,直白来说就是query相当于get请求,params相当于post请求。
4、怎么理解vuex?
答:Vuex是开发的状态管理器,相当于一个大仓库用来存储公共数据,可以实现组件间数据共享,组件通信中的一种,适用于任意组件通信。
vuex五种属性:states:存储响应式数据的地方
mutations:修改state中数据的唯一途径
actions:处理异步操作,在此过程中修改state数据也是通过commit到mutations 进行修改实现的。
getters:类似于计算属性,过滤states数据
modules:用于实现vuex模块化
5、项目基础优化
答:①减少HTTP请求避免重复请求 ②减少bom元素和dom操作 ③使用雪碧图 ④压缩合并js、css代码 ⑤避免图片src为空 ⑥把样式放在link里 ⑦css样式放在文件头部,js脚本放在文件尾部。
6、对$nextTick异步渲染的理解
答:vue采用数据驱动视图的思想,但是在一些情况下,仍然需要操作dom。有时候dom1的数据发生变化,dom2从dom1中获取数据就会发现dom1的视图并没有更新获取不到dom1更新后的数据,这时就需要使用$nextTick;
作用:在下一次dom更新结束之后执行其指定的回调,(当数据更新后,要基于更新后的dom进行某些操作时要在nextTick指定的回调中执行)如果不采用异步更新,在每次数据更新后,都会对当前组件重新渲染。为了性能考虑,vue会在本轮数据更新后,再去异步更新视图。
7、如何对axios进行二次封装的,有什么作用?
答:封装的同时要与后端协商好一些约定,请求头状态码请求超时时间等...
第一阶段:用axios.create创建axios实例,在实例上配置baseurl/header/setTimeout,然后将其进行暴露。
第二阶段:添加请求/响应拦截器
请求拦截器:在请求发送之前进行拦截,进行必要操作处理,相当于每个接口里相同操作的一个封装。
相应拦截器:请求得到响应之后,对响应体的一些处理。
8、用户的增删改查
答: 新增编辑会对弹窗进行复用,定义一个字段为0且让0表示的是新增,1表示的是编辑,默认打开新增弹窗。点击新增/编辑按钮时字段切换到对应的值即可区分点击之后是新增还是编辑弹窗了。打开弹窗之后的提交逻辑:对弹窗点确认的时候对字段进行一个判断如果字段是0则新增字段调用新增的接口获取到新增列表插入数据再调用获取列表刷新数据即完成了新增逻辑,不是0就调用编辑的接口获取到编辑后的列表再调用获取列表刷新数据。
编辑与新增有所不同,在点击编辑按钮之后它需要进行一个数据回显此处需要使用JSON.parse(JSON.stringify())来进行深拷贝赋值。
删:调用element中$confirm即可打开是否删除的消息提醒,在他的回调里,即.then方法里调用删除的接口,并拿到商品的id,把id作为参数发送删除请求,接口返回结果中code===20000消息提示删除成功调用获取列表来更新数据 .catch则代表点击取消 code=-999 提示已取消删除
查:
9、表单验证
答:element form组件的表单就验证功能,只需要通过给form绑定rules属性并传入约定的验证规则,在data中自定义并且使用required:true来设置表单为必填项,并通过form-item的prop属性设置需要校验的字段名即可。
10、项目商品详情页怎么实现?
当用户点击商品名字或图片的时候,就进行this.$router.push进行路由跳转并传递商品id到详情页,再通过后台提供的相关详情接口,把id作为参数,在详情组件的mounted中派发action调用vuex中的请求函数获取到商品的详细数据存储在vuex中,通过getters配置对象对数据进行简化通过map getter映射给组件,通过使用插值语法或者v-for进行数据渲染。
11、防抖和节流
答:防抖:一段时间内连续被触发,只执行最后一次
节流:事件连续被触发n秒内执行一次
使用场景:防抖:登录,支付等按钮避免用户点击太快多次发送请求。
搜索框搜索输入,只需要最后一次输入完再发送请求
手机号邮箱验证输入检测、鼠标经过和离开事件
节流:滚动加载,高频点击、表单重复提交。
12、移动端适配
答:前端适配目前没有最好的方法,只有合适的方法。目前前端主要做适配的方法有百分比、em、rem、媒体查询(即mediaquery)、flex布局(弹性盒子)、vw、vh等,目前我在项目中用的是rem、flex布局,有时会用到媒体查询,在做这个移动端响应式布局时主要是用的是js+rem布局,动态的给font-size属性赋值,将font-size=实际屏幕宽度/设计稿font-size *设计稿宽度,即可做到适配所有移动端了。
13、get和post提交数据的区别是什么?
14、对路由的理解
15、路由的工作模式/vue路由工作原理 https://zhuanlan.zhihu.com/p/27588422
答:通过改变url在不重新请求页面的情况下,更新页面视图。(更新视图不重新请求页面)
①hash模式:借助锚点技术重写url路径(#符号本身以及它后面的字符称之为hash)纯静态技术,刷新不会404;可在不重新加载的情况下变更url路径。只能存在一个#
②history模式:采用H5新增的pushState()函数重写url路径,虽然可以重写url路径但是重写后的新路径不包含原有html物理文件的访问地址,所以在history模式重写后一旦刷新网页就会造成404,解决方法在后端服务器上做一个重定向。
16、路由配置常用的属性及作用
17、VueRouter导航守卫的作用
18、懒加载(图片/路由/数据)
19、单页面开发与多页面开发的区别
20、Vue如何实现跨域
答:
21、Vuex如何实现数据持久化
答:因为vuex中的state是存储再内存中的,一刷新就没了,例如项目中遇到的登录后刷新菜单没了,解决方案有:①利用本地存储(localstorage,sessionStorage)
②利用Cookie进行存储
③利用第三方插件vue-persistedstate
22、route和router的区别
答:this.$route:当前激活的路由的信息对象,每个对象都是局部的,可以获取当前路由的path、name、params、query等属性。
this.$router:全局的router实例。通过vue根实例中注入route实例,然后再注入到每个子组件中,让整个应用都有路由功能。其中包含了很多属性和对象,任何页面也可以调用其push(),replace( ),go()等方法
23、登录的流程,存储了哪些用户信息,以及在什么位置进行了存储
答:①输入用户名密码点击登录,登录成功后端会返回给我们一个token和其他的路由菜单、权限数据。
②我们把数据存储在vuex中
③在aioxs拦截器
24、vue2和vue3的区别
答:①vue2采用Object.definePropertyVue3使用ES6proxy
②vue2虚拟dom进行全量的对比,vue3新增了PatchFlag(静态标记),只对比带有PF的节点。
③vue2无论元素是否参与更新,每次都会被重新创建然后再进行渲染
25、前端缓存数据的方法
答:localstorage、sessionstorage、cookie
区别:①存储大小不同:cookie只有4kb,localstorage和sessionstorage有5mb。
②有效期不同:
cookie设置过期时间则存储在硬盘里,浏览器关闭也不会失效,直到过期时间后才失效,不设置过期时间关闭浏览器窗口就会失效。
localStorage生命周期是永久,除非手动使用remove清除不然就会永远存在。
sessionStorage关闭页面就会消失,临时性的存储。
③作用域不同:sessionstorage不在不同的浏览器窗口中共享,即使是同一个页面,localstorage和cookie所有同源窗口都是共享的。
④cookie可以携带在请求头里,在浏览器和服务器之间进行传递,登录后的token值一般存放在这里面。sessionStorage和localStorage不会自动把数据发送给服务器,仅保存在本地。
26、和后端的协作
答:开发的时候大部分请将后端给我们接口都比较及时,但是如果后端仅给了我们接口文档,没有给接口的时候我们就可以使用Mock.js进行数据模拟,但是在这过程中可能会遇到很多报错的情况可能是接口的问题或者服务器那边的问题有时候传传回来的参数不够,少字段,或者接口文档少了一些参数,这些问题我们都会安排时间进行联调来解决这些对应的问题。
27、前后端针对接口不一致的情况怎么去处理?
答:如果接口出现问题,请求失败报404,我会自己先用postman检查一下,看看参数必填项是不是传完了或者后端进行了修改而我这边没有去做相应的修改,以及请求方式这些东西有没有问题,如果没有问题就去跟后端人员进行沟通。
28、让一个盒子水平垂直居中?
答:①flex布局设置justify-content:center align-items:center
②绝对定位+transform:
③绝对定位+负外边距(已知盒子宽高)
④绝对定位+margin:auto 上下左右都设置成0
29、gird布局和flex布局
答:flex布局是一维布局划分成一行或者是一列,gird布局是二维布局,将容器划分成为了行和列,产生单元格,可以将网格元素放在行列相关位置上从而达到布局目的。
有容器有项目
30、flex布局
弹性盒子布局是一维布局 ,有容器有项目采用flex布局的元素叫容器,容器里的子元素叫做项目。容器默认有两根轴水平的主轴和垂直的交叉轴。flex-direction设置容器主轴的方向。flex-wrap容器一行排不下时是否换行。 flex-flow是flex-direction和flex-wrap的缩写。justify-content属性设置项目在主轴的对齐方式。align-item项目在交叉轴的对齐方式。项目上也有一些属性:order项目的排序顺序(默认为0值越小越靠前)。flex-grow当容器空间有剩余时放大比例。felx-shrink空间不足时缩小比例。
31、rem和em的区别及原理
答:em和rem都是相对单位,em相对于父元素的字体大小。rem相对于根元素即HTML元素的字体大小。rem布局实际上是等比例缩放,实现自适应。
32、原型和原型链
答:原型:①所有函数都有一个prototype(原型),属性值是一个普通的对象
②所有引用类型都有一个__proto__(隐式原型),属性值是一个普通的对象
③所有引用类型__proto__指向它构造函数的prototye
原型链:访问一个对象的属性时候,如果该对象内部不存在这个属性,那么就会沿着它的__proto__所指向的prototype原型对象里面找,该原型对象也有自己的__proto__,层层向上一直找到对象的原型对象为null为止,这样一层层的构成了原型链。
33、父子组件通信
答:挂载阶段:父beforecreate--->父created--->父beforemount--->子beforecreate--->子created--->子beforemount-->子mounted-->父mounted
更新阶段:父beforeupdate--->子beforeupdate--->子updated--->子updated
销毁阶段:父beforedestory--->子beforedestroy--->子destroyed--->子destroyed
34、diff算法
虚拟dom:表示真实dom的js对象(标签名,标签属性,子标签名属性和文本节点)
diff算法本质是比较两个js对象的差异。
整个流程:
当数据改变的时候触发内部的setter方法进一步触发dep.notify方法,然后通知到订阅者执行patch方法,patch方法接收两个参数新旧虚拟dom节点。
首先在内部进行判断是不是同类标签如果是则没有比对必要直接替换。
如果不是同类标签需要进一步执行pathchVnode方法,在这个方法内部也需要判断新旧虚拟dom是否相等,如果相等就直接return。
不相等就需要分情况比对,比对原则以新虚拟节点结果为准。
第一种情况如果新旧都有文本节点,直接用新替换旧的文本节点即可;
第二种情况如果旧的没有子节点新的有则直接添加新的子节点即可;
第三种情况如果旧的有子节点新的没有直接删除旧的字节点就可以了;第四章情况新旧都有字节点就要比对它们的子节点,所以在内部封装了updateChildren方法专门比对子节点。只在同级做比对可以减少比对次数最大化的提高比对性能,同级比对的时候采用的是首尾指针法,不管是新旧虚拟节点都有首位两个元素对应的是start和end,首先olds和news做比对没有比对成功就用olds跟newe做比对如果依旧没有比对成功,olde会和news做比对,如果依旧没有比对成功olde会跟newe做比对,依照以上原则依次去比较,比对成功就退出当前比对,渲染结果会以新虚拟dom的结果为准,每次比对成功后,比对成功的start会向右移,end会向左侧移动,在移动的过程中当start点跑到end点右侧就终止比较。如果首尾指针法以上四种情况都没有比对成功的话,则会看新旧虚拟节点的key值如果key有值相同就会复用,并依照新虚拟节点的位置移动到对应位置上去。
35、函数柯里化
答:是高阶函数的使用方法,函数柯里化指的是将一个接收多个参数的函数变为接收部分参数的函数。并返回一个新的函数去处理剩余参数的固定形式,是逐步传参的过程。
作用:①延迟计算又叫惰性求值,柯里化函数不会立即执行计算第一次只是返回一个函数后面的调用才会进行计算。
②参数复用,固定易变因素,将易变因素传参定下来,生成一个更明确的应用函数。
③入口单一,易于测试与复用。
④易于定位bug,可以准确定位到哪个参数在哪个换节出了问题。
缺点:函数嵌套函数,嵌套的层级太多,占用空间效率低。
36、reflow回流(重排)和重绘repaint
重排:当元素结构或尺寸发生变化的时候浏览器重新渲染全部或者部分文档的过程。
重绘:当元素的样式发生改变但位置不变。浏览器会将新样式赋予给元素的过程。
触发回流重排:①增加删除dom节点 ②元素位置改变 ③元素尺寸变化(width\padding...)
④页面首次渲染 ⑤浏览器窗口尺寸变化
触发重绘:修改颜色、文本方向、阴影修改、overflow:visibility
重绘不一定引起回流,回流必定引起重绘
如何避免回流和重绘:避免使用table布局、多层内联样式、css表达式...
35、对MVVM的理解
项目种所使用到的vue就是mvvm模式的,view视图层,model数据层、viewModel业务逻辑层。viewModel作为view和model中间的桥梁对他俩进行了一个双向绑定
36、Vue是什么?
答:vue是用于构造用户界面的mvvm的渐进式js框架,自底向上逐层应用。vue核心库只关注视图层,能够为复杂的单页面应用提供驱动。 采用mvvm模式实现数据双向绑定,两大核心响应式数据驱动和组件化。
vue的几大特点:数据驱动、渐进式、响应式、组件化、声明式渲染。
声明式渲染:只需要关注结果不需要关注过程具体是怎么实现的,vue使用 "模板语法" 来声明式地将数据渲染进dom系统{{ }}
响应式意思是,数据的更新是响应式的,数据改变驱动视图改变
vue就是一个js库并不依赖于别的js库,直接引入js文件就可以直接使用,与传统的js不同,Vue的渐进式框架表示开发者可以由简单组件写起搭建出一个复杂的前端平台,且本身功能局限要搭配其他工具如vue-router,vuex、axios等可以增强其能力。
形成Vue渐进式框架的核心是:组件化、mvvm、响应式和生命周期。
37、为什么要用Vue?(
答:核心:组件化、mvvm、响应式、生命周期
①组件化:vue将组成一个页面的html、css、js合并到一个组件中,可以被其他组件或页面引入而重复利用。组件化很好的将一个庞大复杂的前端工程拆分成一个个组件,重复利用的性质也大大提高了开发的效率。
②mvvm数据双向绑定:view视图层,model数据层、viewModel业务逻辑层
38、区分响应式和双向绑定
答:响应式:数据改变驱动视图改变,是单向的
双向绑定:是双向的,视图改变也可以使数据改变,也就是说响应式是双向绑定的一环。
39、双向数据绑定的原理
答:采用数据劫持+发布订阅者模式的方式,
数据劫持通过object.definedProperty()方法来劫持各个属性的setter,getter方法,在数据变动setter拦截到数据发生变化后发布通知,dep收到observer的数据变化通知会将变化的依赖通知给watcher订阅者,watcher是observer和comile的桥梁,当接收到数据发生变化的通知会调用compile的回调函数,compile主要是用于解析模板指令将模板中的变量替换成数据,然后在初始化渲染页面的时候将每个指令对应的节点绑定更新函数然后添加监听数据的订阅者一旦有数据有变动它会收到通知然后去更新视图。
1、需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter 这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
2、compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
3、Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
(1)在自身实例化时往属性订阅器(dep)里面添加自己
(2)自身必须有一个update()方法
(3)待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
4、MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
40、methods、computed和watch区别?
答:①methods用来定义方法的区域,需要调用才能触发,不具备缓存性
②computed计算属性 :当一个数据受多个数据影响的时候,某个值需要通过某些逻辑,或由多个值计算而来就需要用到computed,典型的例子就是购物车计算时的总金额,总金额就是依赖于数量和单价进行计算的,支持缓存,只有依赖的数据发生变化的时候才会重新进行计算,否则会直接从缓存中读取,使用时和data中的数据使用方式基本一致,不支持异步,computed内有异步操作是无效的,无法监听到数据的变化,反而
watch监听属性:当一个数据变化会影响其他一个或多个数据的时候就需要监听这个数据,watch是不会进行缓存的,监听的数据发生变化就会触发相应的操作,watch支持异步,监听的数据必须是data中声明过的数据,或者是从父组件传递过来的props中的数据,每个监听数据有两个可选属性一个是immediate和deep,immediate是组件加载(是否)立即触发回调函数,如果值是true组件加载就会立即触发一次如果是false首次是不会执行这个监听逻辑的,只有当数据去改变的时候才会去监听,deep是深度监听,为了监听对象内部值的变化,适合用在复杂数据类型的数据中
版权归原作者 目前还是拼命想成为前端高手的小菜鸟 所有, 如有侵权,请联系我们删除。