前端面试必会的高端面试题看完再倦都不怕
高端面试题(说的越全越详细越好)
欢迎评论-点赞-收藏 👍👍👍👍👍👍👍👍👍
1.防抖节流以及使用场景 具体到项目模块?
防抖就是事件触发N秒后执行的回调,如果在这N秒内又被触发则重新计时。使用场景为input搜索框。 节流就是节省 节流就是事件在某一时间段内只执行一次,或在这次事件请求完成之后才能请求下一次,多次触发不会累加请求次数只要当前请求完成才可继续请求。主要作用就是防止某一时间频繁触发。和防抖原理不同。节流通过设置一个值来实现。
2.递归 以及使用场景?
递归就是方法自己调用自己,使用递归需要找到递归的公式结束条件,当到达这个条件后不再继续调用。 常用与递归将数据转换为children类型数据时使用递归。
什么时候用递归? 当解决一个问题用递归和不用没有明显区别,或者使用递归代码更简单而不用递归需要写很多代码时用递归。 如果使用递归解决一个问题写起来简单,但是有明显问题,那就不能用递归。 权限分配,数据统一转换children数据类型时使用。
3.闭包,以及使用场景?
闭包就是函数外部访问函数内部的变量,同时函数内部也可以访问函数外部,都称作闭包,闭包可以读取其他函数内部的变量,并将其一直保存在内存中,坏处就是会造成内存泄露或溢出。 内存泄露就是无法被垃圾回收机制回收。 垃圾回收机制: 就是内存管理系统中的机制为了防止内存泄漏。分为以下两种。 引用计数: IE采用的引用计数算法,定义“内存不再使用”的标准很简单,就是看一个对象是否有指向它的引用 标记清除:总体思想和引用技术一致,但是现代浏览器不再使用引用技术而是使用标记清除法来判断,将不再使用的对象定义为无法达到的对象,在js中就是全局对象)触发定时扫描内存中的对象。凡是能从根部到达的对象,都是还需要使用的。无法从根部触发的对象被标记不再使用。
使用场景: 定时器setTimeOut 函数防抖↓ 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。 实现的关键就在于setTimeOut这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现。
4.作用域链;
函数内部创建新的函数,就产生了新的函数作用域,作用域就产生了嵌套关系 作用域链的本质 是底层的变量查找机制,函数被执行时 会优先查找当前函数 作用域中的变量,如果找不到则会逐级查找父级作用域直到全局作用域 ,全局找不到 变量返回undefined 函数调用报错 子作用域能够访问父作用域 父作用域无法访问子作用域 OR 作用域链就是底层变量的查找机制,优先查找当前作用域,如果没有查找父级作用域,如果没有继续往上找,直到全局作用域中还没有就返回undefined,父级作用域不能访问子级作用域,子级可以访问父级作用域。 创建作用域的方式就是在函数内创建一个新的函数就生成了新的作用域。
思路:什么是作用域链》它的作用域》如何创建作用域?
5.预解析?
1.把变量声明提升到当前作用域,只会提升声明不会提升赋值
2.把函数的声明提升到当前作用域,只会提升声明,不会提升调用。
3.先提升function 再提升var
6.深拷贝浅拷贝;实现方式;每种实现方式的优缺点?
拷贝就是赋值对象的一种类型方式,object 浅拷贝是内层拷贝的引用地址,如果是简单类型拷贝基本类型的值,如果是引用类型拷贝的就是内存中的地址。只是复制一个对象这个对象在父对象堆内存中关联,一个改变都会改变。
深拷贝是复制一个对象这个对象在父对象堆内存中不关联,属于重新创建一个新的对象,这个对象改变和原来的父对象不会关联改变。 浅拷贝是开辟一个新的栈,对象属性相同,对应不同的地址。
如何实现浅拷贝? const obj1 = {a: 1, b: {c: 2}}; const obj2 = Object.assign({}, obj1); // 使用Object.assign()方法浅拷贝 (额赛应/额赛eng)
const obj3 = {...obj1}; // 使用展开运算符浅拷贝
如何实现深拷贝? const obj1 = {a: 1, b: {c: 2}}; const obj2 = JSON.parse(JSON.stringify(obj1)); JSON.帕啊斯 这种方式原理是先将对象转换为字符串parse再转换为新对象,这样就可以实现对象的深拷贝。 使用该方法进行深拷贝时,如果对象中存在循环引用的情况,则会抛出异常。
7.vue双向绑定原理?
vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的 Vue2是采用Object.defineProperty劫持setter和getter数据变化发布消息给订阅者触发相应的回调来渲染视图。(也就是说数据和视图同步,数据变化视图变化,视图变化数据也随之变化。)
Vue3是采用Proxy劫持整个对象,而不是对象中的某个属性,Proxy的功能更强大,可以直接监听数组变化,还可以阻止对象上的默认行为。
需要整理↓: 区别,优缺点, 还有diff算法 前后比较的一个规则,发布者订阅者模式,还有哪些设计者模式。
8.vue响应式原理?
结合MVVM模式去讲就可以 Vue的数据响应式就是MVVM的更新模式 它有三个层级,分别是数据层model 视图层 view 视图模型层ViewModel。 ViewModel通过Observer监听model的数据变化,自动同步更新到view视图层上。 ViewModel负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作;
优点:分离view和model层,降低代码耦合,提高视图逻辑复用性,自动更新DOM利用双向绑定原理,让数据更新后视图也自动更新。 缺点:出现问题很难调试,因为使用了双向数据绑定,页面出现问题很难判断是view层还是model层,数据长期持久不会释放内容,虽然保证了数据一致性,可能造成性能开销,消耗更多内存。
9.vue生命周期?
初始化阶段: new Vue实例化,初始化事件和生命周期函数,钩子函数执行beforeCreate, 钩子函数执行完成实例创建created
挂载阶段: 编辑模板-是否有el选项: 如果有继续检查template选项,返回return函数。生命周期函数执行beforeMount, 真实Dom挂载完毕执行mounted。 如果没有,编译el选项对应的标签作为template,把虚拟Dom和渲染的数据一并挂到 真实Dom上,真实Dom挂载完毕执行mounted。
更新阶段: data数据改变 更新Dom之前,生命周期钩子函数执行beforeUpdate,虚拟Dom重新渲染, 打补丁到真实Dom,生命周期函数执行updated。此时如果数据继续改变重复执行这个循环
销毁阶段: 当$destory被调用,比如组件Dom被移除v-if,生命周期钩子函数执行beforeDestory, 卸载事件监听器,手动销毁定时器,生命周期钩子函数执行Destoryed。
10.vue的组件通信?
父传子,组件中:传递数据,子组件通过props来接受,V3:defineProps({数据}) 子传父,组件中通过emit触发事件,传递参数,父组件在标签中定义方法接受。 V3:defineEmits(['事件名']),参数 跨组件通信 provide 发送, inject接收
11.vue2和vue3的区别?
1.双向数据绑定原理不同
Vue2:采用es5的Object.Defineproperty对数据进行劫持结合发布者订阅模式来实现的。
Vue3:采用es6的Proxy来劫持整个对象,可以监听数组,不用再单独对数组做异性操作。
2.APi不同
Vue2采用选项类型APi,Vue3采用合成类型APi,合成型API相比选项型更加简便整洁。
3.Vue2数据存放在data中,Vue3通过setup方法,创建数据时通过ref和reactive。
4.Vue3采用按需导入导出可以让项目更加轻量级,v-if和v--for优先级不同vue2中V-for优先级高,Vue3相反,Vue3没有过滤器,支持多个根节点,插槽不同,Vue3使用V-slot而Vue2直接用slot
5.生命周期不同
vue2 --------------- vue3
beforeCreate -> setup()
Created -> setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroyed -> onBeforeUnmount 昂忙特
destroyed -> onUnmounted 昂昂忙替的
-----------------------------------------------------------
activated -> onActivated
deactivated -> onDeactivated
6.组件通信方式不同
12.小程序登录的流程?
获取表单信息,通过uni.login进行授权登录,通过uni.getUserInfo获取用户信息,然后调用登录接口,传递参数,appid,秘钥,用户名,用户头像,用户表示Code码,用户性别。
13.小程序上线流程?
小程序开发完成测试通过后,在小程序微信开发者工具中右上角上传,点击后发布完后小程序官网有一个版本管理,填写项目类型种类,然后点击确定发布后,平台审核,审核快的1小时内就通过。
14.后台项目如何打包,出现的问题;并部署上线?
不知道就说是运维 或者是前端老大做 nginx配置 配置一些跨域方面的问题。
通过npm run build 打包项目生成dist文件,将dist文件放到服务器根目录前端页面就可以使用了。
15.小程序支付流程?
获取用户所选商品信息,生成订单号,将订单号,回跳地址,参数传递过去,生成支付地址,支付完成回跳到当前页面。
16.小程序超包问题解决?
将页面开启分包,将运行的一些脚本进行压缩优化,将图片文档之类的静态资源放到服务器通过网络请求的方式获取,或者通过压缩来减小体积,最后再打包,npm run dev:mp-weixin
运行npm run build:mp-weixin进行打包
17.小程序上线时遇到的问题?
资质认证,资料不符会无法通过审核
代码审核,需要和微信代码审核机制符合才可以。
功能问题,小程序功能是否符合标准,是否有违反政策的功能和是否小程序功能是否完善,如果小程序开发一半就上线,会被拒绝。
维护问题,一旦小程序上线,需要不断改进功能和用户体验,出现问题需要及时解决,确保用户体验。
优化问题,需要对小程序代码是否符合上线代码标准。
18.vue的diff算法?
diff算法,同级比较
根元素改变:删除重新创建整个DOM树
根元素未变:属性改变,DOM复用,只更新属性
---不全--就地更新没有key值
Or
diff算法就是对虚拟DOM进行对比当数据变化快速找出变化部分,将变化部分进行改变,减少整个DOM的操作,从而提高性能。
根元素改变:首先比较新旧DOM树是否相同,如果不同,删除重新创建整个DOM树
根元素未变:如果根节点相同,逐级比较子节点,只更新需要改变的属性
19.小程序生命周期?
应用生命周期:
onLaunch 小程序初始化完成触发,全局只触发一次
onShow 小程序启动,从后台将进入前台显示触发
onHide 小程序从前台进入后台触发
onError 小程序发生脚本错误或API调用报错触发
onPageNotFound 小程序要打开页面不存在触发
onUnhandledRejection 小程序有未处理的 Promise 拒绝时触发
onThemeChange 系统切换主题时触发
页面生命周期:
onLoad 页面加载完成执行 执行一次
onShow 页面加载完成执行 执行多次
onReady 首次现身页面触发 执行一次
onHide 跳转其他页面时触发 监听页面隐藏
onUnload 页面卸载触发
组件生命周期:
created 组件实例创建执行
attached 组件实例进入页面节点树执行
ready 组件在视图层布局完成后执行
moved 组件实例被移动到节点树另一个位置执行
detached 组件实例被从页面节点树移除执行
error 组件方法抛出错误执行。
onPullDownRefresh 监听用户下拉动作
onReachBottom 监听用户上拉触底动作
20.es6的新特性; set和map的区别?
新增了let和const
新增了symbol
新增了箭头函数
新增了模块化
新增了Class类和继承
新增了promise proxy ,async/await
新增了解构赋值let {name} = {name:"lilei",age:34}
新增了扩展运算符 ...
新增了map和set
set和map的区别:
set类似于数组,他的成员是唯一的没有键值对
map类似于对象,有键值对,是键值对的集合。
map是一组键值对的集合,用来解决不能用对象作为键值对的问题,利用map进行查找十分迅速。map可以用来查找数据。map不会对空数组进行监测,不会改变原数组。
Map查找代码↓:
---
set和map类似,也是一组键值集合(没有键,只有值)它的值(key)不能重复,所以在Set中没有重复的Key,通常可以使用Set去重,
Set去重代码:
let arr2 = new Set([1,1,2,3,4])
let arr3 = [...arr2]
console.log(arr2, arr3) // {1,2,3,4} [1,2,3,4]
21.promise理解;async 和await ?
Promise是将异步代码同步去写,Promise()执行是同步的,而then执行是异步
的,Promise可以解决回调地狱的问题,它有三个状态,pending(进行中默认)
,fulfilled(已成功),rejected(已失败),成功执行then函数,失败执行,catch
函数。
Promise有两种常用的多请求方法,race方法:可以处理多个promise请求 只要
有一个成功就成功, all方法:也可以处理多个promise请求, 全部成功就成功。
Promise 是 ECMAscrpt6新增的引用类型 可以通过new操作符来实例化
async 和 await 配合使用可以把一个异步函数可以强制处理为一个同步函数,但是它本质是异步的请求,本质也是Promise衍生出来的语法糖,写起来更优雅。async返回的是Promise对象
虽然 '.then回调函数是异步执行的,但它的参数确实是同步执行的。在 Promise 请求完成后,回调函数的参数会立即传递给回调函数,而不会等待队列中的任务执行完成。
宏任务:异步AJAX请求,script中的js文件外层同步代码,文件操作,定时器,所有的事件处理,数据请求
微任务:Promise.then.catch,Proxy,async/await
宏任务是在后台执行的,所以他也是异步的,当我们使用定时器函数创建一个定时器时,该定时器会在后台等待一段时间后执行,而主线程会继续执行后面的代码,不会阻塞,当定时器时间到达后,回调函数被添加到宏任务队列中,等待当前任务执行完毕后执行。
需要注意宏任务和微任务执行顺序不同,当前任务执行完成后js引擎会先执行所有的微任务,然后再执行宏任务,这种顺序的特点适合处理需要优先执行的异步操作,而宏任务更适合处理一些需要后台执行的任务。
22.vue3中ref和reactive的区别?
ref和reactive都是借助Proxy来实现的
ref把基本类型的数据变为响应式数据。参数类型为基本类型,引用类型,DOM的ref属性值
reactive是可以创建原始对象的响应式副本,将引用类型转为响应式数据。参数必须为对象或数组。
23.使用vue3的哪个版本?
使用Vue3.2.20版本,Vue3最新版本。
24.vue3的新特性有哪些?
Vue3引入了Composition(组合式Api),结合TypeScript进行类型重写
Vue3采用更好的响应式系统Proxy代理对象,性能更强大
更好的组件通信方式,defineExpose,defineProps,defineEmits,provide,reject
25.事件循环机制?
Js的事件循环执就是Event-loop,是javascript为解决异步编程的一种机制。
1.进入到script标签,就进入了第一次事件循环
2.遇到同步代码立即执行
3.遇到宏任务,放到宏任务队列中
4.遇到微任务,放到微任务队列中
5.执行完所有同步代码,执行微任务代码
6.微任务代码执行完毕,本次队列清空
7.寻找下一个宏任务,重复步骤一,以此反复直到清空所有宏任务,这种不断重复的执行机制就叫事件循环。
宏任务:异步AJAX请求,script中的js文件外层同步代码,文件操作,定时器,所有的事件处理,数据请求
微任务:Promise.then.catch,Proxy,async/await this.nextTick ==微任务
// 宏任务在此运行
function nextTick(callback) {
setTimeout(() => {
callback();
});
}
Promise.resolve().then(() => { // 微任务在此运行 });
26.cookie sessionStorage、localStorage的区别?
cookie 扣Kei :KUKI sessionStorage localStorage // 四道闰值
cookie:是保存在客户端的纯文本文件text,客户端就是用户电脑本地。用于识别用户的跟踪会话。
sessionStorage:是本地的会话储存,数据在同一个会话中才可以访问,会话结束后也会被销毁。
localStorage:是本地储存,不手动清除不会销毁。
cookie 是保存在用户客户端的纯文本text文件,一般使用的键值对的方式表示,就是name=123 name携带的值时123
里面的参数:
Name:这个是cookie的名字
Value:这个是cooke的值
Path:这个定义了Web站点上可以访问该Cookie的目录
Expires:这个值表示cookie的过期时间,也就是有效值,cookie在这个值之前都有效。
Size:这个表示cookie的大小
---
27.axios的封装?
在src文件夹内创建utils文件夹
2. 在utils文件夹内创建request.js文件
3. 在request.js内引入axios
4. 使用axios.create方法创建axios的实例,在axios.create方法里面可以配置请求的公共地址和超时时间以及其他的一些配置
5. 创建请求拦截器和响应拦截器
6. 在请求拦截器里面可以获取vuex的token,并通过config.header.token = vuex的token,将token发送给后台
7. 在请求拦截器里面我们配置loading加载
8. 在响应拦截器里面我们可以结束loading加载以及token的过期处理,以及错误响应信息的处理
9. 最后通过export default 导出axios的实例对象
10. 在src文件内创建api文件夹
11. 在api文件夹内创建对应模块的js文件
12. 在对应的文件里面引入request.js文件
13. 封装api方法
14. 最后通过export default 导出封装的api方法
瑞快斯特 .use 康飞哥,error 艾瑞
瑞炮斯 .use
28.小程序网络请求的封装?
讲代码思路即可:
request文件中:
// 请求的基地址
const Baseaddress = "https://meituan.thexxdd.cn/api"
// 网络请求 等同于 axios请求和拦截器
const http = function request(options) {
//封装的实际代码
const list = uni
.request({
url: Baseaddress + options.url,
header: {
'custom-header': 'hello' //自定义请求头信息 在这里配置携带token
},
methods: options.methods,
data: options.data
})
.then((data) => {
//data为一个数组,数组第一项为错误信息,第二项为返回数据
console.log(data);
return data.data;
});
return list;
}
//抛出request 在此组件可以简写
module.exports = {
http
}
APi文件中:
// 导入请求函数
const { http } = require('../utils/index')
// 配置请求地址 -方法
export const frontpage = function (data) {
return http({
// 定义接口
url: "/frontpage",
// 请求方式
methods: "GET",
// 传递数据
data,
success: (res) => {
return res//返回结果
}
})
}
29.文件上传?
文件上传 图片上传
uni-file fail哦 fai哦
el-upload elemen-ui的上传图片
van-uploader vant的上传图片
30.websocket?
WebSocket可以实现实时通信,而且实时性高,延迟低,可以在线聊天,直播等。
传输数据时采用二进制帧格式,可以将数据转化为二进制码进行传输,比http请求响应式模式的文本数据更小,速度更快。
缺点:
兼容性差,老版本浏览器不支持,排错比较难因为链接状态是一直保持的,需要使用浏览器的开发工具进行调试。
WebSocket是HTML5下一种新的协议
它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的
Websocket是一个持久化的协议即时通讯就是
方法:
ws.send() - 向服务器发送数据
ws.close() - 关闭连接
事件:
ws.onopen - 建立连接时触发
ws.onmessage - 客户端接受服务端数据时触发 昂买谁治
ws.onerror - 通信错误时触发
ws.onclose - 连接关闭时触发
31.普通函数和箭头函数的区别?
普通函数用function定义箭头函数用=>定义,箭头函数不能用于构造函数,普通函数可以用构造函数就是首字母大写创建对象。
箭头函数全是匿名函数,普通函数可以匿名也可以具名
箭头函数没有argument对象,普通函数调用后都有一个arguments对象用来储存实际传递的参数,箭头函数没有。
箭头函数没有prototype原型对象,箭头函数不具有super,不具有new.target。
OR
普通函数存在变量提升,箭头函数没有
2.普通函数this指向,谁调用指向谁,箭头函数是在哪里定义就指向谁
3.普通函数可以当成构造函数,而箭头函数是不可以
4.箭头函数没有arguments,如果要接受所有的参数用...rest
32.route的区别?
this.$router是全局路由器对象
this.$route是当前激活的路由对象,包含了当前的路由信息。
router操作路由的,route获取路由信息的。
33.如何使用分包?
在小程序项目根目录中创建subpackages的文件夹,存放分包的文件和代码,在小程序的app.json中添加subPackages字段,用来指定分包的路径和名称,在页面组件中引入分包的文件和代码,usingComponents字段中引入,需要注意分包不能超过32mb,分包之间不能相互依赖,需要按照开发文档需求进行使用分包。
34.原型链,原型
任何对象都有原型对象,也就是prototype属性,所有的对象都是通过new来创建的,任何原型对象也是一个对象,拥有_proto_属性,这样一层一层向上找的过程就形成了链式结构,这就是原型链。
每一个构造函数都有一个prototype属性,指向原型,这就是原型对象。
每个原型对象都有constructor指向object和prototype指向原型对象
Or
原型对象也是对象,那我们只要找到对象的构造函数就能知道_proto_的指向了,而js中对象的构造函数是Object,所以对象的原型对象就是Object.prototype ,所以说原型对象也是对象,那原型对象的原型对象就是Object.prototype,不过Object.prototype比较特殊没有上一层的原型对象,或者说他的_proto_指向null
35.微信小程序的登录
通过uni.Loging方法登录返回success参数中有code用户登录凭证。
通过uni.getUserProfile获取用户信息返回,用户昵称,头像,性别,国家,省份,城市,
getuserinfo已经停用,京东小程序如果未授权会直接报错,而且不会弹出授权,getUserprofile可以弹出授权。
getUserProfile ↓
//概特苏破肉fail哦
//概特优则破柔fail哦
36.JS数据类型
基本数据类型: Undefined、Null、Boolean、Number、String、Symbol、BigInt。
引用数据类型:object,function,array
37.this指向
this指向在函数定义时是确定不了的,只有函数执行的时候才能确定this到底指向谁
1.全局作用域或者普通函数中this指向全局对象的window,
2.定时器中,this也指向全局对象的window,
3.方法调用中谁调用this,this就指向谁
4.构造函数中this指向构造函数的实例
38.Vue常用的指令
v-if,v-show,v-html,v-text,v-on,v-bind,v-model,v-for
39.Vue常用修饰符
.trim 去除首尾多余的空格 锤木
.stop 阻止事件冒泡 四套破
.once 只渲染一次 万斯
.self 事件只作用在元素本身 赛哦父
.number 将值转化为number类型
.capture 组件之间捕获 开坡true
.prevent 阻止元素的默认行为 破瑞问特
.native 事件穿透,让我们可以在自定义组件上定义事件和方法 耐提悟
trim 垂木 去首尾空格
40.Vue中Key的作用
避免dom元素重复渲染. 我们一般在设置key的时候首先尽量会设置为id,或者index下标
就是在v-for中使用key,如果不使用key数据可能会很庞大,而且要经常对数据进行增删改查操作,整个列表都会重新渲染一遍,会很费事,,而使用key就可以让每个元素拥有一个id名字识别到它的唯一性,我们在操作时就可以根据它的id来操作就不用每次都重新渲染所有数据了,一般key值为id不使用index下标,因为index顺序无论怎么颠倒都是0,1,2,这样排列,导致vue会复用错误的旧子节点,做很多额外的工作。
41.Slot插槽的理解
插槽就是一个占位符,将定义的组件内容展示出来,自定义的组件如果写内容是不会显示出来的,所以要使用slot插槽来解决这个问题。
默认插槽:匿名插槽,一个组件只能有一个匿名插槽,slot没有指定name时会默认展示这个插槽。
具名插槽:带有具体名字的,在slot中定义name,一个组件可以出现多个。
作用域插槽:和匿名,具名插槽类似只是可以传递数据给父组件,让父组件收到数据决定如何渲染该插槽。
42.如何解决跨域,以及原理? 同源策略是什么?
本地跨域是通过在`vue.config.js`文件里面的`devServer`属性里面的`proxy`属性里面配置,一共配置三个属性,分别是`代理名称 代理地址 开启跨域 重写路径`
原理是通过本地的脚手架webpack生成一个本地服务器去访问服务端数据这样就可以解决, 因为服务端请求服务端没有跨域问题。
同源策略:
出于安全考虑默认网页中使用JS发送请求,请求的服务器和当前所在网页服务器必须一样,即两个请求地址的http协议、域名、端口必须一致。不一致就会产生同源策略。
补充:
Vue中解决跨域问题
Vue脚手架生成的项目包,自带一个服务器,支持快速设置代理服务器,临时解决跨域问题,不适合上线。
43.Vue和JQuery的区别
JQuery是js封装的一个类库,主要是为了方便操作DOM元素,而vue是一个框架,并且可以从真实的dom构建出一个虚拟的dom树,通过diff算法渲染只发生改变的dom元素,其他的相同dom不会重复渲染。
Vue是操作数据的,JQuery是操作DOM的。
44.Vue中data发生变化,视图不更新如何解决?
因为Vue实例中的数据是响应式的,而我们新增的属性不是响应式的,由于受JavaScript限制,Vue无法监测属性新增还是删除,所以有时候无法实时更新数据到视图上。
在项目中遇到这种问题通常使用this.$set方法去解决,他一共有三个参数,分别是目前属性,新增属性,新增的值。
45.为什么Vue中data必须是一个函数
如果data是一个函数的话,这样每复用一个组件就会返回一份新的data,类似于每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据,如果单纯写成对象的形式,就使所有组件实例共用同一份data,会造成一个变了全都会变的结果,所以说vue组件的data必须是一个函数,这都是因为js特性带来的跟vue本身设计无关。
46.Props如何设置默认值
设置默认值:default
自定义验证函数:validator
设置普通字符串: default:String,
设置对象: default:()=>{}
47.vue项目是打包了一个js文件,一个css文件,还是有多个文件?
vue项目打包是将多个文件合并一个js文件和一个css文件
48.Vue-cli工程常用的npm命令有哪些?
1.npm i 下载node_modules 资源包
2.npm run dev OR npm run serve 启动项目
3.npm run build 通过vue-cli生成环境部署,打包命令
4.npm run build--report 查看vue-cli生产环境部署资源文件包大小
49.做过哪些Vue性能优化
1.单页面中通过keep-alive缓存组件
2.合理使用v-if和v-show,因为v-if值为false时内部指令不会执行,有阻断能力,很多情况下v-if代替v-show
3.v-for循环时使用key保证唯一性,不适用索引(vue采用diff算法就地更新策略)
4.合理使用路由懒加载,异步组件
5.数据持久化问题,使用防抖,节流优化,对于一些不展示的数据尽可能少执行或不执行。
6.使用CDN加载第三方插件依赖包,优化脚本文件gzip进行压缩。
50.Vue中路由传参的方式
通过params传递参数,获取属性值时可以通过:this.$route.params.id
this.$router.push({
name:"admin",
params:{
id:item.id
}
})
这个组件对应的路由配置:
{
//组件路径
path: '/admin:id',
//组件别名
name: 'admin',
//组件名
component: Admin,
}
query传参,路由中无需配置
this.$router.push('/home?id='+id)
区别:
params传参只能用 name,不能用 path。地址栏不显示参数名称 id,但是有参数的值。
query传参name 和 path 都能用。用 path 的时候,提供的 path 值必须是相对于根路径的相对路径,而不是相对于父路由的相对路径,否则无法成功访问。
地址栏显示参数格式为?id=0&code=1
51.Vue中路由跳转方式
<router-link :to="{path:'/home'}"> 不带参数
<router-link :to="{name:'home', params: {id:1}}"> 带参数
<router-link :to="{name:'home', query: {id:1}}"> 带参数
this.$router.push('/home') 不带参数
this.$router.push({path:'/home'})不带参数
this.$router.push({path:'/home',query: {id:'1'}})带参数
this.$router.push({name:'home',params: {id:'1'}}) 带参数
`this.$router.go(N)` 向前跳转或后跳转,N为正数或负数
this.$router.replace 跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面) 用法和push相同
52.Vue的事件穿透方法
native 事件穿透,让我们可以在⾃定义组件上定义事件和⽅法
53.Vue中加载应用太多加载慢,什么原因,如何解决?路由懒加载原理?
1、使用 vue-router 懒加载解决首次加载时资源过多导致的速度缓慢问题
2、使用CDN加速
3、组件按需加载
4、图片资源压缩
5、对引用多次的文件进行处理,对大的文件进行分隔
6、nginx开启gzip
54.如果想要修改element-ui中的样式
创建一个全局样式文件,然后再当前vue页面中的style标签下写element-ui样式,
不能使用scoped属性,写了不会覆盖样式。
`使用/deep/进行深度修改样式`
找到需要修改的样式的标签名的类名,在类名前加/deep/,这种方式可以强制修改element-ui样式,可直接用到加了scoped属性的style节点下。
55.小程序双向数据绑定和Vue双向数据绑定的区别
Vue中进行数据绑定后数据修改了直接可以更新到视图中,小程序中data数据修改不会同步,小程序中需要调用this.setData()方法
Or
在vue中进行数据绑定后,当数据修改了会直接更新到视图上
但是在小程序中呢,data数据修改是不会直接
同步到,必须调用this.setData()这个方法
56.Vue操作DOM节点的方法有哪些?
1.Ref,Vue中的ref是把当前DOM元素抽离出来,通过this.$refs.属性值就可以获取到整个标签元素。
2.Document.querySelector/getElementById/getElementsByName等等...
57.Vue有哪些内置的组件
component 动态组件
transition 动画 Or transition-group 踹SEI神
keep-alive 缓存
slot 插槽
58.常用的组件库
Vant Vant-Weapp(小程序) Element-UI Element-UI-PLUS(Vue3) Boostrap Echarts Uni-App
59.Vue长列表优化
当页面DOM元素较多时,渲染速度会变慢,会导致浏览器内存不足,甚至浏览器卡顿,所以解决方案就是减少DOM渲染。
通过按需进行加载DOM,比如只显示用户可视化区域的数据,从而减少DOM结构,实现性能提升,或通过分页的形式渲染DOM元素,但是这些只能解决一时的,最完美的方法是使用长列表优化,首先下载插件vue-virtual-scroll-list第三方插件通过虚拟列表进行滚动加载数据。
代码↓
// 安装
npm i vue-virtual-scroll-list --save
<virtualList
style="height: calc(100vh - 100px);
overflow-y: auto;border:1px solid"
:size='50'
:keeps='15'
:data-key="'id'"
:data-sources="data"
:data-component="itemComponent"
:extra-props="{
itemClick
}">
</virtualList>
60.Vue的数据更新流程?什么是虚拟DOM > diff算法参考18题 >重绘回流参考71题
生成的新的dom结构和旧的虚拟dom结构对比,利用diff算法找不同,只更新变化的部分(重绘/回流)到页面这个过程也叫打补丁。
好处:
提高了更新dom的性能不用把页面删除重新渲染
虚拟dom只包含必要的属性没有真实dom上面的几百个属性
什么是虚拟DOM?
虚拟DOM是因为频繁操作真实DOM是很昂贵的,所以要虚拟DOM解决浏览器性能问题,加入一次操作中有十次更新DOM的动作虚拟DOM不会立即操作DOM,而是将这十次更新的内容报错到本地js对象中,通过js对象渲染到DOM树,避免大量无谓的计算。
Or
虚拟DOM是因为频繁操作真实DOM是很昂贵的,所以要虚拟DOM解决浏览器性能问题,通过将页面更新反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制,从而提高性能!
61.vue是如何提高更新性能的?
vue采用了虚拟Dom结合diff算法提高了vue的性能
Or
Vue采用了响应式数据绑定,结合虚拟DOM减少真实DOM的操作次数,同时还使用缓存组件的方式提高组件的渲染速度,将组件缓存到内存中,当组件需要重新渲染时直接使用缓存的结果避免重复请求渲染,路由中使用懒加载将页面组件按需加载,减少页面加载时间。
Or
Vue通过响应式数据结合虚拟DOM异步渲染,缓存组件和懒加载等提高了组件更新性能和渲染速度,从而提升用户体验。
62.什么是虚拟DOM?它的好处
什么是虚拟DOM:虚拟dom本质上是一个js对象保存DOM关键信息
虚拟DOM的好处↓
1.提高DOM更新的性能,不频繁操作真实DOM
2.在内存中找到变化的部分,再更新真实DOM(打补丁)
63.nextTick是什么?
vue中的nextTick主要用于处理数据动态变化后,DOM还未及时更新的问题,用nextTick就可以获取数据更新后最新DOM的变化;
第一种:有时候需要根据数据动态的为页面某些DOM元素添加时间,这就要求在DOM元素渲染完毕时去设置,但是created与mounted函数执行时一般DOM并没有渲染完毕,所以就会出现获取不到,添加不了事件的问题,这就要用到nextTick处理;
第二种:在使用某个第三方插件时,希望在vue生成的某些DOM动态发生变化时重新应用该插件,也会用到该方法,这时候就需要$nextTick的回调函数中执行重新应用插件的方法,例如:应用滚动插件better-scroll时
$nextTick是处理异步dom元素的,DOM更新完执行$nextTick,直接通过$refs操作dom元素无法
获取到dom元素,因为dom元素是异步更新的必须用$nextTick才可以。
代码示例↓:
使用时:在标签中绑定ref=‘值’ 在事件中↓
this.$nextTick(()=>{
this.$refs.值.focus()//实现自动获取焦点
})
64.什么是单向数据流
数据从父组件传递到子组件,子组件没有权利修改父组件,如果要修改可以通知
父组件去修改。
Or
单项数据流就是指数据流的方向,数据只能从父组件传递到子组件,不能反向传递,如果子组件要修改父组件的状态及数据需要通过向父组件发送事件来触发父组件才能修改。
65.Vue中的继承
继承简单来说就是让子类继承父类的属性或方法。我们常用的继承有四种,分别是,call继承,原型继承,class类继承,call+原型混合继。
1.call继承是在子类中调用call方法,修改this指向,让this指向父类的属性和方法,这样
就可以在子类访问父类的属性和方法,但是call有个缺点,就是不能继承原型上的属性和方法
2.原型继承就是将父类的实例放在子类的原型上,这样就可以通过子类实例去继承父类的属性
和方法,缺点就是原型实例的父类祖先原型改变,实例就会改变。
3.混合继承就是call+原型继承,混合继承的缺点就是被父类调用两次,浪费资源。
4.class继承的关键字是extends,子类通过extends来继承父类的属性和方法,子类通过sup
er关键字,访问父类的属性方法,super必须在子类this之前去调用,添加方法的话可以在
constructor下面直接调用
call//靠
66.Set和Map的使用
Set只有键值没有键名,类似于数组,可以遍历,成员不能重复,常用用于去重。
add:新增 has:判断集合中有没有value, clear:清空 forEach:遍历 entries:返回集合中的所有元素 vlaues 返回一个包含集合中所有键值,delete:删除
Map就像一个字典,是一组键值对的结构,具有极快的查找速度。用来查
3.
找元素。
可以使用map去讲字符串转换为数组,元素格式化,可以使用map方法将一个整数数组的每个元素翻倍构造一个新数组。
还有就是后台请求过来返回给我们一个对象,我们可以通过map返回一个新数组。
67.什么是发布者订阅者模式
订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
举个例子:比如一个商店,会员粉丝经常要询问有什么活动,商店老板每次都要做一次解答,工作重复又麻烦,但是把所有会员的邮箱收集成名单有活动时统一发送邮件,会员就是订阅者,老板就是发布者,发布者在合适的时候遍历一下这个名单,依次给会员发布邮件消息这就是一个发布-订阅模式。
发布者订阅者模式 有三种模式分别是什么以及他的区别 ---
68.小程序和Vue项目打包可能出现哪些问题?
小程序问题:
资源文件丢失,代码冲突,性能问题,安全问题
1.资源文件丢失:打包过程中可能因为一些原因导致一些资源无法加载如图片,样式,丢失或者不正确的被打包。
2.代码冲突:小程序可能用到一些第三方库或者组件,如果这些文件和小程序自身代码存在冲突就会导致小程序无法正常运行。
3.性能问题:打包后的小程序,可能存在一些性能问题,如启动速度慢,卡顿,这些问题可能与代码量过大,渲染层和逻辑层之间的通讯频繁有关。
4.小程序打包过程中可能出现安全问题,比如未经过授权访问,这些问题可能会导致用户数据泄露或被恶意篡改。
Vue项目问题:
路径问题:代码压缩问题,依赖管理问题,资源文件处理问题
1.路径问题:打包过程中,可能因为一些原因导致路径一弄不正确,导致页面无法正常访问。
2.代码压缩问题:打包是为了减小文件体积,可能会使用代码压缩工具对代码压缩,所以会导致在一些代码出现问题,如变量被修改,代码顺序变化等。
3.依赖管理问题:打包时可能遇到依赖管理问题,比如依赖包版本不匹配,依赖包冲突,这些问题可能导致打包后的代码无法正常运行。
4.资源文件处理问题:打包时,可能遇到资源文件处理问题,比如图片压缩不合适,字体文件不正确等,这些问题都可能回影响页面加载速度。
为了避免这些问题我们在打包前可以进行一些代码监测,优化和依赖管理,以确保打包后的代码和质量可靠性,同时我们也可以使用一些打包工具,提高打包效率,如webpack进行打包。
69.Vue的路由模式
1.哈希模式 Hash 历史模式 History
哈希模式的路由形式是在URL后面添加#号,不会引起页面重新加载只会更新浏览器地址栏中的URL
历史模式是直接修改浏览器中的URL所以要再服务端配合使用,返回同一个html文件,以避免在刷新或直接访问页面时出现404错误。
70.Vue中数据改变视图不更新有几种情况?如何解决?$set如何使用?
首先数据改变视图不更新有几种情况。
Vue2中:
用数组下标修改值时或新增对象Key值时,这样Vue的devserve函数是监听不到数据变化的,就会导致数据更新视图不变。
举例:
1.通过索引方式去修改data中数据时 array[10].name='你好'
2.当修改数组长度时 array.length = 10
$set如何使用?
当数据没有被双向绑定的时候,我们就需要使用$set来解决了他一共有三个参数,分别是目前属性,新增属性,新增的值。
this.$set(this.array[10],"name","hello")
71.重绘,回流是什么如何理解?
重绘就是在页面第一次绘制(渲染)完成后,重新绘制的过程。
回流就是在页面布局(视图)更新之后对元素大小,位置进行改变的过程。
重绘触发时机:修改网页内容样式,文字颜色,边框颜色,文本,回流一定触发重绘,但是重绘不一定触发回流。
回流触发时机:DOm结构发生改变,布局改变,窗口大小改变,内容变化,以及页面第一次渲染的时候。
72.高内聚低耦合
什么是高内聚?
高内聚是一种评判软件设计质量的标准,内聚更专业的说法就是功能内聚,是对系统中元素职责的相关性集中度的(量度),如果元素有高度的相关责任,除了这些责任没有其他工作,就说明这个元素有高内聚。()
举例:我是一个项目经理,我的职责是负责管理这个项目开发从0-100的进度,这期间我只负责安排任务,动手的都交给员工-技术,如果参与了开发过程我就不是一个高内聚元素,因为开发不是我的职责(简单说,做好自己分内的事,不去做其他事)
什么是低耦合?
耦合就是元素之间的关联度,感知依赖度如:模块,对象,功能之间关联。
举例:当我们在A元素调用B元素,B元素有问题或者不在的时候,A元素就不能正常工作,那么就说明A元素和B元素的耦合度较高这种耦合度可以称为100%。这都将影响元素A的正常工作,影响项目可维护性和易变更性。同时元素A只能运行在元素B中,这也大大的降低了A元素的可复用性。正因为耦合的种种弊端,我们才需要在软件设计上追求低耦合。
再简单的说: 高内聚、低耦合讲的是程序单位协作的问题, 你可以这样理解,一个企业的管理, 最理想的情况就是各个部门各司其职,井然有序,互不干涉, 但是需要沟通交流的时候呢, 各个部门都可以找到接口人专门负责部门沟通以及对外沟通。 在软件里呢, 就是说各个模块要智能明确, 一个功能尽量由一个模块实现, 同样,一个模块最好只实行一个功能。这个是所谓的“内聚”; 模块与模块之间、系统与系统之间的交互,是不可避免的, 但是我们要尽量减少由于交互引起的单个模块无法独立使用或者无法移植的情况发生, 尽可能多的单独提供接口用于对外操作, 这个就是所谓的“低耦合”。 但是实际的设计开发过程中,总会发生这样那样的问题与情况, 真正做到高内聚、低耦合是很难的,很多时候未必一定要这样, 更多的时候“最适合”的才是最好的, 不过,理解思想,审时度势地使用, 融会贯通,灵活运用,才是设计的王道。
Or
简单的理解高内聚低耦合:耦合和内聚的的评判标准是强度,耦合越弱越好,内聚越强越好。
总结一句简单通俗易懂的的话:
高内聚就是功能内聚越高越好,低耦合就是元素关联度越低越好。高内聚就是一个项目经理只安排别人做事自己不动手,如果自己动手内聚性就低了。低耦合就是元素与元素之间的关联度A依靠B执行,B不存在A就无法运行,这种就是低耦合。
73.键值对的理解
键值对(“key = value”),顾名思义,每一个键会对应一个值。
键:就是存的值的编号
值:就是要存放的数据
键就是属性,值就是属性值,因为他们是成对出现所以叫键值对。
74.Vue3的组合式APi和V2选项api有什么不同吗?
Vue2采用选项类型APi,Vue3采用合成类型APi,合成型API相比选项型更加简便整洁。
75.首屏加载慢如何解决?
1.首先分析一下什么是首屏加载慢?
首屏时间值得就是用户输入网址地址浏览器开始响应,到页面首页内容渲染完成的时间,(这个渲染完成指的是页面屏幕视窗可视内容)
2.分析下加载慢的原因有哪些?
·网络异常延迟问题
·资源文件体积过大
·数据是否重复请求
·加载脚本是否堵塞
解决办法:
代码优化:合理使用v-if和v-show,使用定时器和回调函数记得销毁,避免意外的全局变量,适当的使用闭包尽力减少&避免内存泄露。
小程序解决方案:
减少网络请求:通过合并CSS和JS文件使图片压缩和CDN加速方式减少网络请求。
优化代码的逻辑,避免在渲染时复杂的计算或数据操作,可以提前在后台进行计算并将结果缓存起来,减少首屏渲染的计算量。
使用分包加载,将主业和分包分开,将一些不必要的模块延迟加载,从而减少首屏的加载时间
优化图片,使用图片懒加载预加载等方法优化图片加载提高用户体验。
76.为什么要使用Pinia,Pinia和Vuex有什么区别?
Vue2和Vue3都可以使用Pinia,Pinia中只有state,getter,action,抛弃了Vuex中的mutations,pinia中action支持同步和异步,Vuex中active不支持。Pinia可以结合TypeScript使用,毕竟Vue3都推荐使用Ts来编写,这时使用pinia就非常合适了。
无需再创建各个模块嵌套,Vuex中数据过多我们使用模块来管理,略显麻烦,而Pinia中每个store都是独立的,体积非常小,只有1kb左右,Pinia支持插件来扩展自身功能,支持服务端渲染。
Or
简单说
Vue2和Vue3都可以使用Pinia可以让使用Vue2的人快速上手Pinia,Pinia中只有state,getter,action抛弃了Vuex中的mutations,Pinia中action支持同步和异步,Pinia可以结合TypeScript将类型重写,不用嵌套何种模块因为使用Vuex模块化也是有点略显麻烦的,所以Pinia中每个store都是独立的,体积仅1kb比Vuex更加灵敏便捷。
77.如何实现数组扁平化
arr.toString().split(",").map(Number)
将数组扁平化,最终得到不重复的数组
Array.from(new Set(arr.flat(Infinity)))
将数组扁平化,最终得到一个升序且不重复的数组
Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{ return a-b})
JavaScript原生基础
1.JavaScript中怎么去判断两个对象是否相等?
1. 通过全等方式
2.Object.is(对象1,对象2) 判断两个值是否为同一个值,如果相等会返回true吗?不会因为它是储存在栈里面的他们之间的引用地址不同所以就是false
3.递归方式↓
function isEqual(obj1, obj2) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
for (let key of keys1) {
// console.log(key,'key');
const val1 = obj1[key];
console.log(val1,'val1');
const val2 = obj2[key];
const areObjects = isObject(val1) && isObject(val2);
if (areObjects && !isEqual(val1, val2) || !areObjects && val1 !== val2) {
return false;
}
}
return true;
}
function isObject(obj) {
return obj != null && typeof obj === 'object';
}
const obj1 = { a: 1, b: { c: 3 } };
const obj2 = { a: 1, b: { c: 2 } };
console.log(isEqual(obj1, obj2)); // true
const obj3 = { a: 1, b: { c: 2 } };
const obj4 = { a: 1, b: { c: 3 } };
console.log(isEqual(obj3, obj4)); // false
4.使用第三方插件Lodash库的isEqual方法
5.Jquery库的$extend方法
3.bind,call,apply的使用方法,如何修改this指向
这三个方法都可以修改this指向
在使用bind方法时,本身不会执行函数,会返回一个新的修改this指向后的函数。需要调用才能执行。传参方式和call相同,
在使用call方法时,本身会立即执行这个函数。第一个参数为修改的this指向,后面的参数为传入给函数的参数。
在使用apply时,他的作用和call相同,修改this指向立即执行函数,区别就是传参不同,接受两个参数,第一个参数是要指向的this对象,第二个是数组,会被展开传入函数中作为参数。
fn.bind(obj1, '设计师', '画画')();
fn.call(thisArg, arg1, arg2, arg3, ...)
fn.apply(obj1, ['设计师', '画画'])
5.Vue中父组件的生命周期先加载还是子组件的生命周期先加载?
挂载阶段
父beforeCreate -----> 父created -----> 父beforeMount ----> 子beforeCreate ----> 子created ---->
子beforeMount ----> 子mounted ----> 父mounted
更新阶段
父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated
销毁阶段
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed
规律就是:父组件肯定要等子组件加载完它才能完,所以开始阶段肯定是父组件先加载先开始执行,然后等到子组件执行完,父组件收尾。
所以是子组件加载完成父组件才能加载完成。
Vue2生命周期API 描述
beforeCreate 实例创建前(dom没生成,数据也拿不到)
created 实例创建后(dom没生成,数据可以拿到)
beforeMount DOM挂载前调用(dom没生成,数据可以拿到)
mounted DOM挂载完成调用(dom已生成,数据可以拿到)
beforeUpdate 数据更新之前被调用
updated 数据更新之后被调用
beforeDestroy 组件销毁前调用
destroyed 组件销毁完成调用
6.宏任务微任务执行顺序,同步任务异步任务的执行顺序
由于JavaSCript是单线程语言,在同一个时间内只能做一件事,这就导致后面的任务需要等到前面任务完成才能执行,如果前面任务比较耗时就会导致后面任务一直等待所以JS就出现了同步任务和异步任务。
同步任务就是不耗时的无论是同步任务还是异步任务他都是同时执行的按顺序进行执行,,异步任务只是不等待执行的结果而已并不是遇到异步任务就不执行了,同步任务没有优先级之分,异步任务有,先执行微任务再执行宏任务,同级别的按顺序执行。
8.APi不同的区别
Vue3 的 Composition API 就是组合式api。 亢pu-C神
组合式api 就是一个功能所定义的 api 会放在一起,这样子即使项目变大,功能增大,我们能够很快找到功能相关的所有api,不像 Options API 功能分散,需要改动时,需要多处查找过程比较困难。
项目-实现
1.小程序中怎么识别登录后返回的信息去知道这是哪个用户?
通过login方法,返回openId 该服务商唯一用户标识,通过这个标识去处理,获取到在系统中的这个用户。
2.GET和POST的区别
get用来获取数据,post用来提交数据
get参数有长度限制最长2018字节,post无限制
get请求的数据会附加在url
后面以?分割,多个参数以&分割,而post请求会把数据放在http请求体中。
get请求会保存在浏览器历史中,或者web服务器的日志中。
什么是乐观锁,什么是悲观锁?
1.乐观锁
首先来看乐观锁,顾名思义,乐观锁就是持比较乐观态度的锁。就是在操作数据时非常乐观,认为别的线程不会同时修改数据,所以不会上锁,但是在更新的时候会判断在此期间别的线程有没有更新过这个数据。
2.悲观锁
反之,悲观锁就是持悲观态度的锁。就在操作数据时比较悲观,每次去拿数据的时候认为别的线程也会同时修改数据,所以每次在拿数据的时候都会上锁,这样别的线程想拿到这个数据就会阻塞直到它拿到锁。
怎么通过代码去设置让浏览器不缓存页面
防止浏览器缓存的方法:
添加版本号或时间戳
可以在文件名后面添加版本号或时间戳,例如:
<script src="script.js?v=1.0"></script>
或者Or
<link rel="stylesheet" href="style.css?t=1625689241">
CSS样式性能优化
二、具体优化方案
2.1、加载性能
1、css压缩:将写好的css进行打包,可以减少很多的体积。
2、css单一样式:在需要下边距和左边距的时候,很多时候选择:margin:top 0 bottom 0,但是margin-bottom:bot tom;margin-left:left;执行效率更高。
3、减少@import,而建议使用link,因为后者在页面加载时一起加载,前者是等待页面加载完成之后再进行加载。
2.2、选择器性能
1、关键选择器:选择器的最后面的部分为关键选择器。css选择器是从右向左进行匹配的。当使用后代选择器的时候,浏览器会遍历所有子元素来确定是否是指定的元素等等。
2、如果规则拥有ID选择器作为其关键选择器,则不要为规则增加标签。过滤掉无关的规则。
3、避免使用通配符规则,如果*{},计算次数惊人,只对需要用到的元素进行选择。
4、尽量少的区队标签进行选择,而使用class。
5、了解哪些属性是可以通过继承而来的,然后避免对这些属性重复指定规则。
2.3、渲染性能
1、慎重使用高性能属性:浮动,定位。
2、尽量减少页面的重排和重绘。
3、去除控规则,{}。空规则的产生的原因一般来说是为了预留样式。去除这些空规则则无疑能减少css文档体积。
4、属性值为0时,不加单位。
5、属性值为浮动小数0.***,可以省略小数点之前的0。
6、标准化各种浏览器前缀,带浏览器前缀的在前。标准属性在后。
7、不使用@import前缀,它会影响css的加载速度。
8、选择器优先嵌套,尽量避免层级过深。
9、css雪碧图:同一页面相近部分的小图标,方便使用,减少页面的请求次数,但是同时图片本身不变大,使用时,优劣考虑清楚使用。
10、正确使用display的属性,由于display的作用,某一些样式组合会无效,徒增样式体积的同时也影响性能。
白屏现象有哪些怎么解决?
页面资源加载堵塞,路径错误两种情况,前者优化资源后者修改路径。
渲染阻塞的原因
可能是因为CSS加载出现阻塞,然后又因为CSS在headb标签内,导致只有加载完CSS,才能显示内容,然而CSS出于某种原因加载出现阻塞,导致后面的内容无法渲染,从而使整个页面变为白屏。
也有可能是JS加载出现阻塞,从而导致页面无法解析。最后导致整个页面变为白屏。
优化办法
优化的最佳办法,那肯定直接优化CSS,JS体积,从而从根本上解决加载缓慢,加载阻塞的问题
除此之外,讨巧的办法就是将大体积的CSS和JS放入到body最尾部,然后将少量用于定位等基本样式的CSS放入头部,保证页面会先将页面基本样式和元素加载出来,然后加载JS的Script标签还可以加入async,defer属性,使JS的加载变为异步加载,这样JS的加载就不会阻塞页面解析了
nuxt的了解
1、模块化
Nuxt 基于一个强大的模块化架构。你可以从 50 多个模块中进行选择,让你的开发变得更快、更简单。支持 PWA 、添加谷歌分析到你的网页或生成网站地图,这些功能都无需重新发明轮子来获得。
2、高性能
Nuxt.js 默认会优化你的应用程序,尽可能地利用 Vue.js 和 Node.js 的最佳实践来构建高性能的应用程序。Nuxt 帮你把所有不需要的比特都从你的应用程序中剔除,并且还包含了一组分析器,以便更好地优化你的应用程序。
总结:快速 简单、约定式开发
nuxt 做什么类型的项目
1、需要做SEO优化的
2、工期着急的项目(nuxt很多的配置都已经集成好了,不需要你再去配置,例如 自动导入路由 组件等等)
3、需要服务器渲染的项目
ssr服务做缓存的意义
如果未使用缓存,就会导致每一个用户的对页面的请求,都使用服务去渲染一次,这对于服务器简直是灾难。特别是渲染所依赖的node.js服务,不论是express还是koa又或者是像nuxt的封装,都绕不开渲染时对于服务器cpu产生压力。反之,使用缓存,用内存空间换取cpu的使用率这是划算的,且属于node.js的长项。