青训营前期笔记
青训营基础前期知识点汇总
如何写好Javascript
一个好的js代码需要遵守:
1、各司其职:即HTML负责网页结构 CSS负责元素样式 JS负责交互和行为
2、组件封装:组件是指Web页面上抽出来一个个包含模板HTML、样式CSS和功能JS的单元,好的组件应该具备封装性、正确性、扩展性、复用性。
3、过程抽象:用函数作为黑盒来编写和使用,这个过程称之为过程抽象
举例:通过一段js代码实现浅色和深色两种浏览模式
// 基本的html结构
<div class="content">
<header>
<h1>深夜食堂</h1>
<span id="modeBtn" style="font-size: 30px;">🌞</span>
</header>
<main>
<div class="pic">
<img width="500px" src="https://p2.ssl.qhimg.com/t0120cc20854dc91c1e.jpg">
</div>
<div class="description">
<p>
这是一间营业时间从午夜十二点到早上七点的特殊食堂。这里的老板,不太爱说话,却总叫人吃得热泪盈
眶。在这里,自卑的舞蹈演员偶遇隐退多年舞界前辈,前辈不惜讲述自己不堪回首的经历不断鼓舞年轻人,最终令其重拾自信;轻言绝交的闺蜜因为吃到共同喜爱的美食,回忆起从前的友谊,重归于好;乐观的绝症患者遇到同命相连的女孩,两人相爱并相互给予力量,陪伴彼此完美地走过了最后一程;一味追求事业成功的白领,在这里结交了真正暖心的朋友,发现真情比成功更有意义。食物、故事、真情,汇聚了整部剧的主题,教会人们坦然面对得失,对生活充满期许和热情。每一个故事背后都饱含深情,情节跌宕起伏,令人流连忘返 [6] 。
</p>
</div>
</main>
</div>
// 基本样式
<style>
.content {
width: 500px;
padding: 20px;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
// 版本一: 基本交互 采用在原生的DOM结构上修改样式 即在js中修改了css样式
<script>
const btn = document.getElementById('modeBtn')
const body = document.body
btn.addEventListener('click', (e) => {
// console.log(e);
if(e.target.innerHTML === '🌞'){
body.style.background = 'black';
body.style.color = 'white';
e.target.innerHTML = '🌜';
} else {
body.style.background = 'white';
body.style.color = 'black';
e.target.innerHTML = '🌞';
}
})
</script>
// 版本二 单独写出白天和晚上的样式 点击时修改body的类样式即可 这样就不用直接在js中修改css样式了
<script>
const btn = document.getElementById('modeBtn')
const body = document.body
btn.addEventListener('click', (e) => {
console.log(e);
if(body.className !== 'day'){
body.className = 'day'
} else {
body.className = 'night'
}
})
</script>
// css样式
.night {
background-color: black;
color: white;
}
.day {
background-color: #fff;
color: black;
}
// 在body标签上添加类名
<body class="day">
// 版本三 纯展示类交互寻求零js方案
/* 隐藏checkbox 只是利用它的check状态改变来关联符号的状态 */
#modeCheckBox {
display: none;
}
#modeCheckBox:checked + .content {
background-color: black;
color: white;
}
#modeBtn::after {
content: '🌞';
}
#modeCheckBox:checked + .content #modeBtn::after {
content: '🌜';
}
<body>
<input type="checkbox" id="modeCheckBox">
<div class="content">
<header>
<h1>深夜食堂</h1>
<label id="modeBtn" for="modeCheckBox" style="font-size: 30px;"></label>
</header>
<main>
<div class="pic">
<img width="500px" src="https://p2.ssl.qhimg.com/t0120cc20854dc91c1e.jpg">
</div>
<div class="description">
<p>
这是一间营业时间从午夜十二点到早上七点的特殊食堂。这里的老板,不太爱说话,却总叫人吃得热泪盈
眶。在这里,自卑的舞蹈演员偶遇隐退多年舞界前辈,前辈不惜讲述自己不堪回首的经历不断鼓舞年轻人,最终令其重拾自信;轻言绝交的闺蜜因为吃到共同喜爱的美食,回忆起从前的友谊,重归于好;乐观的绝症患者遇到同命相连的女孩,两人相爱并相互给予力量,陪伴彼此完美地走过了最后一程;一味追求事业成功的白领,在这里结交了真正暖心的朋友,发现真情比成功更有意义。食物、故事、真情,汇聚了整部剧的主题,教会人们坦然面对得失,对生活充满期许和热情。每一个故事背后都饱含深情,情节跌宕起伏,令人流连忘返 [6] 。
</p>
</div>
</main>
</div>
Web标准与前端开发
【青训营】- Web标准与前端开发 - 掘金 (juejin.cn)
前端应用的领域
Business:企业级应用,企业资源管理
Customer: 面向消费者,门户网站、电商平台
Developer: 面向开发者,提升开发者开发效率的平台、工具、框架
- web端
5大浏览器
- 服务器端
Nodejs Expressjs koa
- 移动端
安卓 苹果
终端和跨端
- 终端
Webpack Cli
Babel Cli
Vue Cli
React Cli
- 跨端
Electron
NW.js
http理解
现代浏览器的深入理解
Web标准
W3C Ecma WHATWG IETF
HTTP实用指南
【青训营】HTTP实用指南——基础篇 - 基本特点 - 协议分析 - 缓存 - HTTP2 - HTTPS - 掘金 (juejin.cn)
B站笔记
请求方法分类:
安全的请求:不会修改服务器的数据,也就是说这是一个对服务器只读操作的方法:GET、HEAD、OPTIONS
幂等的请求:同样的请求执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的。就是说,幂等方法不应该有副作用,POST方法不是幂等的。
强制缓存与协商缓存的区别:
强制缓存命中,则不需要给服务器发送请求,会返回请求状态码200
协商缓存会判断资源是否更新而决定是否使用缓存,客户端与服务器会发生一次通讯,如果命中协商缓存,则服务器返回304.
Cache-Control是HTTP1.1的规范,一般用max-age字段来表示相对时间,比如 Cache-Control:max-age=3600 代表资源的有效期是 3600 秒。并且返回头中的 Date 表示消息发送的时间,表示当前资源在 Date ~ Date +3600s 这段时间里都是有效的。
如果 Cache-Control与 Expires 同时存在的话, Cache-Control 的优先级高于 Expires 。
Last-Modified/If-Modified-Since 二者的值都是 GMT 格式的时间字符串,Last-Modified标记了文件最后的修改时间,然后在下一次请求时请求头带上If-Modified-Since,其值为本地保存的Last-Modified,告诉服务器我本地缓存最后的修改时间,服务器如果判断文件未修改,则命中协商缓存,返回304 Not Modified状态码,浏览器就不再请求资源,直接使用本底的缓存;如果文件修改,则返回资源内容,新的 Last-Modified 会在 response header 返回,并在下次请求之前更新本地缓存的 Last-Modified,下次请求时,If-Modified-Since会启用更新后的 Last-Modified。缺点是最小判断步长为1秒,无法判断1秒内的多次变化。
Etag/If-None-Match,对于每一个文件,服务器根据文件本身算出一个哈希值(一般来说是哈希结构)并通过 Etag字段返回给浏览器,然后下一次请求后请求头带上 If-None-Match 字段,服务器会通过比较两者是否一致来判定文件内容是否被改变。与 Last-Modified 不一样的是,当服务器返回 304 Not Modified 的响应时,由于在服务器上ETag 重新计算过,response header中还会把这个 ETag 返回,即使这个 ETag 跟之前的没有变化。缺点是计算Etag值有性能损耗。
RESTful API
架构特征
以资源为基础 :资源可以是一个图片、音乐、一个XML格式、HTML格式或者JSON格式等网络上的一个实体,除了一些二进制的资源外普通的文本资源更多以JSON为载体、面向用户的一组数据(通常从数据库中查询而得到)。
统一接口: 对资源的操作包括获取、创建、修改和删除,这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。换言而知,使用RESTful风格的接口但从接口上你可能只能定位其资源,但是无法知晓它具体进行了什么操作,需要具体了解其发生了什么操作动作要从其HTTP请求方法类型上进行判断。具体的HTTP方法和方法含义如下:
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供完整资源数据)。
- PATCH(UPDATE):在服务器更新资源(客户端提供需要修改的资源数据)。
- DELETE(DELETE):从服务器删除资源。
URI指向资源:URI = Universal Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。URI包括URL和URN,在这里更多时候可能代指URL(统一资源定位符)。RESTful是面向资源的,每种资源可能由一个或多个URI对应,但一个URI只指向一种资源。
无状态:服务器不能保存客户端的信息, 每一次从客户端发送的请求中,要包含所有必须的状态信息,会话信息由客户端保存, 服务器端根据这些状态信息来处理请求。 当客户端可以切换到一个新状态的时候发送请求信息, 当一个或者多个请求被发送之后, 客户端就处于一个状态变迁过程中。 每一个应用的状态描述可以被客户端用来初始化下一次的状态变迁。
设计规范
通常一个完整的URL组成由以下几个部分构成:
URI = scheme "://" host ":" port "/" path [ "?" query ][ "#" fragment ]
scheme: 指底层用的协议,如http、https、ftp
host: 服务器的IP地址或者域名
port: 端口,http默认为80端口
path: 访问资源的路径,就是各种web 框架中定义的route路由
query: 查询字符串,为发送给服务器的参数,在这里更多发送数据分页、排序等参数。
fragment: 锚点,定位到页面的资源
通常一个RESTful API的path组成如下:
/{version}/{resources}/{resource_id}
version:API版本号,有些版本号放置在头信息中也可以,通过控制版本号有利于应用迭代。
resources:资源,RESTful API推荐用小写英文单词的复数形式。
resource_id:资源的id,访问或操作该资源。
此外,有时可能增删改查无法满足业务要求,可以在URL末尾加上action,例如
/{version}/{resources}/{resource_id}/action
action就是对资源的操作。
- 不用大写字母,所有单词使用英文且小写。
- 连字符用中杠
"-"
而不用下杠"_"
- 正确使用
"/"
表示层级关系,URL的层级不要过深,并且越靠前的层级应该相对越稳定 - 结尾不要包含正斜杠分隔符
"/"
- URL中不出现动词,用请求方式表示动作
- 资源表示用复数不要用单数
- 不要使用文件扩展名
展示GET,POST,PUT,DELETE几种请求API的设计与含义分析。
GET /collection:从服务器查询资源的列表(数组)
GET /collection/resource:从服务器查询单个资源
POST /collection:在服务器创建新的资源
PUT /collection/resource:更新服务器资源
DELETE /collection/resource:从服务器删除资源
根据安全性和幂等性,解释如下
使用场景
静态资源
通过调试器中的网络->css等请求头内容可以得到一些静态资源的信息,为了更快的传输静态资源,优化用户体验,那么就涉及到了静态资源的部署方案:缓存+CDN(如果是第一次访问,本地没有缓存,那么就会把资源存放在CDN上,CDN是内容分发网络 content delivery network,通过用户就近性和服务器负载的判断,以一种极为高效的方式为用户的请求提供服务)+文件名hash(因为cache-control里面的缓存的时间写的是一年,如果在这期间进行了更新,为了能够返回最新值,加上了文件名hash,如果文件名有变化—版本名变化,导致hash有变化,就会返回最新的内容了,这一步一般是在webpack打包的时候进行配置)。
登录
业务场景:表单登录 扫码登录
技术方式:SSO
主要讲解表单登录的方式,这里头条页面登录完成之后查看请求头会发现是options的请求,是因为请求资源的url是跨域的。一般请求分为两类——简单请求,复杂请求,只有在复杂请求之前需要发送一次预请求OPTIONS,查看跨域是否允许
跨域解决方法 CORS 代理服务器 Iframe
http是一种无状态的请求,为什么下一次进入页面还能够记住登录状态呢?
1、鉴权方案
cookie+session
登录成功之后会发起登录提交请求POST,账户名密码+手机验证码等提交给server,如果信息是正确的,那么server会生成一个session并保存下来,同时会借由这次的response的set-cookie将session保存在相应的域名和地址下面,下一次访问时浏览器自动携带策略会帮我们把之前的set-cookie携带出来,server会根据携带的信息进行分析是否是该用户登录,然后返回对应的信息。
2、JWT
JSON web token
登录成功之后会发起登录提交请求POST,账户名密码+手机验证码等提交给server,如果信息是正确的,那么server会生成一个token但不会保存,然后response返回该token,下次请求时发送token,server对token进行解析,判断是哪位用户,返回相应信息。
ps:一般https默认的端口号就是443
实战分析
浏览器:http的运用主要是在AJAX的XHR和Fetch
node:标准库(HTTP、HTTPS)、axios
网络优化
稳定性
重试机制(超时、错误)
缓存
数据安全
WebSocket
浏览器与服务器进行双工通讯的网络技术(聊天室等实时性要求高的场景,URL使用ws://或者wss://开头
QUIC
Quick UDP Internet Connection
0-RTT建联
类似TCP可靠传输
类似TLS加密传输。。。
前端设计模式应用
设计模式简介
设计模式(Design pattern)代表了最佳实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式是软件设计中常见问题的解决方案的模型,它是历史经验的总结,与特定语言无关。
设计模式分类
根据设计模式的参考书 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 中所提到的,总共有 23
种设计模式,可分为三大类。
创建型模式 - 如何创建一个对象
- 工厂模式
- 抽象工厂模式
- 单例模式
- 建造者模式
- 原型模式
结构型模式 - 如何灵活的将对象组装成较大的结构
- 适配器模式
- 桥接模式
- 过滤器模式
- 组合模式
- 装饰器模式
- 外观模式
- 享元模式
- 代理模式
行为型模式 - 复责对象间的高效通信和职责划分
- 责任链模式
- 命令模式
- 解释器模式
- 迭代器模式
- 中介者模式
- 备忘录模式
- 观察者模式
- 状态模式
- 空对象模式
- 策略模式
- 模板模式
- 访问者模式
浏览器中的设计模式
单例模式
定义:全局唯一访问对象。eg:window
应用场景:用单例模式实现请求缓存,全局状态管理等。
import { api } from "./utils"
// 创建了一个响应类
export class Request{
static instance: Request;
// 私有变量 map类型 键值对 保存 url与对应的资源
private cache: Record<string, string>;
constructor() {
// 进行初始化
this.cache = {};
}
// 创建实例对象时使用该方法创建
static getInstance() {
// 如果实例有缓存 则直接返回该实例
if(this.instance) {
return this.instance;
}
// 否则就返回new的新对象
this.instance = new Request();
return this.instance;
}
// 接下来就是实现响应的部分
public async request(url: String) {
// 如果有该url的缓存 则返回
if(this.cache[url]) {
return this.cache[url];
}
// 否则就异步进行资源请求 完成后不要忘记将其保存到cache中
const response = await api(url);
this.cache[url] = response;
}
}
发布订阅模式
定义:一种订阅机制,可在被订阅对象发生变化时通知订阅者。
应用场景:从系统架构之间的解耦,到业务中一些实现模式,像邮件订阅,上线订阅等等,应用广泛。
const button = document.getElementById("button")
const doSomething1 = () => {
console.log("Send message to user")
}
const doSomething2 = () => {
console.log("Log...")
}
button.addEventListener("click", doSomething1)
button.addEventListener("click", doSomething2)
JavaScript中的设计模式
这里设计模式其实没有太懂
原型模式
定义:复制已有对象来创建新的对象。
应用场景:JS中对象创建的基本模式。
代理模式
定义:可自定义控制对原对象的访问方式,并且允许在更新前后做一些额外处理。
应用场景:监控,代理工具,前端框架实现等等。
迭代器模式
定义:在不暴露数据类型的情况下访问集合中的数据。
应用场景:数据结构中有多种数据类型,列表,树等,提供通用操作接口。
前端框架中的设计模式
代理模式
定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。
应用场景:对 DOM 进行操作等。
前端框架中对 DOM 操作的代理:
虚拟 DOM(Virtual DOM)本质上是 JS 和 DOM 之间的一个映射缓存,它在形态上表现为一个能够描述 DOM 结构及其属性信息的 JS 对象。
- 虚拟 DOM 是 JS 对象
- 虚拟 DOM 是对真实 DOM 的描述
我们看看 React 中的虚拟 DOM 大致是如何工作的:
- 挂载阶段:React 将结合 JSX 的描述,构建出虚拟 DOM 树,然后通过
ReactDOM.render
实现虚拟 DOM 到真实 DOM 的映射(触发渲染流水线)。- 更新阶段:页面的变化在作用于真实 DOM 之前,会先作用于虚拟 DOM,虚拟 DOM 将在 JS 层借助算法先对比出具体有哪些真实 DOM 需要被改变,然后再将这些改变作用于真实 DOM。
组合模式
定义:可多个对象组合使用,也可单个对象独立使用。
应用场景:DOM,前端组件,文件目录,部门。
响应式系统与React
掘金上关于青训营的笔记
响应式系统与React|青训营笔记 - 掘金 (juejin.cn)
B站尚硅谷笔记
[react-study/React 入门学习/React 入门学习(一)– 基础知识以及 jsx语法.md at main · linjunc/react-study (github.com)](https://github.com/linjunc/react-study/blob/main/React 入门学习/React 入门学习(一)– 基础知识以及 jsx语法.md)
xzlaptt/React: React学习 (github.com)
回流与重绘
回流:对DOM的修改引发了DOM几何尺寸的变化(修改元素的宽、高或者隐藏元素等)时,浏览器需要重新计算元素的几何属性,然后再将计算的结果绘制出来,这个过程就是回流(也叫做重排)。 个人理解:这里应该就是布局树的重新建立(包括局部范围或者全局范围:从根节点html开始对整个渲染树进行重新布局)
重绘:对DOM的修改导致了样式的变化却并没有影响它的几何属性(比如修改了颜色或者背景色)时,浏览器不需要重新计算元素的几何属性、直接为该元素绘制新的样式。这个过程叫做重绘
只改变外观,风格,不影响布局,会引发重绘。
所以回流必然会引起重绘,但是重绘不一定会引起回流