chenhw2017 / blogs Goto Github PK
View Code? Open in Web Editor NEW记录自己的前端成长之路,并加以总结以和大家分享交流
Home Page: https://github.com/Chenhw2017/blogs
记录自己的前端成长之路,并加以总结以和大家分享交流
Home Page: https://github.com/Chenhw2017/blogs
微软出品必属精品,vscode也不例外,微软大佬凭借其强大的开发与架构能力给予electron实现了跨平台的可拓展的轻量级编辑器,其很多强大的功能都是通过其插件拓展实现的
阅读这篇文章你将收获:
同时我也需要有以下知识储备
npm i -g yo generator-code
yo code
或者执行yo通过命令行选择相应的代码生成器我们今天就做个类型收藏小网站的功能,最终效果图如下:
1 ��使用yo生成插件模版
2 在package.json配置要用到的插件激活命令、相应的view命令
3 在activate生命钩子黎明定义相应命令对应的处理逻辑
4 实现TreeDataProvider
5 注册webview命令及相应处理逻辑
1 contributes.viewsContainers.activitybar
:主要是定义右边tabbar
2 定义treeview,如果key等于上面activitybar的id,则这个view就属于那个bar里
3 如果这个view的id在activationEvents的onview注册了,那么这个view的展示就会促发activate钩子函数
研究表明知识概念的图形化,相较于文字描述更具有直观性,有助于高效的学习及加深对知识概念的理解
http协议的文章太多了,光掘金就有"几千篇",更别说google了,也有很多优秀的文章,但是本文将尽可能避免过多的使用文字,而是使用图形或者表格来刻画描述http及其相关生态圈概念,以便让大家能够花最少的时间更加高效直观的掌握http以及方便以后查阅,作图作表不易,你的赞就是对作者的最大的鼓励
阅读本文你将收获/了解:
请求方式 | 描述 |
---|---|
GET | GET方法请求一个指定资源的表示形式. 使用GET的请求应该只被用于获取数据. |
HEAD | HEAD方法请求一个与GET请求的响应相同的响应,但没有响应体(报文主体),用于确认URI的有效性及资源更新的日期时间等. |
POST | POST方法用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用. |
PUT | PUT方法用请求有效载荷替换目标资源的所有当前表示, 由于PUT自身不带验证机制,存在安全问题,一般不用,若配合web程序的验证制或架构设计采用REST标准的同类web网站,可能会开放PUT方法 |
DELETE | DELETE方法删除指定的资源,一般不用,原因PUT |
CONNECT | CONNECT方法建立一个到由目标资源标识的服务器的隧道. |
OPTIONS | 查询针对指定请求URI指定的资源支持的方法 |
TRACE | TRACE方法配合Max-forwords沿着到目标资源的路径执行一个消息环回测试,不常用(容易跨站追踪攻击) |
LINK | 建立和资源之间的联系(HTTP/1.1已弃用) |
�UNLINK | 断开连接关系(HTTP/1.1已弃用) |
状 态 码 | 描述 |
---|---|
1xx | Informational(信息性状状态码),接受的请求正在处理 |
2xx | Success(成功状态码),请求正常处理完毕 |
200 | OK:请求正常处理完毕,注意HEAD请求方法不返回报文主体 |
204 | NO CONTENT:成功处理但是返回响应不含任何实体的主体;当然也不允许返回任何实体的主体,一般用于不需要对客户端返回新内容对情况 |
206 | Partial Content:客户端进行了范围请求,而服务器成功执行了这部分GET请求,响应报文中包含由Content-Range指定范围的实体内容 |
3xx | 重定向 |
301 | Moved Permanently:永久性重定向,请求的资源已经被分配新的URI,以后应使用该URI |
302 | Found:临时性重定向,请求的资源已经被分配新的URI,希望本次应使用该URI |
303 | See Other:对应当前请求的响应可以在另一个 URI 上被找到,而且客户端应当采用 GET 的方式访问那个资源。与302区别是如果POST方式希望用户能使用GET重定向,303状态码更加合适,虽然功能上是一样的 |
304 | Not Modified:客户端发送带有条件的请求时,服务器允许请求访问资源,但是因发生请求未满条件的情况(即可直接shying客户端未过期缓存) |
307 | Temporary Redirect:临时性重定向,与302含义相同,尽管302标准禁止POST改为GET,但是实际大家并不遵守,307会遵守标准不会POST改为GET,但是对于处理响应的行为,每种浏览器可能不一样 |
4xx | 客户端错误 |
400 | Bad Request:请求报文中存在语法错误 |
401 | Unauthorized:当前请求需要用户验证,弹出认证用的对话窗口;若之前已经请求过一次,则表示用户认证失败,该响应必须包含一个适用于请求资源的 WWW-Authenticate 信息头用以询问用户信息 |
403 | Forbidden:服务器已经理解请求,但是拒绝执行它 |
404 | Not Found:请求失败,请求所希望得到的资源未被在服务器上发现.也可用于当服务器不想揭示到底为何请求被拒绝或者没有其他适合的响应用的情况 |
405 | Method Not Allowed:请求行中指定的请求方法不能被用于请求相应的资源。该响应必须返回一个Allow 头信息用以表示出当前资源能够受的请求方法的列表 |
5xx | 服务器错误 |
500 | Internal Server Error:服务器在执行请求时发生了错误,也可能是web应用存在bug或者临时故障 |
502 | Bad Gateway:此错误响应表明服务器作为网关需要得到一个处理这个请求的响应,但是得到一个错误的响应。 |
503 | Service Unavailable:服务器没有准备好处理请求。 常见原因是服务器因维护或超负载而停机 |
504 | Gateway Timeout:当服务器作为网关,不能及时得到响应时返回此错误代码 |
字段名称 | 可能值举例 | 缓存优先级 | 描述 |
---|---|---|---|
Cache-Control | max-age=3600 | 高(强缓存) | 再次请求3600s内都可以使用缓存 |
Expires | Sat, 10 Jan 2020 09:00:00 GMT | 高(强缓存) | 2020年1月10日9点之前再次请求都可以使用缓存 |
If-Modified-Since/Last-Modified | Sat, 10 Jan 2020 09:00:00 GMT | 低 | 第一个时间>第二个(只能精确到秒),返回304,反之,200,读取服务器资源并返回实体结果 |
If-None-Match/ETag | 123xx | 中 | 若123xx!==ETag,则读取资源并返回实体,反之304,注意:,ETag判断资源是否修改的准确度虽然高于If-Modified-Since ,但这是要牺牲服务器的资源的为前提的,因为要根据算法生成ETag需要额外开销服务器资源 |
注: 1.缓存控制字段同时存在时,会按照优先级由高到低进行控制缓存命中控制,在
HTTP/1.0
中,同时存在Cache-Control和Expires会忽略Cache-Control,在HTTP/1.1
中,则会忽略Expires
指令 | 参数 | 说明 |
---|---|---|
no-cache | 无 | 强制向源服务器再次验证 |
no-store | 无 | 不缓存请求或响应的任何内容 |
max-age = [ 秒] | 必需 | 响应的最大Age值 |
max-stale( = [ 秒]) | 可省略 | 接收已过期的响应 |
min-fresh = [ 秒] | 必需 | 期望在指定时间内的响应仍有效 |
no-transform | 无 | 代理不可更改媒体类型 |
only-if-cached | 无 | 从缓存获取资源 |
cache-extension | - | 新指令标记(token) |
指令 | 参数 | 说明 |
---|---|---|
public | 无 | 可向任意方提供响应的缓存 |
private | 可省略 | 仅向特定用户返回响应 |
no-cache | 可省略 | 缓存前必须先确认其有效性 |
no-store | 无 | 不缓存请求或响应的任何内容 |
no-transform | 无 | 代理不可更改媒体类型 |
must-revalidate | 无 | 可缓存但必须再向源服务器进行确认 |
proxy-revalidate | 无 | 要求中间缓存服务器对缓存的响应有效性再进行确认 |
max-age = [ 秒] | 必需 | 响应的最大Age值 |
s-maxage = [ 秒] | 必需 | 公共缓存服务器响应的最大Age值 |
cache-extension | - | 新指令标记(token) |
在使用强缓存时,当我们设置了缓存有效时间之后,如果在有效时间静态内资源被修改,但是我们依然会使用缓存(老的),显然生成中这是不被允许的!在单页面实践中,在打包的时候
webpack
会通过hash
的方式修改html
引用的静态资源文件名(否者静态资源的URI没变,依然会使用缓存),并将其嵌入html
中生产新的html
文件,所以我们只需要设置请求html
资源为no-cache
(即每次请求都会验证缓存的有效性)就可以保证即使缓存有效期内,被引用的静态资源发生了修改,也能获取到最新的改动
首部字段名 | 说明 |
---|---|
Cache-Control | 控制缓存的行为 |
Connection | 逐跳首部、连接的管理 |
Date | 创建报文的日期时间 |
Pragma | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式 |
Upgrade | 升级为其他协议 |
Via | 代理服务器的相关信息 |
Warning | 错误通知 |
首部字段名 | 说明 |
---|---|
Accept | 用户代理可处理的媒体类型 |
Accept-Charset | 优先的字符集 |
Accept-Encoding | 优先的内容编码 |
Accept-Language | 优先的语言(自然语言) |
Authorization | Web认证信息 |
Expect | 期待服务器的特定行为 |
From | 用户的电子邮箱地址 |
Host | 请求资源所在服务器 |
If-Match | 比较实体标记(ETag) |
If-Modified-Since | 比较资源的更新时间 |
If-None-Match | 比较实体标记(与 If-Match 相反) |
If-Range | 资源未更新时发送实体 Byte 的范围请求 |
If-Unmodified-Since | 比较资源的更新时间(与If-Modified-Since相反) |
Max-Forwards | 最大传输逐跳数 |
Proxy-Authorization | 代理服务器要求客户端的认证信息 |
Range | 实体的字节范围请求 |
Referer | 对请求中 URI 的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP 客户端程序的信息 |
首部字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定URI |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
首部字段名 | 说明 |
---|---|
Allow | 资源可支持的HTTP方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(单位:字节) |
Content-Location | 替代对应资源的URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
协议简称 | 英文全称 | 中文全称 | 描述 |
---|---|---|---|
SMTP | Simple Mail Transfer Protocol | 简单邮件传输协议 | 用于邮件发送的基于TCP的应用层协议 |
POP3 | Post Office Protocol - Version 3 | 邮局协议版本3 | 用于邮件接收的基于TCP的应用层协议 |
DNS | Domain Name System | 域名系统 | 用于解析域名与IP地址的基于UDP/TCP 应用层协议 |
DHCP | Dynamic Host Configuration Protocol | 动态主机配置协议 | 用于主机动态获取IP地址、缺省网关、DNS服务器等参数的基于UDP 应用层协议 |
CIFS | Common Internet File System | 通用网络文件系统 | Windows 文件共享的基于TCP的应用层协议 |
NFS | Network File System | 网络文件系统 | 用于Unix / Linux 文件共享,基于UDP/TCP协议 |
NTP | Network Time Protocol | 网络时间协议 | 用于时钟同步的基于UDP的应用层协议 |
SIP | Session Initiation Protocol | 会话发起协议 | IP电话信令协议,IETF协议标准,基于TCP/UDP应用层协议 |
H.323 | - | - | IP电话信令协议,国际电信联盟 ITU协议标准,基于TCP/UDP应用层协议 |
RTP | Real-time Transport Protocol | 实时传输协议 | 用于IP多媒体电话的语音、文字、视频等流体的传输,基于UDP的应用层协议 |
http几乎深透了我们每天的开发实践中,渗透到你对它的存在习以为常而忽略它,,但它真的很重要,因为它是前后端通信的桥梁,也是前端性能优化的一个点,这块知识难点不多,但是很散,如果大家看完这篇文章(图),对http生态有个清晰或者深刻的认识,我的目的就达到了~,本人水平有限,文章如有错误或者建议,还请指教
call/apply在我们日常开发中也是经常会用到的两个api,如何使用它们我们并不陌生,所以今天我们讨论下如何实现它
用法:function.call(thisArg, arg1, arg2, ...)
它有以下功能与约束:
function
,并且指定function内this指向为thisArg
call
没有副作用,调用之后不会对thisArg
产生任何影响function
调用的返回值对于第一点
这里需要处理下参数的兼容性及相应的性能优化:
null
或者undefined
,则this
为宿主环境全局对象null
或者undefined
且参数只有一个时或者参数为空时,就没必要进行下面逻辑了function globalEnv () {
return this;
}
...
if(typeof thisArg === 'string' || typeof thisArg === 'boolean' || typeof thisArg === 'number') {
thisArg = new Object(thisArg);
}else if (!arguments.length || (thisArg === null || thisArg === void 0) && arguments.length === 1) { // call() || call(null)
return this();
}
thisArg = thisArg || globalEnv();
Tip:基本类型进行转换相应类型的实例对象
var numberObj = new Object(22);
numberObj.constructor === Number // => true
numberObj instanceof Number // => true
numberObj instanceof Object // => true
对于第二点,我们如何实现调用function
,并且指定function内this指向为thisArg
呢?
我们知道函数调用时,其函数内this指向分为以下四种情况
obj.fn()
,fn
内this
指向就是obj
。首先,function
不一定是构造函数所以1行不通,2是我们这次要实现的pass,因为call
就是要绑定到指定对象,全局或者undefined
只是其中一种情况,所以我们通过3将函数绑定到上下文对象上即thisArg
更加符合要求,分析到这里思路就非常明确了,无非就是给绑定对象thisArg
加个function
方法
var uiqueFn = Date.now();
while (thisArg.hasOwnProperty(uiqueFn)) { // 防止属性重复
uiqueFn = Date.now();
}
thisArg[uiqueFn] = this; // 1
由于参数是从类数组对象arguments
取出,其只支持for
遍历,不支持数组其他api
var rest = [],result;
for (var index = 1; index < arguments.length; index++) {
rest.push("arguments[" + index + "]");
}
函数调用时,是以fn(a,b,c...)
的形式调用,考虑兼容问题不实用es6的拓展运算符,改用eval的形式,如果你有更好的方法,欢迎评论👏
eval('result = thisArg[uiqueFn]('+arr+')');
函数调用获取结果后,将添加的���属性删除即可,并把函数结果返回
delete thisArg[uiqueFn]; // 2
return result;
最后,贴下完整代码:
function globalEnv () {
return this;
}
Function.prototype._mycall = function (thisArg) {
if(typeof thisArg === 'string' || typeof thisArg === 'boolean' || typeof thisArg === 'number') {
thisArg = new Object(thisArg);
}else if (!arguments.length || (thisArg === null || thisArg === void 0) && arguments.length === 1) { // call() || call(null)
return this();
}
thisArg = thisArg || globalEnv();
var uiqueFn = Date.now();
while (thisArg.hasOwnProperty(uiqueFn)) {
uiqueFn = Date.now();
}
thisArg[uiqueFn] = this; // 1
var rest = [],result;
for (var index = 1; index < arguments.length; index++) {
rest.push("arguments[" + index + "]");
}
eval('result = thisArg[uiqueFn]('+rest+')'); // 3
delete thisArg[uiqueFn]; // 2
return result;
}
用法:func.apply(thisArg, [argsArray])
apply和call两者除了参数不同之外,其他没有任何区别,实现上只有对于第二个参数的错误处理有区别之外,其他几乎没有任何区别,这里我就不再赘述细节直接贴代码
注意
⚠️ :由于是检测函数类型,所以这里instanceof
可以使用typeof
替代进行检测,但是需注意typeof对于其他类型如null判断的是object
,以及其他引用类型也是object
,如Array
、Date
等
Function.prototype._myapply = function (thisArg) {
if(!this instanceof Function) {
throw new Error(`${this}.myapply is not a function`)
} else if(!arguments.length || (thisArg === null || thisArg === void 0) && arguments.length === 1) { // 参数全部为空直接调用 没必要执行下面逻辑了
return this();
} else if (typeof arguments[1] === 'boolean' || typeof arguments[1] === 'string' || typeof arguments[1] === 'number') { // 兼容处理部分基本类型
throw new Error(`CreateListFromArrayLike called on non-object`);
}
thisArg = thisArg || globalEnv();
var uiqueFn = Date.now();
while (thisArg.hasOwnProperty(uiqueFn)) {
uiqueFn = Date.now();
}
var rest = arguments[1] instanceof Array ? arguments[1] : [], result, arr = [];
for (var index = 0; index < rest.length; index++) {
arr[index] = 'rest['+index+']'
}
thisArg[uiqueFn] = this;
eval('result = thisArg[uiqueFn]('+arr+')');
delete thisArg[uiqueFn];
return result;
}
节流与防抖这两个概念大家并不陌生,可是你是否真正了解两者的真正区别?是否能够在实际开发中知道什么时候该用防抖?什么用节流?
debounce(fn, threshhold)
技术最终都要服务于社会,任何脱离业务(社会)实际的都是耍流氓,防抖当然也不例外,实际生活中对于拍照(人工防抖,不是智能那种:joy:),如果你在自拍,你肯定不会在镜头没稳定之前,按下快门吧(PS:如果你想要这种模糊效果当我没说:no_mouth:),也就是镜头不稳(手抖)你不会按下快门,如果你感觉稳了,才会按下快门,类似:
debounce
的功能就相当于帮你判断什么时候该按下快门fn
相当于快门threshhold
(阈值)就相当于人体感知稳定的需要经历的时间阈值threshhold
有一次抖动都会重新判断稳定threshhold
间隔内一直稳定不下来,第一次触发threshhold
ms之后fn不会被执行,同理一直不稳定,fn永远不会被执行(假入死循环)// fn => 2
function debounce(fn, threshhold){ // 1
if(!fn instanceof Function) {
throw new TypeError('Expected a function')
}
let timer = null;
return function () {
clearTimeout(timer); // 3
timer = setTimeout(() => {
fn.apply(this) // 4
},threshhold)
};
}
代码浅析:debounce
就相当于帮你判断是什么时候该按下快门,要执行的fn相当于快门,人体的感知稳定时间阈值为threshhold
,如果连续两次调用(对应拍照抖动)小于threshhold
,那么肯定要重新设置稳定间隔的起始点也就是重置clearTimeout(timer)
,当然如果两次间隔超过threshhold
,重置已经无法影响了已经发生的调用了,最后定时器执行fn.apply(this)
就是手终于不抖可以按下快门啦:joy:
throttle(fn, threshhold)
实际生活中,节流这一概念其实生活中有很多例子,比如这快过年了,火车站考虑到大家的安全,对进站进行节流(官方应该叫限流,其实表达都是同一个意思)因为单位时间内车站的接待(容纳)人数是有限的,还有大家更加熟悉的例子,王者荣耀或者英雄联盟这类moba游戏,都有攻速上限(攻速2.5),换句话说哦假设程序设定了英雄一秒最多A五下,那么即使你手速再快,1s内也A不出第六下,通过以上例子我们可以得出:
threshhold
间隔内函数fn
无论触发多少次,第一次触发到threshhold
ms后都是只执行一次threshhold
,则第二次会立即执行根据这两点,有两种实现方式
function throttle(fn, threshhold) {
if(!fn instanceof Function) {
throw new TypeError('Expected a function')
}
let limited = false; // 节流阀标志位
let start = Date.now();
threshhold = threshhold || 500
return function (...args) {
let current = Date.now();
limited = limited && current- start < threshhold
if(!limited) {
fn.apply(this,args);
limited = true;
start = Date.now();
}
}
}
代码浅析:通过limited
节流阀标志位模拟当前是否需要节流(限流),第一次默认fales
即首次不限流(车站为空的:joy:),限流之后(limited = true
)且只有两次时间间隔(current- start
)超过threshhold
,才会除去限制,调用fn即车站让旅客进站进入新的周期重置开始时间start
function throttle2(fun, threshhold) {
if(!fun instanceof Function) {
throw new TypeError('Expected a function')
}
let limited = false; // 节流阀标志位
let timer = null;
let start = Date.now();
threshhold = threshhold || 500
return function (...args) {
let current = Date.now();
limited = limited && current- start < threshhold
if (limited) {
clearTimeout(timer)
timer = setTimeout(() => {
limited = true
start = Date.now()
fun.apply(this, args)
}, threshhold)
}else {
limited = true
start = Date.now();
fun.apply(this,args)
}
}
}
代码浅析:第二种使用了setTimeout
定时器的方式,多加了如果最后一次触发距离上一次调用fn
小于threshhold
则这次设置的定时器回调将会在下一个threshhold
周期内执行,所以这种方式触发多次fn
总共会执行两次
,只是第二次会在下一个threshhold
周期内执行
节流两种方式对比
- 第一种,一个
threshhold
间隔内多次促发,fn
只会被执行一次,最后一次并不会进入下一个周期执行,比如连续1秒内平A了5次超过限度(节流)5次,第六次并不会说下一秒自动平A,而是直接舍去- 第二种,一个
threshhold
间隔内多次促发,fn
总共会执行两次,注意第二次会进入下一个threshhold
周期执行
相同点:
区别:
threshhold
时间间隔之后fn
也没执行,但是使用节流触发的threshhold
间隔内有且只执行一次threshhold
间隔内连续触发,防抖只执行一次,而节流会执行两次,只是在不同的threshhold
周期内无论什么技术都有他擅长的地方,技术与实现的优与劣不能单从技术方面去考量,这样是没有意义的,如对于节流函数的两种方式,他们都有适合的场景,比如你的产品需要类似游戏内限制攻速的,显然节流的第一种方案更合适,元芳你怎么看?:laughing:(ps:github源码地址含单测)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.