前端技术知识(含八股)总结 - 持续更新中
- 参考文献
- 1.HTML和CSS
- 1.1 语义化标签
- 1.2 CSS 选择器及优先级 / position 定位 / box-sizing 属性 / transition / 继承属性(如字体文字类的属性大部分有继承)/ 行内元素和块级元素 / html的dom事件
- 1.3 BFC
- 1.4 元素水平垂直居中
- 1.4 隐藏页面中某个元素
- 1.5 页面布局方式
- 1.6 伪类、伪元素
- 1.7 css预处理器
- 1.8 href和src
- 1.9 < img > 的 title 和 alt 有什么区别
- 1.10 像素
- 1.11 视口
- 1.12 移动端像素
- 2.JS(含ES6)、TS
- 2.1 JS 中的 8 种数据类型及区别
- 2.2 var / let(ES6) / const(ES6)
- 2.3 JS异步问题处理
- 2.3.1.回调函数
- 2.3.2.Promise
- 2.3.3.async/await(Generator语法糖)
- 2.4 this
- 2.5 JS单线程 / 异步/ EventLoop 事件循环 / 微任务和宏任务
- 2.6 防抖(debounce)节流(throttle)
- 2.7 闭包
- 2.8 页面滚动监听(上拉加载、懒加载)
- 2.9 原型与原型链
- 2.10 箭头函数 / for of for in / 数组操作等其他js常用语法(省略)
- 2.11 typescript
- 2.12 console
- 2.13 数组扁平化
- 2.14 深/潜拷贝
- 2.15 arr.map()、arr.reduce()、arr.forEach()
- 3.浏览器
- 3.1 从输入 URL 到页面加载的全过程
- 3.2 浏览器重绘与回流(涉及性能优化)
- 3.3 “缓存”(中文歧义)
- 3.3.1 storage(application的storage)
- 3.3.2 http缓存(network里看某个请求的Headers)
- 3.4 网页性能优化
- 3.5 跨域
- 3.6 前端路由
- 3.7 AJAX(Asynchronous JavaScript And XML)工作原理
- 3.8 H5新特性记录(新语义标签暂没记录)
- 4. 工程化 / webpack基础概念
- 4.1 webpack Core Concepts
- 4.2 vue项目目录结构
- 4.3 vue部署(Nginx部署)
- 5.软件开发模式(项目管理/软件产品管理)
- 6.业务开发场景方案总结
- 6.1 把一个word文档内容(分不同章节)展示在一个竖直大长页中,包含多个echarts/表格/页面数据、多个接口请求。除上拉滑动查看外,还可以大纲直接点击章节查看。如何实现并优化?
- 6.2
参考文献
力扣八股文
https://zhuanlan.zhihu.com/p/346468901
https://zhuanlan.zhihu.com/p/141134693
https://blog.csdn.net/sayUonly/article/details/117520021
https://blog.csdn.net/qq_28766729/article/details/102839161
https://zhuanlan.zhihu.com/p/413440875
https://zhuanlan.zhihu.com/p/91674680
https://www.zhihu.com/question/587456887?utm_id=0
https://zhuanlan.zhihu.com/p/390394730
https://it.cha138.com/nginx/show-467347.html
1.HTML和CSS
其他前端相关内容见
CSS基础学习总结
HTML基础学习总结
js基础学习总结
Vue基础学习总结
1.1 语义化标签
H5新特性,相对于全部div,结构清晰,利于搜索引擎优化
1.2 CSS 选择器及优先级 / position 定位 / box-sizing 属性 / transition / 继承属性(如字体文字类的属性大部分有继承)/ 行内元素和块级元素 / html的dom事件
- !important >行内样式> ID 选择器「如:#header」> 类选择器「如:.foo」> 标签选择器「如:h1」
- html dom 的 event 事件,如onfocus和onchange等,和elementui组件的事件名一样。
其他内容见CSS基础学习总结
1.3 BFC
- BFC(Block Formatting Contexts,块级格式化上下文), 是W3C CSS2.1规范中的一个概念。加了BFC特性的容器,可以认为是独立渲染规则容器,决定了子元素的布局和与其他元素的关系。即,把 BFC 理解成一块独立的渲染区域,BFC 看成是元素的一种属性。
- 给block实现BFC属性,有很多方式,最常用的是overflow:hidden
- 使用场景:1.清除浮动(让父元素的高度包含子浮动元素,直接加clear:both也能清除浮动,但不如BFC好),即解决高度塌陷。2.去除margin重叠。3.避免某元素被浮动元素覆盖。
1.4 元素水平垂直居中
1.绝对定位(子绝父相)
div {// 父position: relative;
}
div {position: absolute;left: 50%;top: 50%;transform: translate(-50%,-50%);
}
2.绝对定位:确定了当前 div 的宽度,margin 值为当前 div 宽度一半的负值。
3.绝对定位:绝对定位下 top left right bottom 都设置0 ,margin 设置为 auto
4.flex布局:
display: flex;
align-items: center; //项目在竖轴的对齐方式
justify-content: center; //主轴上的对齐方式
5.table-cell 实现水平垂直居中:table-cell middle center 组合使用
6.绝对定位:calc() 函数动态计算实现水平垂直居中
1.4 隐藏页面中某个元素
opacity:0; 继续占据空间,内容不可见。如果该元素已经绑定事件,点击也能触发点击事件。
visibility:hidden; 继续占据空间,内容不可见 ;但是不会触发该元素已经绑定的事件
display:none ; 不占据任何空间(v-show)
1.5 页面布局方式
1.flex布局(弹性布局)
2.rem布局(移动端)
3.百分比布局(用的少)
4.浮动布局(用的少)
1.6 伪类、伪元素
伪类在dom树,伪元素不在。
其他内容见CSS基础学习总结
1.7 css预处理器
- CSS 预处理器是一种专门的编程语言,用来为 CSS 增加一些编程特性(CSS 本身不是编程语言)。 不需要考虑浏览器兼容问题,因为 CSS 预处理器最终编译和输出的仍是标准的 CSS 样式。
- 可以在 CSS 预处理器中:使用变量、简单逻辑判断、函数等基本编程技巧。
- 关于 CSS 预处理器:sass、less、stylus
1.8 href和src
href,表示超文本引用。用来建立当前元素和文档之间的链接。src 指向的内容会嵌入(下载)到文档中当前标签所在的位置(src 用于替换当前元素)。
1.9 < img > 的 title 和 alt 有什么区别
title: 鼠标滑动到元素上的时候显示
alt: 图片无法加载时显示
1.10 像素
- 物理像素(physical pixel,也称设备像素dp,device pixel),手机高清屏
- css像素(逻辑像素,logical pix,也称设备独立像素)
- 设备像素比(dpr = 物理像素/css像素),标清dpr=1,高清dpr>1(dpr=2代表1x1个css像素可以用2x2的设备像素绘制)
- 缩放:改变的是css像素的大小
- PPI:pixels per inch,每英寸的物理像素点
1.11 视口
- pc端没有该概念,移动端提出用,视口本身可以进行缩放。
- document.documentElement.clientWidth,拿到视口宽。(不缩放的话,默认拿到屏幕宽)
1.12 移动端像素
(在pc调移动端时,由于浏览器内核限制,可能导致某些像素无法显示,但到移动端就好了)
- px/%:常见。
- em:元素的字体大小,font size of the element。1em等于字体大小,如设置font-size = 12px,则5em代表60px。缩进两字符时好用。
- rem(移动端多用该单位,可以做页面适配):font size of the root element。root指html根元素。设置HTML根的font-size比如等于12px(代表在标准375视口下想要的标准font-size为12px,这个标准是人定的,你可以选择750),然后整个页面用rem单位的元素都会根据该font-size来变化,此时如果该font-size的px用,(视口宽度/标准案例视口宽度(如写死375))*标准想要的px像素(如12px),都会以标准案例视口宽度为准进行缩放。
window.onresize里执行计算代码 - vh/vw:视口像素,适配好用。
2.JS(含ES6)、TS
其他内容见
js基础学习总结
2.1 JS 中的 8 种数据类型及区别
- Number
- String
- Boolean
- undefined:js特有,变量声明过但并未赋过值。你可以认为undefined是表示系统级的、出乎意料的或类似错误的值的空缺。
- null:它是一个空对象指针,可以用java理解。是表示程序级的、正常的或在意料之中的值的空缺
- Symbol:ES6 中新定义,符号类型是唯一的并且不可修改。Symbol 指的是独一无二的值。存储关键数据或者服务器数据,且可以唯一属性名。
let a = Symbol("11");let b = Symbol("11");console.log(a==b); // falseconsole.log(a===b); // falseconsole.log(a.description === b.description); // true
判空代码
// 普通判空
if (obj === undefined || obj === null || obj === '') {
}
等价于
if(!obj)// 对象判空
if(JSON.stringify(obj) === '{}') {
}// 数组判空
if(JSON.stringify(obj) === '[]') {
}
2.2 var / let(ES6) / const(ES6)
- var:1.函数级作用域;2.变量提升(声明提升,赋值不提升);3.可重复声明且赋值;4.全局作用域中声明的变量会被挂载到全局对象的window中
- let:1.块级作用域;2.没有变量提升,所以必须先声明后使用;3.同一作用域下不能重复声明;4.全局作用域中使用let声明的变量不会挂载到window对象中
- const:1.const声明常量必须赋初始值;2.const声明的常量不能更改(原始数据类型肯定不能改,引用数据类型其实也不能改,但这里不能改的是引用的地址,地址里的值/属性能改);3.其他和let一样
- 隐式定义和显式定义:隐式直接给变量赋值,无关键字,是全局的;显式用关键字定义变量,如上面那三。
2.3 JS异步问题处理
2.3.1.回调函数
一个函数A,作为另一个函数B的参数,那么函数A就被称为回调函数。回调函数A就是一个普普通通的函数,它被其他函数B作为参数在B的内部调用,那么在这个时候A才能被称为B的回调函数**。回调函数这个概念是相互的,一个单独的函数是无法叫做回调函数的**,它只能被称为XXX(被谁在内部调用)的回调函数。
ES6出现之前,这种代码可以说是随处可见。它虽然解决了异步执行的问题,可随之而来的是我们常听说的回调地狱问题:没有顺序可言:嵌套函数执行带来的是调试困难,不利于维护与阅读;耦合性太强:一旦某一个嵌套层级有改动,就会影响整个回调的执行
2.3.2.Promise
ES6异步编程的一种解决方案,比传统的方案(回调函数和事件)更加的合理和强大,可以解决回调地狱问题。
- 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、resolved(已成功)和rejected(已失败)
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为resolved和从pending变为rejected
- promise内部发生错误,不会影响到外部程序的执行。
- promise的.then
案例1:
let promise = new Promise((resolve, reject) => {// do somethingif (true) {// 将参数返回,供then方法使用resolve("value");} else {// 将参数返回,供then方法使用reject("error");}
});
// Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
promise.then(value => {// resolved时调用,value为resolve函数返回的参数console.log(value);},err => {// rejected时调用,err为reject函数返回的参数console.log(err);}
);
// 当then方法只有一个函数参数时,此时为resolved状态的回调方法
promise.then(value => {// 只有状态为resolved时才能调用,如果返回的是rejected状态,则报错 Uncaught (in promise) errorconsole.log(value);});
案例2:
// 从 买笔 -> 写作业 -> 交作业 三个异步状态,都需要依赖上一步的结果才能执行
// 如果单纯在 ajax 异步回调里又做异步,就会形成回调地狱,看看 promise 是如何解决回调地狱的问题// 买笔
function buy(){console.log("开始买笔");return new Promise( (resolve,reject) => {$.ajax({url: 'xxx.com',data: {name:'krry'},success: res => {console.log('买了笔芯');resolve(res); // 成功},error: (err) => {reject(err); // 失败}});});
}// 写作业
function work(data){console.log("开始写作业:" + data);return new Promise( (resolve,reject) => {$.ajax({url: 'xxx.com',data: {name:'krry'},success: res => {console.log('写完搞定');resolve(res); // 成功},error: (err) => {reject(err); // 失败}});});
}// 交作业
function out(data){console.log("开始上交:" + data);return new Promise( (resolve,reject) => {$.ajax({url: 'xxx.com',data: {name:'krry'},success: res => {console.log('上交完成');resolve(res); // 成功},error: (err) => {reject(err); // 失败}});});
}// 调用异步的时候,如此简单,优雅地解决了回调地狱的问题
// 调用每一个方法的时候自动将参数放进去了
// 这里调用的是成功的回调
buy().then(work).then(out).then( data => {console.log(data);
});// 上面的写法等同于这种写法:还是没有上面的简洁,推荐上面写法
buy().then(res => work(res)).then(res => out(res)).then( data => {console.log(data);
});// 考虑失败的回调
buy().then( work, err => {console.log('买笔失败啦' + err);
}).then( out, err => {console.log('作业太难,写不了')
}).then( data => {console.log(data);
});
案例3:体现promise异步(顺便体现setTimeOut)
setTimeout(() => {console.log(7) // 宏任务
}, 0)
new Promise((resolve, reject) => {console.log(3); // 主线程resolve();console.log(4); // 主线程
}).then(() => {console.log(6) // 回调(微任务)
})
console.log(5) // 主线程// 执行结果3,4,5,6,7
- Promise的catch()和then(…,err)的优先级
2.3.3.async/await(Generator语法糖)
1.async为异步标识,标识在该函数内可以使用await
2.async返回的是promise,await可以阻塞,并解promise的result
2.4 this
- this考虑运行环境的上下文,尤其是函数。当就是个普通函数在script里运行,this是window。当在对象(构造函数)里运行,this是该对象。
- vue中不用太考虑,this为vue对象
- call,apply,bind三个方法:改变函数执行时的上下文,简而言之就是改变函数运行时的this指向
2.5 JS单线程 / 异步/ EventLoop 事件循环 / 微任务和宏任务
-
javascript是一门单线程语言:单线程的特性,与它的用途有关,作为浏览器脚本语言,JavaScript的主要用途是互动和操作DOM。为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM(故HTML5提出Web Worker标准后,我理解JS的单线程应该叫DOM操作单线程)。所以,这个新标准并没有改变JavaScript单线程的本质。
-
Event Loop是javascript的执行机制:图中,主线程运行的时候,产生堆和栈,栈中的代码调用各种外部API,异步操作执行完成后,就在消息队列中排队。只要栈中的代码执行完毕,主线程就会去读取消息队列,依次执行那些异步任务所对应的回调函数。
同一次事件循环中,微任务永远在宏任务之前执行。
宏任务macrotask: script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
微任务microtask: process.nextTick, Promise, MutationObserver
- 消息队列(任务队列)
其他线程执行完后,会把回调扔到消息队列等待。(例如定时器触发线程在计时结束后会把回调扔到消息队列)。
消息队列有
- 浏览器
浏览器的架构是多进程的,不同的浏览器采用不同的进程架构,这个没有统一的标准,以谷歌浏览器为例,他主要有四个进程,分别是顶层的Browser process,负责标签页网页呈现的Renderer Process,负责控制网页插件的Plugin Process和负责处理GPU的GPU Process
2.6 防抖(debounce)节流(throttle)
1.防抖:只执行最后一次。n 秒内函数只会执行一次,若在 n 秒内被重复触发,则重新计时。
常见场景:下拉框模糊搜索、手机号/邮箱格式的输入验证检测、登录等按钮避免用户快速点击产生两笔交易(两次请求)…
function debounce(fn, delayTime) {let timer = null;return function() {if (timer !== null) { // 这个if不写也行,===null了相当于清了clearTimeout(timer) // 清除掉定时任务}let context = thislet args = argumentstimer = setTimeout(() => {fn.apply(context, args)timer = null}, delayTime)}
}
2.节流。一次次间隔执行。n 秒内只运行一次,若在 n 秒内重复触发,只执行一次。
常见场景:下拉框模糊搜索、监听滚动事件(懒加载)…
// fn为回掉业务逻辑,delayTime为延迟时间
function throttle(fn, delayTime) {let time = null // 闭包产生的私有属性,产生私有数据// let usedFlag = 1 // usedFlag用来测试当前节流是否生效return function() { // fun() 套一个 return fun()闭包写法if(time !== null) { return } // n 秒内只运行一次// console.log('usedFlag', usedFlag)let context = this // 获取上下文(看似不体现作用)let args = arguments // 传参// fn.apply(context, args) // 写在外面运行是(业务->[间隔]->业务)// usedFlag = usedFlag + 1time = setTimeout(() = > {fn.apply(context, args) // 写在里面运行是([间隔]->业务->[间隔])time = null // 到时间清空定时器,关键操作}, delayTime) // 延迟时间设置}
}
- vue或uniapp框架中使用节流函数,和直接js里使用有区别。当在vue或uniapp框架中使用节流函数时,要用eventFunction(): throttle(function(){// 业务代码}, 100),不能用eventFunction() {throttle}这种。
2.7 闭包
- 闭包:函数 和 函数体内可访问的变量总和,把闭包看作是密闭容器。
- 在一个函数内部创建另一个函数,内层函数中访问到其外层函数的变量,就会形成闭包。由于闭包是内层函数引用了外层函数的变量,所以在调用完外层函数,外层函数中的变量也不会被垃圾回收,而内部函数在包含它们的外部函数之外被调用时,外层函数的变量就不会被释放。不同fn的不同闭包调用,会产生不同的私有变量。
- js存在大量事件驱动,闭包可以保存/保护。然而,会导致函数的变量一直保存在内存中,过多的闭包可能会导致内存泄漏。
2.8 页面滚动监听(上拉加载、懒加载)
window.addEventListener('scroll', this.handleScroll)
handleScroll: throttle(function () {// 全部有浏览器内核适配问题// 网页被卷起来的高度(即浏览器滚动条滚动后隐藏的页面内容高度),初始值是0,它是一个变化的值document.documentElement.scrollTop// 视口高度document.documentElement.clientHeight// 页面不能滚动时是不存在的,body长度超过window时才会出现,所表示body所有元素的长度document.documentElement.scrollHeight// 某一dom元素的高度document.getElementById('idXXX').offsetTop// 触底公式if(scrollTop + clientHeight >= scrollHeight) {// 触底}
}, 1000)
2.9 原型与原型链
JS的继承思想设计(模仿java子类继承父类共有),产生原型与原型链。
- 构造函数生成的所有实例对象都能够共享属性,那么我们就给构造函数加一个属性叫做prototype(js给构造函数加的),用来指向原型对象,我们把所有实例对象共享的属性和方法都放在这个构造函数的prototype属性指向的原型对象中,不需要共享的属性和方法放在构造函数中。
- 每个对象(对象即构造函数的实例化),都会有一个内置属性叫做_proto_,而且这个属性是系统自动生成的,只要你创建一个对象,这个对象就有这个属性。这个属性_proto_指向的是原型对象。
- 小总结:构造函数的prototype属性和它实例化的对象的_proto_均指向原型对象(我认为是java中的父类)
- 所有的 JS 对象的都是继承了Object对象。Object构造函数的原型是本身,所以把_proto_指向了null。
- 最后,原型链就是实例对象和原型对象之间的链接。
其他见js基础学习总结
2.10 箭头函数 / for of for in / 数组操作等其他js常用语法(省略)
- 普通函数中的 this 是动态的。而箭头函数中的 this 指向的是包裹箭头函数的那个对象,并且不改变。(箭头函数没this)
- for of 数组(js中用for in list出来的不是数组中的每个数)
- for in 对象
2.11 typescript
比js更像java,包括class、注解符号、private等等
2.12 console
- console.log()可以直接正常打印基本类型
- console.log()打印对象会出现不符合预期的问题,如果console.log()输出一个对象或数组,那么它实际上输出的是该对象或数组的引用。当引用中的值改变了,在控制台也会随即改变,console.log显示就会有出入。
解决方案:确保始终记录对象的序列化快照 字符串显示(JSON.stringify),如console.log(JSON.stringify(d));
2.13 数组扁平化
1.递归
2.ES6 的 flat 方法
3.JSON.stringify()转成字符串,用正则替换掉括号,再用JSON.parse()转回数据
2.14 深/潜拷贝
堆栈,和java一样
深拷贝JSON.parse(JSON.stringify())
2.15 arr.map()、arr.reduce()、arr.forEach()
arr.map()返回的是数组(给数组做处理)
arr.reduce()返回的是一个数(累加)
arr.forEach()遍历数组,所以想做操作得外面建个变量接它
3.浏览器
3.1 从输入 URL 到页面加载的全过程
细节见计算机网络基础复习总结、2022秋招面经总结(补充前面文章中不含的内容)计算机网络部分
-
DNS解析得到IP地址(网络层IP)
-
建立TCP连接(传输层,三次握手)
-
发送HTTP请求(应用层协议,传输层的协议TCP或UDP加上端口就可以标识一个应用层协议;常见POST/GET)(涉及HTTP缓存)
HTTP报文是包裹在TCP报文中发送的,服务器端收到TCP报文时会解包提取出HTTP报文。体现请求响应7层模型从顶到底加协议再从底到顶解封。 -
服务器处理请求,然后返回HTTP报文。
请求行、请求头、请求报文 => http请求报文
状态码、响应头、响应报文 = > http响应报文 -
浏览器接收到响应后,显示渲染页面
HTML是一种超文本标记性语言,HTML在经过浏览器编译以后在内存是以一种树形结构存在着,这个树也被称为DOM树(document object model)。将HTML或XML文档转化为DOM树的过程称为解析(parse)。DOM树叫文档对象模型。
-
客户端和服务器通过四次挥手终止 TCP 连接。
3.2 浏览器重绘与回流(涉及性能优化)
Reflow:当 DOM 的变化影响了元素的几何信息,浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置。表现为重新生成布局,重新排列元素。
Repaint: 当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程。表现为某些元素的外观被改变。
3.3 “缓存”(中文歧义)
3.3.1 storage(application的storage)
- cookie:保存信息在客户端(场景:登录token)。服务器发送到用户浏览器并保存在本地的一小块数据,浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。(cookie 的同源策略:cookie同源策略。ajax 需要完全同源,而 cookie 只需要同一父级域名。)
- session:保存信息在服务端(场景:登录信息)。session 是基于 cookie 的一种方案,sessionID存在cookie里。session 是基于cookie实现的一种数据存储方式。
- localStorage:HTML5提供的一个API,实质是一个hash。(场景:免登录)不会因为刷新而释放,可以使用localStorage来实现变量的持久化存储。localStorage 理论上永久有效,除非用户清理缓存。(只有相同域名的页面才能互相读取 localStorage,同源策略与 cookie 一致)。浏览器关闭后数据不丢失除非主动删除数据
- sessionStorage:所有性质基本上与 localStorage 一致,有效期是页面会话持续,如果页面会话(session)结束(关闭页面),sessionStorage 就会消失。而 localStorage 则会一直存在。
3.3.2 http缓存(network里看某个请求的Headers)
谷歌浏览器开发者工具的network的Disable cache,勾选时会禁用浏览器缓存。这里的缓存是指http缓存,而不是cookie、storage。浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识。
- 强缓存(场景:大量静态资源的网页):在缓存查找该请求结果,决定是否使用该缓存结果。
不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求(跟第一次发起请求一致);存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存;存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果。
Cache-Control 和 Expires(HTTP/1)。network里找请求看,当浏览器对某个资源的请求命中了强缓存时,返回的http状态为200,在chrome的开发者工具的network里面size会显示为from cache
- 协商缓存:强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存。
协商缓存生效,返回 304;协商缓存失效,返回 200 和请求结果结果
Last-Modified,If-Modified-Since。ETag、If-None-Match。
3.4 网页性能优化
静态资源下载、接口请求等看瀑布
纯js代码逻辑可以console.time(‘flag’)与console.timeEnd(‘flag’),这两个方法均使用一个参数,参数值可以为任何字符串,但是这两个方法所使用的参数字符串必须相同,才能正确地统计出开始时间与结束时间之间所经过的毫秒数。
- 1.懒加载(异步组件)
见5.1节 - 2.分包策略(webpack)
除了上述1外(上述1属于分包策略),optimization.splitChunk等webpack配置也可以做自己的分包策略。 - 3.节流、防抖
见2.6节、5.1节 - 4.gzip压缩
项目打包上线,若build后的包体积大,会导致首屏加载速度慢。Gzip就是能非常明显有效的解决这个问题。它的原理是把原js、css文件进行压缩,从而减小文件体积,加快首屏访问速度。
步骤:
1.npm i 安装依赖。
2.在vue.config.js或config/index.js&build/webpack.prod.conf.js写配置代码。
3.nginx服务端配置(http里面加,也可以在某个server里加)。
4.浏览器支持(一般浏览器都已支持.gz的资源文件,在http请求的Request Headers中能看到 Accept-Encoding:gzip) - 5.使用字体图标 iconfont 代替图片图标(总之就是减少静态资源大小)
icon网站:https://www.iconfont.cn/?spm=a313x.collections_index.i3.2.6ca33a81tsnd67 - 6.预加载(离线包)
- 7.webworker
Web Worker 是一项 HTML5 新特性,可以在 Web 页面中创建后台线程,从而可以让 JavaScript 在主线程运行的同时,在后台线程中执行耗时的操作。这使得 Web 应用程序可以更加流畅,而不会出现 UI 卡顿或其他性能问题。Web Worker 是一种浏览器提供的 JavaScript API。
解决纯js计算数据逻辑不阻塞页面渲染/交互,使js拥有多线程能力
3.5 跨域
3.6 前端路由
-
单页面应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML 页面(如vue打包后dist里只有一个index.html)并在用户与应用程序交互时动态更新该页面的Web应用程序。
-
构建 SPA,需要引入前端路由系统(如vue中的Vue-Router)。前端路由的核心在于改变视图的同时不会向后端发出请求。
hash模式路由(vue-router 默认使用 hash 模式):
- 通过监听浏览器 window.onhashchange 事件变化,查找对应路由应用。通过改变 location.hash 改变页面路由。特点是地址栏URL中的#符号(http://www.baidu.com/#/test, hash的值为#/test)。hash后边变,不发服务器。
- 改成#/78hjhhjhkhuu,即没有做到对路由的全覆盖, 也不会返回 404 错误。
- 监听 url 中 hash 的变化,然后渲染不同的内容,这种路由不向服务器发送请求,不需要服务端的支持
history模式路由:
- H5新特性,history Interface 中新增的 pushState() 和 replaceState() 方法,改变页面路径。特点是history模式没有#号,是个正常的url,符合url规范。(所以分享到第三方的页面需要用该模式)
- history模式下,前端的 URL 必须和实际向后端发起请求的URL一致, 如http://www.baidu.com/test/78hjhhjhkhuu。如果后端缺少对/test/78hjhhjhkhuu的路由处理,将返回 404 错误。(还有种情况,你点击到某一层,一点刷新,history下是真实请求,但服务器没这个资源,会404。即浏览器直接访问嵌套路由时,会报 404 问题)(Nginx配置当请求的URL匹配不到任何静态文件或目录时,将请求重定向到index.html文件,可解决该问题)
- 监听 url 中的路径变化,需要客户端和服务端共同的支持
3.7 AJAX(Asynchronous JavaScript And XML)工作原理
AJAX不是编程语言,而是一门提供网页局部刷新的技术。AJAX最大的优点是在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容。XML是一种古老的数据交互格式,目前多数情况下会使用JSON数据格式替换XML数据格式,所以AJAX可以看做是异步JavaScript和JSON形式。
js中:var xhr = new XMLHttpRequest();
作者:LeetCode
链接:https://leetcode.cn/leetbook/read/2023-ming-qi-qian-duan-mian-shi-kao-dian/wb1ig7/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
3.8 H5新特性记录(新语义标签暂没记录)
- canvas和SVG:canvas和SVG都是HTML5中的图形渲染技术,用于在网页中呈现动态或静态图形。canvas是基于位图的绘图技术,而SVG是基于矢量图形的绘图技术。canvas可以用纯js画图但放大缩小会失真,SVG放大缩小不失真。
- 地理定位:1.HTML5 Geolocation API(需授权):navigator.geolocation.getCurrentPosition(success, error, options)。2.接入第三方位置服务平台——百度地图、高德地图、腾讯地图(需注册开发者账号)
- websocket:WebSocket 可以在浏览器里使用;支持双向通信(全双工通讯的网络技术);服务端可以推数据给客户端。(引入ws)
- webworker:Web Worker 是一项 HTML5 新特性,可以在 Web 页面中创建后台线程,从而可以让 JavaScript 在主线程运行的同时,在后台线程中执行耗时的操作。这使得 Web 应用程序可以更加流畅,而不会出现 UI 卡顿或其他性能问题。
4. 工程化 / webpack基础概念
4.1 webpack Core Concepts
webpack网站
At its core, webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it internally builds a dependency graph from one or more entry points and then combines every module your project needs into one or more bundles, which are static assets to serve your content from.
- Entry:An entry point indicates which module webpack should use to begin building out its internal dependency graph.
入口,以哪个文件作为入口起点分析构建内部依赖图并进行打包 - Output:The output property tells webpack where to emit the bundles it creates and how to name these files.
打包后的资源bundles输出到哪里去,以及如何命名(如默认dist文件夹) - Loader:Out of the box, webpack only understands JavaScript and JSON files. Loaders allow webpack to process other types of files and convert them into valid modules that can be consumed by your application and added to the dependency graph.
处理非JavaScript语言的文件 - Plugins:While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables.
执行范围更广的任务,插件的范围包括从打包和压缩等。 - mode:By setting the mode parameter to either development, production or none, you can enable webpack’s built-in optimizations that correspond to each environment. The default value is production.
相应模式的配置。development和production。打包不一样。 - Browser Compatibility:Webpack supports all browsers that are ES5-compliant (IE8 and below are not supported).
IE8及以下不支持
4.2 vue项目目录结构
参考:
https://www.cnblogs.com/jacksplwxy/p/11495700.html
4.3 vue部署(Nginx部署)
- 在项目开发完成后,我们需要将该项目部署到服务器上,并且需要设置Nginx等web服务器来处理前端请求。
- Nginx 是一个轻量级、高性能的HTTP和反向代理web服务器。其主要关心的是 HTTP 协议层面的传输和访问控制,监听相应的地址和端口,对客户端的HTTP资源请求进行响应、转发或处理,但是一个 HTTP Server 能做的始终只是把服务器上的静态资源如实的通过 HTTP 协议传输给客户端。(后端关注Nginx的反向代理和负载均衡功能,前端关注Nginx的web服务器本质对HTTP资源请求进行响应、转发或处理)
- Nginx动静分离(之前只听说过反向代理、负载均衡,动静分离和这俩功能结合起来了):web服务器架构。静态资源请求本地(Nginx物理机),动态服务请求通过反向代理转发给其他后台服务器。
Vue应用程序中可能包含一些动态路由(Vue-Router)和接口请求(ajax、axios)等功能。这时,我们需要在Nginx中进行配置以解决这些请求。一般而言,我们会将接口请求转发到服务端进行处理(Nginx location配置),同时将动态路由交给前端进行处理(Nginx location、try_files配置)
参考(更详细):https://blog.csdn.net/qq_40772692/article/details/124988974
5.软件开发模式(项目管理/软件产品管理)
- 瀑布模型:布模型将软件生命周期划分为制定计划、需求分析、软件设计、程序编写、软件测试和运行维护等六个基本活动,并且规定了它们自上而下、相互衔接的固定次序,如同瀑布流水,逐级下落。软件开发的各项活动严格按照线性方式进行。(现)
- 敏捷软件开发:敏捷开发是一种以人为核心、迭代、循序渐进的开发方法。在敏捷开发中,软件项目的构建被切分成多个子项目,各个子项目的成果都经过测试,具备集成和可运行的特征。(曾)
- 其他模式不赘述
6.业务开发场景方案总结
前端一定要懂后端基础,某些业务逻辑落在哪一端做才可以讨论清楚
6.1 把一个word文档内容(分不同章节)展示在一个竖直大长页中,包含多个echarts/表格/页面数据、多个接口请求。除上拉滑动查看外,还可以大纲直接点击章节查看。如何实现并优化?
-
解决方案:章节锚点(定位) + 上拉滚动监听(优化按需渲染压力、按需发送请求压力)+ 节流(优化滚动监听频率)+ 异步组件懒加载(优化按需渲染压力、按需发送请求压力)+ 章节锚点flag数组(避免重复发送请求)
-
echarts / g2plot 画图:1.id重复画图问题。2.g2plot更新数据要调用更新数据的方法,echarts更新数据要重置配置里的data。3.实时更新数据用watch就行。
-
数据制作成展示结构(包括页面直接展示、表展示、柱状图、饼图、折线图展示,类似于仪表大盘实现):
大概:由于该需求特殊性,前端整理组织全部数据。故利用工厂设计模式整理数据。页面多个模块显示内容是调用不同接口得到数据,且包含列表、echarts、直接显示等多种展示方式,给每个某块设计一个独立的vue data属性,即独立的数据结构对象(其实有点typescript的感觉)。实时性可采用定时器发请求。
具体:.map方法数组筛选出数组、三个点…拆装箱、固定自定义数据结构。注意let temp = { a:[] }初始化列表。直接属性temp.b = 3可以,列表temp.a.push()必须初始化了a才行。 -
webworker:该需求js数据计算的量级不大,单次处理不到100条数据,所以没用webworker
6.2
后续将持续更新…