面试题
cookiee的作用
答: 用于在浏览器中存储一份数据,一般用于存储用户登录后的个人信息,比如用户名,密码,记住密码等。他的存储大小不能超过4Kb,现在比较推荐的是sessionStorage
和localStorage
,他的存储大是5mb。
sessionStorage
存储的数据在浏览器关闭后会自动清除
localStorage
存储的数据会一直保存在浏览器中,除非手动清除
如何让一个盒子在水平和垂直方向居中
1:弹性和布局,设置水平和垂直方式都是居中排列
2:定位布局,left,top,right,bottom都设置为0,margin:auto
3:定位加平移,left:50%,top:50%,translate(-50%,-50%)
隐藏网页元素有哪些方式
1:display:none;不占空间
2:visibilty:hidden;占空间
3:opacity:0;透明度设置为0,占空间
4:width:0;overflow:hidden;不占空间
sass和less你是怎么理解的
sass和less是css的预处理器,提供了更高效的语法快速定义样式,但是浏览器不认识他,再生产环境下需要将sass和less重新编译成css
常用的功能:嵌套选择器和定义变量
js的原型对象和原型链有什么作用
构造函数的原型对象是prototype,对象的原型对象是__proto__
属性指向对象的prototype
原型属性。他的作用是共享一份数据,就是所有的对象的原型对象都指向构造函数的原型对象
原型链就是js中继承关系,我们可以通过构造函数的原型对象重新指向另一个对象来得到另一个对象的功能
谈谈你对this的理解
谁调用了当前方法,当前方法中的this就指向谁,比如a.b(),那么b方法中的this就执行a
箭头函数中没有this,如果在箭头函数中使用了this,那么改this指向的上一层方法中的this,如果没有上一层函数,this执行window
什么是闭包,有什么作用
外层函数中定义的数据,在内层函数中使用。
在执行外层函数的时候,外层函数中定义的变量 会被初始化,外层函数返回内层函数,内层函数在没有执行之前,数据始终保存在内存中,而且没有任何途径能对数据进行破坏,然后在需要的时候执行内层函数,然后使用外层函数定义数据,其实react的函数式组件采用的就是这种思想。采用这种方式设计的目的就是包装数据的安全性。
好处:
-
可以让一个变量长期在内存中不被释放
-
避免全局变量的污染,和全局变量不同,闭包中的变量无法被外部使用
-
私有成员的存在,无法被外部调用,只能直接内部调用
闭包可以完成的功能:1.防抖、2.节流、
弊端:过多的闭包也会造成空间的浪费
回调函数有什么作用
回调函数的本质作用:减少代码冗余
函调函数就是将一个函数作为参数传给另一个函数,在另一个函数中的某个时刻重新调用参数函数。这样做的好处时,在本函数中将定义固定路径,变化的逻辑在通过回调函数传出去,比如数组的高阶函数就是这么设计的
原生ajax的步骤
1.创建XmlHttpRequest对象 2.通过open方法初始化请求 3.通过send方法发送请求 4.通过onReadystateChange事件监听状态,接收返回结果
http的状态码有哪些
200 请求成功 404 请求资源不存在 401 请求无权限 500 服务器错误
vue有哪些常用的指令
v-if v-for v-model v-on v-text v-html v-show
v-for时不推荐key使用index
key是列表渲染的唯一键,是底层虚拟DOM判断是否渲染真是DOM的依据
当列表变化时,会重新生成一份新的虚拟DOM,如果新虚拟DOM的key是一样的,那么就不会渲染真实dom
如果key是index,往列表中添加之前的数据的index不会有影响,但是如果往列表中插入数据,就会影响列表中之前的所有的index,这样就导致之前生成的虚拟dom全部作废,比如我们向列表的最前头插入一个数据,生成的虚拟dom全部作废,整体列表需要重新渲染
key如果是index,往数组中push数据没有影响,但是往数组中push数据就会受到影响,所有的列表会重新渲染。
所有key推荐使用对象的唯一属性,比如:学号,工号,车牌号,身份账号等等
vue组件传值有哪些方式
1:父向子传:用prop,$children
$ref
2:子向父传:用$emit
$parent
3.后代组件之间传值: 用依赖注入(provide,inject)
4.兄弟组件之间: 用中央事件总线 5.更加复杂的传值: 可以用vuex
vuex有哪些成员
1.state: 定义全局状态 2.getters: 定义计算属性 3.mutations: 定义同步方法 4.actions: 定义异步方法 5.modules: 定义子模块
vue路由有哪些模式
hash模式: 路由地址上会有#号,它本质上采用的是错链接原理,所以兼容性高
historv模式: 路由地址上没有#号,看上去更美观,才采用的是浏览器权限的historyApi技术,兼容性会相对低一点
生产环境下为了放在状态丢失,要在服务器上配置对应的信息.
如何深拷贝对象
1.可以使用]SON.stringify 和JSON.parse 这两个方法配合完成对象的深拷贝,这种方式不能拷贝方法和undefined数据
2.手写递归算法
let obj = { name: 'uu', age: 30, friend: { name: 'kk', age: 20, friend: { name: 'bb', age: 10 } } } function deep(obj) { let obj2 = {} for (const key in obj) { if (typeof obj[key] === 'object') { obj2[key] = deep(obj[key]) } else { obj2[key] = obj[key] } } return obj2 } // 对obj进行深拷贝得到了obj2 let obj2 = deep(obj) // 修改obj2的属性,对原对象obj也没有影响 obj2.name = 'aaa' obj2.friend.friend.name = 'bbb' console.log(obj); console.log(obj2);
3.用库Lodash:它里面有很多的工作方法。比如:深拷贝,防抖,节流
在什么场景下会选择用vue的动态路由
当用户可以访问的路由是有后端返回的,此时就需要采用动态路径注册可以访问的路由
路由添加动态路由的方式:router.addRouter
(具体的路由信息)
路由懒加载有什么好处
默认情况下vue在显示首页之前要加载所有的路由,这样的话首屏打开的速度就很慢
采用路由懒加载的好处是,跳转指定的路由时在加载相关的页面,首屏的打开速度就很快了
你什么怎么理解组件化思想的
就是讲一个大的页面宅分成一个个独立的小的组件,在拼装成大的页面
好处:可以重复使用,可维护性高,便于分工
你封装过哪些组件:
一般在开发中遇到结构非常相似时,我都会采用组件的方式封装
比如我之前做过一个电商的项目,里面的很多的页面都要对商品列表进行展示(首页列表区,搜索页,列表分类页,购物车页,收藏页等),而每个商品的展示结构在不同页面中是很相似的,当时我就是采用了一个自定义组件的方式做的,将不同的部分通过属性和插槽的方式传入
你是怎么理解MVVM模型
M:model
V:view
VM:view-model
wom我们可以将model理解成程序中的数据,将view理解成页面最终展示的效果,而页面和数据直接的桥梁就是view-model,他是中间环节,所谓响应式指的就是view-model。无论是vue还是react他们都是根据mvvm思想设计的。
vue的路由守卫有什么作用
路由守卫的作用是在路由跳转之前和跳转之后进行拦截,比如你室友哟普权限访问指定的路由就可以使用路由前置守卫,必填路由跳转完成后,我们需要修改对应的标题内容,就可以在路由后置守卫中完成
vue路由传参有哪些方式
params方式由传参和query方式路由传参
param方式路由传参,需要在配置路由时,在路由路径中定义参数的名称,query方式不需要
获取params方式的路由参数通过$route.params.参数名
获取query方式的路由参数通过$route.query.参数名
vue2的响应式原理是什么
它采用了Object对象的defineProperty方法,给代理对象添加属性,他的内部通过get方法返回源对象的属性重新赋值,而响应式就是通过监听set方法是否执行,从而对数据进行劫持,并重新页面渲染。
这种方法的弊端是:要为对源对象的每个属性采用defineProperty方法定义响应式,代码量会非常大,并且源对象后天的属性是布局响应式的,所有vue3采用了更新的技术,直接创建浏览器全新的Proxy对象定义响应式
vue3和vue2有什么区别
首先最大的区别是按需引入,在vue2中所有的api都是绑定在this身上的,尽管很方便,但是太重,对程序的性能不利,而vue3 的设计理念是按需导入,需要什么就导入什么,这样不仅可以提高程序性能,还减少了打包体积
同时vue3 为了向下兼容,不仅引入了权限的组合式api语法,还保留了vue2中选项式api语法,这样给了我们更多的选择性,当然我个人比较喜欢使用setup语法的写法。
另外就是vue3重写了底层的响应式部分,vue2 采用的是Object.defineProperty方法实现响应式,vue3采用的是Proxy代理对象实现响应式。
v-if和v-show的区别
v-if采用的是渲染和移除DOM的方式
v-show是通过display样式显示和隐藏DOM
通常某个结构如果只是在页面加载是判断是否显示采用v-if
如果某个结构需要反复显示和隐藏采用v-show
$nextTick有什么作用
用于延迟执行。,通常用于手动更新DOM,因为Vue是响应式框架,响应式本身是需要时间的,当状态变化后,重新渲染DOM是需要等待一点时间的,那么$nextTick方法里面的代码会在DOM重新染完成后执行。
计算属性和监听器如何选择(computed 和 watch 的区别?)
当一份数据需要根据其他数据计算返回,此时使用计算属性,比如有一个学生数组,现在需要返回学生的平均年龄。当数据的变化需要操作其他事情时,此时使用监听器,比如当页码发生变化后,需要重新加载当前页数据
js有哪些数据类型
number:数字类型
string字符串类型
boolean布尔类型
null空
undefined未定义
object对象类型
symbol唯一类型
biglnt长整型
array和function类型本质上也是object类型
px,em,rem的区别
px:像素
em:当前的元素的font-size大小,如果当前的元素的font-size没有设置大小,从父元素中继承,如果所有的父元素都没有设置font-size,那么就从html元素中继承
rem: 是网页根元素(html元素)中定义的font-size大小,如果html元素没有定义font-size属性,那么默认是16px
所有默认情况下:1rem===16px ,rem单位通常用于移动端布局
css的变形函数有哪些
变形属性是:transform,他有4个变形函数,分别是:
translate:平移
scale:缩放
skew:倾斜
rotate:旋转
Promise对象
Promise对象用于处理回调地狱
比如有两个请求,第二个请求是建立在第一个请求的基础之上的,以前我们需要在第一个请求的回调函数里面发送第二个请求,这样就形成了回调地狱。可以在Promise对象回调函数中发送第一个请求,通过.then方法获取第一个请求的结果,然后在.then方法中发送第二个var, let, const请求,再通过第二个.then(方法,返回第二请求的结果,这就是Pramise链式调用,他解决了回调地狱。
Promise对象在创建的时候,本身需要传回一个回调函数,该回调函数有两个参数:resolve,reject
resolve用于返回成功的结果,reject用于返回失败的结果
async 和 await有什么作用
async定义异步函数,在异步函数中,通过await提取Promise返回结果,这样的好处是不需要写 .then方法了,因为要写一层回调函数,采用async和await可以做到一层灰调函都不需要写了
微信小程序一个页面包含哪些文件
四个文件夹
index.wxml:页面结构文件
index.wxss:样式文件
index.js:逻辑与交互文件
index.json:是配置文件
微信小程序中页面跳转如何传参
在小程序中页面跳转时通过query方式传递参数,方式是: index?a=100&b=200 在页面的onLoad生命周期函数中,通过该函数的参数获取路由参数,方式是: onLoad(options)这里的optnos对象保存的是所有参数
微信小程序如何实现页面跳转
通过组件:Navigate跳转页面,通过url属性设置地址
通过wx.navigateTo方法跳转页面
如果跳转的页面是table页面,navigate组件需要设置open-type=“SwitchTap”,通过wx.switchTap跳转页面
vue的生命周期函数有哪些
beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeDestroy, destoryed 如果是缓存的组件,还有两个actived,deactived 在vue3中,beforeDestroy和destoryed 改成了beforeUnMount和unMounted 同时vue3环推出了6个组合式api命周期函数分别是: onBeforeMount,onMounted.onBeforeUpdate. onUpdatedonBeforeUnMount和onUnMounted
css过渡和动画的区别
过渡是一次性动画,通水需要借助鼠标事件触发,比如鼠标悬停时,触发某个过渡效果
动画是连续性的,可以利用关键帧定义复杂连续的动作,不需要借助任何事件去触发。动画属性是animate,定义动画关键帧的关键字是@keyframe
var,let,const
var可以定义重名的变量,后定义的变量会盖之前定义的变量,var定义的变量存在作用域提升,所有变量会提升到当前作用域的项端定义。var定义的变量只有方法作用域,没有块级作用域。 let不可以定义同名变量。let定义变量不存在作用域提升。let定义的变量存在块级作用域. const定义的变量是常量,常量在定义的时候必须要赋值,并目之后不能修改值。其他用法跟Ict一样.
构造函数有什么作用
构造函数可以理解成js中的类型,它的作用是定义一个固定的模板,之后根据这个模板可以创建出无数个对象
如果将一个字符串的内容翻转
let str = "abcd" str.split(").reverse0join(") 将一个字符串先打散成数组,将数组翻转,再将数组拼接成一个字符串
数组的map方法有什么作用
数组的map方法,用于将一个数组根据指定的规则映射出一个全新的数组比如:将一个学生数组里面的所有年龄映射成一个年龄数组
本地离线存储 localStorage 、sessionStorage
sessionStorage存储的数据在浏览器关闭后会自动清除
localStorage存储的数据会一直保存在浏览器中,除非手动清除
iframe标签有什么作用
iframe是内嵌架标签,用于在一个网页中嵌入另一个完整的网页
CSS选择器及优先级
Id选择器>类选择器>标签选择器
!important具有最高级别的优先级
属性选择器,交集选择,并集选择器,后代选择器,子选择器
null 和 undefined 的区别?
null是空指针,本质上是一个object类型,这是js底层的一个BUg,至今没有修复
undefined是未定义,不知道他是什么类型
比如一个方法返回一个undefined,说明方法没有返回任何数据。
如果一个方法的返回值是null,这个null一定是主动返回的
防抖和节流的区别
防抖:指定的时间后触发,如果提前触发,等待时间需要重新计算
节流:指定的时间内只触发一次
##
vue有哪几种插槽
普通插槽,具名插槽,作用域插槽
具名插槽如何使用呢?slot标签添加name属性,通过template标签的v-slot属性制定具体的插槽名字。
作用域插槽的优势是什么?可以利用插槽将组件中数据回传给组件的调用者
事件修饰符有哪些
.stop组织事件冒泡
.prevent阻止默认行为
.self只能通过自身元素触发
.once只触发一次
.capture设置事件的触发顺序为捕获顺序
v-model的修饰符
.trim取消字符串两端空格
.lazy设置为懒加载模式,在光标离开文本框时触发
.number强转为数字类型
.sync修饰符的作用
在自定义组件中,实现对多个数据的双向绑定
方式是 属性名.sync = "绑定的数据"
在组件中触发的事件名必须是update:属性名
在vue3中取消了.sync修饰符,vue3将v-model和.sync修饰符进行合并
在vue3中,使用v-model.属性= "绑定数据",在组件中通过 update:属性 定义事件
这样的话,在vue3就可以使用v-model绑定多个属性
自定义组件如何使用v-model实现双向绑定
在使用组件时通过:v-model="数据"
在组件内部的属性必须定义为value
在组件内部的事件必须定义为input
在vue3中...
vue操作数组并且保留响应式的7个方法
-
push():在数组最后添加数据
-
splice():实现元素的删除和插入
-
pop():删除数组最后一个元素
-
shift():删除数组第一个元素
-
unshift():在数组的最前面添加元素
-
sort():对数组进行排序
-
severse():对数组进行翻转
如果想通过数组的下表操作数组,并且还要具备响应式,可以使用vue的一个api是$set
什么时候会用路由缓存
当从A页面跳转到B页面,A页面中的页面状态,那么此时就应该将A页面缓存起来
通过keepalive组件将routerview路由视图组件进行包裹,并给keepalive组件设置一个include属性,给该属性绑定一个数组,在数组中定义A页面组件的名称。
在vue3,keepalive和routerview用法需要反过来,routerview中通过component属性,返当前页面组件,在同Component内组件动态生成当前组件,然后在keepalive中缓存,就是组件的mounted和destroyed这两个生命周期函数就不会反复执行,
如果我们在组件加载时和销毁时,需要做一些操作,此时可以使用actived和deactive这两个生命周期函数代替
自定指令有什么作用
就是对DOM操作的封装,
我们可以利用自定义指令,结合用的权限,对页面中操作按钮的显示做控制
什么样的场景下会去使用插槽
当组件中的某个区域到底以什么结构呈现时,就可以在这个位置放置一个插槽,
在使用该组件时,在组件标签之间在传递具体要呈现的内容
自定义插件有什么作用
我们在使用vue框架时,很多时候会对vue本身进行扩展,比如扩展全局,全局混入,全局过滤器,自定义指令,甚至会对vue的原型进行扩展,这样的话,代码就会分散,自定义插件的作业就是将对vue的扩展整合到一起。
方式是:定义一个对象,在对象中定义一个install方法,该方法的一个参数就是vue,然后将对vue的所有扩展在当前方法中定义。最后通Vue.use(自定义插件对象),其实这个use方法就是去执行插件对象的install方法。
什么是宏任务和微任务
宏任务和微任务都是异步任务,宏任务是浏览器发起的,微任务是JS自身发起的
在 JavaScript 中,任务可以分为同步任务和异步任务。异步任务又分为宏任务和微任务。宏任务是指那些需要长时间执行的任务,例如 XMLHttpRequest、setTimeout、setInterval 等。宏任务会阻止其他任务的执行,直到它完成或被取消。微任务是指那些短时间执行的任务,例如 Promise.then、.catch、.finally、process.nextTick 等。微任务不会阻止其他任务的执行,它会在当前任务完成后立即执行。在 JavaScript 中,任务的执行顺序是按照调用栈的顺序来的,但是异步任务的执行会受到事件循环的影响。事件循环会检查当前任务是否完成,如果没有完成,就会将控制权交给下一个任务。因此,微任务会比宏任务先执行。
比如:定时器即时宏任务,Promise就是微任务
在同一层级中,微任务要先于宏任务,当然主线程肯定最先执行
所有的微任务要添加到微任务队列中排队执行
所有的宏任务也要添加到宏任务队列中排队执行
微任务中添加的微任务会放置到第一微任务事件队列中排队
微任务中添加的宏任务会放置到第一宏任务事件队列中排队
微任务中添加的微任务会添加到当前宏任务的微任务事件队列,必须要全部执行完成后,才会执行下一个宏任务
宏任务中添加的宏任务会放置
console.log('开始...') setTimeout(() => { console.log('a'); 1)6 注意: 创建Promise的过程,还是是主线程 new Promise((resolve) => console.log('b'); resolve( 'c') }).then(r=>[ console.log(r);// 所有的宏任务,要先先放置到宏任务队列中去排队执行 setTimeout(() => { console.log('d'); 06new Promise((resolve)=> console.log('e'); resolve('f') }).then(r=>! console.log(r); 2 6 console.log('结束....'); //开始 b 结束 c a d
前端页面如何优化
-
通常我会开启语法检查,他会帮我检查程序中的语法是否有缺陷,比如定义的变量和导入的方法没有使用
-
养成良好的开发习惯,能多拆模块就多拆模块,能都封装成组件就封装组件,这样就可以减少代码冗余,减少代码冗余,就是减少打包体积
-
模块按需导入
-
路由采用懒加载方式
-
页面中采用的图标是雪碧图(所有的图标放在一张图上叫做雪碧图),页面中的图片资源如果不大可以采用base64转码
-
页面中的图片或者视频资源,可以采用独立的服务器发布
-
尽量优化代码,减少DOM结果的回流和重绘
-
第三方插件,可以使用cdn加速,能不安转到本地最好,比如:echars,百度地图api 等等