如何知道鼠标在canvas元素上
- 对于规则图形可以直接使用数学方法判断
- 对于复杂图形,可以使用ctx.getPointPath(x, y)方法
// 监听鼠标事件 cvs.onmousemove = function (e) { // 得到鼠标的坐标 var x = e.pageX, y =e.pageY; ctx.clearRect(0,0,400,300) // 遍历绘制图形 for(var i = fns.length; i--;) { fns[i](); // 每绘制一个图形就判断一次当前鼠标的坐标是否在这个图形上,然后进行自定义操作 if(ctx.isPointInPath(x,y)) { ctx.fillStyle = "#f00" } else { ctx.fillStyle = "#000" } ctx.fill() } }
Vue中的props传递是单向的,也就是说父子组件的prop之间形成的是一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
**这么做的原因:**防止子组件更改父组件的状态,组件是可以复用的,假设子组件被复用了n次,当一个组件更改了父组件的状态,其他的子组件跟着就一起改了,引起混乱。正确的做法是将传递过来的props进行转换处理,利用 computed
计算属性处理。
浏览器渲染网页注意事项
DOM的构建过程是一个深度遍历的过程,即当前节点的所有子节点都构建好以后才会去构建当前节点的下一个兄弟节点
渲染树和DOM不同,因为像DOM树中的display:none
元素不会出现在渲染树中,但visibility: hidden会出现在渲染树中
DOM解析和CSS解析是同时进行,互不影响
渲染树的生成并不是等到DOM树和CSS规则树解析完成才开始合并,而是边解析、边合并渲染
浏览器渲染网页阻塞顺序
构建DOM树时,如遇到JS元素时,会阻塞DOM树和CSS规则树的构建,优先执行JS文件
构建DOM树时,如遇到CSS元素时,会开启异步请求线程,该线程会先下载CSS文件,再构建CSS规则树,该线程会阻塞JavaScript引擎线程,但不会阻塞DOM树的构建
CSS解析和JS解析互斥,也就是说JS解析时会阻塞CSS解析而CSS解析时也会阻塞JS解析
JS解析时,如果JS还操作了CSS,而这个CSS还没有下载或构建解析,则会延迟执行JS,直到完成CSS下载构建解析,再会继续执行JS
白话说明
浏览器在渲染网页时会开启两条线程,渲染引擎线程和JS引擎线程,但这两条线程是互斥的,同时只能有一个线程在执行。也就是说在构建DOM树时,渲染引擎在执行:
当遇到JS时:渲染引擎会停止执行,控制权交给JS引擎,当执行JS代码时
如果遇到获取DOM,那么如果该DOM还没有解析,则会获取为null,如果JS代码还操作了CSS,而这个CSS如果还没有下载和构建,那么浏览器首先会阻塞JS引擎执行,然后会开启一个异步请求线程,在该线程上,去下载构建CSS规则树,CSS规则树构建完成后,再继续执行JS代码,当JS执行完以后,控制权再次交给渲染引擎去执行。
当遇到CSS元素时:也会开启异步线程,去下载构建CSS规则树,但同时也会继续构建后面的DOM树,也就是说DOM解析和CSS解析可以同时进行,但如果后面遇到JS元素,则会阻塞JS引擎线程执行,后面DOM树解析不受影响。
版权声明:本文为CSDN博主「小凳子腿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Liu_yunzhao/article/details/91550704
就经验来说,如果页面完全一片空白。极有可能是后端出现问题,并且禁用了错误输出。比如apache2,后端配置无错误输出,并且服务状态500,这个时候页面就是一片空白。
如果是前端导致的,那么极有可能是单页应用异常,因为普通的html输出,哪怕出了一些错误,也不太可能一片空白。
排查步骤如下:
如果没有明确设定容器高情况下它要计算内容全部高度,才能确定在什么位置hidden
浮动的高度就要被计算进去,顺带达成了清理浮动的目标。
同理
overflow 非默认值
position 非默认值
float 非默认值
等都是遵循这个布局计算思路
除了推送内嵌资源之外,还可以推送什么?其实, 任何HTTP响应都是平等的游戏。我们能推送一次重定向吗? 是的, 那很简单:
spdy.createServer(options, function(req, res) {
//push JavaScript asset (/newasset.js) to the client
res.push('/newasset.js', {'content-type': 'application/javascript'}, function(err, stream) {
stream.end('alert("hello from (redirected) push stream!")');
});
// push 301 redirect: /asset.js -> /newasset.js 这里为重定向
res.push('/asset.js', {':status': 301, 'Location': '/newasset.js'}, function(err, stream) {
stream.end('301 Redirect');
});
// write main response body and terminate stream
res.end('');
}).listen(443);
我们还能做的更多吗?推送缓存失效信息和再验证信息到客户端,怎么样?我们可以把已经存在于客户端缓存中的任何资源标记为失效(即推送一个失效时间戳),或者相反,推送一个携带未来时间戳的304来更新资源的生存期。简言之,服务器能够主动的管理客户端缓存!
SSE类似于长轮询的机制,但是它在每一次的连接中,不只等待一次数据的更动。客户端发送一个请求到服务端 ,服务端保持这个请求直到一个新的消息准备好,将消息返回至客户端,此时不关闭连接,仍然保持它,供其它消息使用。SSE的一大特色就是重复利用一个连接来处理每一个消息(又称event)。
// 前端
var evtSource = new EventSource('/sse');
evtSource.addEventListener('testEvent', function (e) {
console.log(e)
}
// 后端
router.get('/sse', (req, res, next)=> {
res.writeHead(200, {
'Connection': 'keep-alive',
'Content-Type': 'text/event-stream', // 这个必须要设置
'Cache-Control': 'no-cache'
});
let data = { meg: '这是一个测试SSE的数据内容' };
setTimeout(() => {
console.log(JSON.stringify(data));
res.write('data:' + JSON.stringify(data) + '\n\n');
}, 2000)
})
chrome浏览器有一个memory选项卡,点击之后去进行快照,过一段时间再进行快照,展示快照之间的对比。
#New:新建了多少对象
#Deleted:回收了多少对象
#Delta:新建的对象个数减去回收的对象个数
重点看closure(闭包),如果#Delta为正数,则表示创建了闭包函数,如果多个快照中都没有变负数,则表示没有销毁闭包。
使用CORS解决跨域问题,想要带上cookie必须要设置
前端:xhr.withCredentials = true 来标识传输cookie,如果使用axios,直接
axios({
method: 'get',
url,
data,
params,
withCredentials: true
})
后端需要设置响应头 Access-Control-Allow-Credentials:true 才能获得前端的cookie (注意:设为true时,Access-Control-Allow-Origin不能为’*’)
1、数据库密码字段存入的数据为MD5加密后的数据
2、第一次访问登录页面通过uuid生成一个loginkey并存入session
3、前端提交登录数据的密码构成: MD5(MD5(用户填写的密码)+loginkey) 传入后台
4、后台验证用户存在的情况下取出用户数据库数据进行验证:MD5(数据库密码+session中的loginkey) === 用户提交的密码(步骤三传过来的密码)
就是传输文件时,不必重头开始传输,而是从指定的位置继续传输,这样的功能就叫做断点续传。 断点续传的理解可以分为两部分:一部分是断点,一部分是续传。断点的由来是在传输过程中,将一个传输文件分成了多个部分,同时进行多个部分一起的下载,当某个时间点,任务被暂停了,此时下载暂停的位置就是断点了。续传就是当一个未完成的下载任务再次开始时,会从上次的断点继续传送。
原理:
官方不推荐get请求带body,一般来说,服务端会忽略get请求的body,但是协商一下,更改一下配置是可以的。往GET里加body会导致缓存机制失效。“GET 被设计来用 URI 来识别资源,如果让它的请求体中携带数据,那么通常的缓存服务便失效了,URI 不能作为缓存的 Key。”
Body类请求在语义能力上兼容url类请求,但是post用url传参不符合RESTful风格。而且body中能带的数据比url中大得多。
www.a.baidu.com 与 www.b.baidu.com 会发生跨域吗?
子域名不同,也会发生跨域。解决方法:
有a.ceshi.com通过iframe加载b.ceshi.com下的内容,通过对两个子域下的页面同时设置document.domian设置为相同的主域名可实现跨域读取数据:
Chrome 51 开始,浏览器的 Cookie 新增加了一个SameSite
属性,用来防止 CSRF 攻击和用户追踪。Cookie 的SameSite
属性用来限制第三方 Cookie,从而减少安全风险。他有三个值:
Strict:最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
Lax:适当放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
None:必须同时设置Secure
属性(Cookie 只能通过 HTTPS 协议发送),否则无效。下面的设置有效:
Set-Cookie: widget_session=abc123; SameSite=None; Secure
用来标识文档的元数据,元数据是用来描述数据的数据,它不会显示在页面中,但是机器却可以识别。因此meta标签常用来定义页面的说明、关键字、最后修改日期等元数据。这些元数据将,告诉浏览器怎么布局或重载页面,告诉搜索引擎页面的一些信息等。meta标签共有两个属性,分别是http-equiv属性和name属性。
name属性:用于描述网页,比如关键词、描述,与之对应的属性是content。常见的name有keyword、description、viewport、robot、autor、copyright…
<meta name="参数" content="具体的描述">。
http-equiv属性:顾名思义,相当于http的头文件使用,与之对应的属性也是content。常见的http-equiv有content-type设置网页字符集,便于浏览器解析(现在直接用charset属性)、cache-control指定缓存机制(和http一样)、expire、set-cookie、x-dns-prefetch-control(dns预解析)…http响应头的优先级比meta高。
<meta http-equiv="参数" content="具体的描述">
用js是可以获取到meta标签中值的:
function getMeta(metaName) {
const metas = document.getElementsByTagName('meta');
for (let i = 0; i < metas.length; i++) {
if (metas[i].getAttribute('name') === metaName) {
return metas[i].getAttribute('content');
}
}
return '';
}
function fetchImageWithLimit(imageUrls, limit) {
// copy一份,作为剩余url的记录
let urls = [ ...imageUrls ]
// 用来记录url - response 的映射
// 保证输出列表与输入顺序一致
let rs = new Map()
// 递归的去取url进行请求
function run() {
if(urls.length > 0) {
// 取一个,便少一个
const url = urls.shift()
return fetchImage(url).then(res => {
rs.set(url, res)
return run()
})
}
}
// 当imageUrls.length < limit的时候,我们也没有必要去创建多余的Promise
const promiseList = Array(Math.min(limit, imageUrls.length))
// 这里用Array.protetype.fill做了简写,但不能进一步简写成.fill(run())
.fill(Promise.resolve())
.map(promise => promise.then(run))
return Promise.all(promiseList).then(() => imageUrls.map(item => rs.get(item)))
}
limit
个图片请求,作为Promise.race
的参数limit - 1
个图片请求一起作为新一轮的Promise.race
的参数function imageLoad(urls,fetchImage,limit) {
//先创建长度为limit的池子
let pool = urls.splice(0,limit).map((item,index)=>{
return fetchImage(item).then(res=>{
return index //将当前加载完图片的 index返回
})
});
let p = Promise.race(pool) //将第一个执行成功的 先返回
for (let i = 0; i < urls.length; i++) {
p = p.then(index=>{ //形成链式调用.then .then
pool[index] = fetchImage(urls[i]).then(()=>{
//将已经加载完成的图片重新替换成新的 未加载的图片
return index
})
return Promise.race(pool)
})
}
}
执行 imageLoad(imageUrls,fetchImage,3)
https不一定全是安全的,一些网站会使用自签名证书。
自签名证书是指不受信任的任意机构或个人,使用工具自己签发的SSL证书。不是从公共证书机构(CA)那里申请来的证书,没有第三方监督审核,不受浏览器和操作系统信任,常被用于伪造证书进行中间人攻击,劫持SSL加密流量。
Tree shaking 是一种通过清除多余代码方式来优化项目打包体积的技术,专业术语叫 Dead code elimination。虽然 tree shaking
的概念在 1990 就提出了,但直到 ES6
的 ES6-style
模块出现后才真正被利用起来。因为 import 是完全静态的,因此可以进行静态分析,在编译的时候就知道哪些模块和变量未被使用。
Quic概述:相比于 http2+tcp+tls 协议有如下优势:
采用TCP协议进行网络数据传送的软件设计中,普遍存在粘包问题。这主要是由于现代操作系统的网络传输机制所产生的。我们知道,网络通信采用的套接字(socket)技术,其实现实际是由系统内核提供一片连续缓存(流缓冲)来实现应用层程序与网卡接口之间的中转功能。多个数据包被连续存储于连续的缓存中,在对数据包进行读取时由于无法确定发生方的发送边界,而采用某一估测值大小来进行数据读出,若双方的size不一致时就会使数据包的边界发生错位,导致读出错误的数据分包,进而曲解原始数据含义。
如何解决粘包问题:
vue-cli依托于webpack,因此优化是基于webpack的。
配置某些包使用CDN,主要借助html-webpack-plugin
这个插件以及webpack externals
这个属性。
使用splitChunks进行代码分割:
splitCode
插件所有的库按需引入而不是全局引入
启用gzip
压缩:gzip 是需要服务端配置的,当开启时会压缩我们的线上代码,但是如果我们前端已经使用 gzip 压缩过,那么服务端就会直接使用已经压缩好的代码,就不需要花时间再去压缩了。前端启用 gzip 压缩,使用到的插件是 CompressionWebpackPlugin
;
DllPlugin
插件 抽离第三方库的包,然后通过script 引入 ;
配置webpack
压缩js、css、img
等资源文件,分别有uglifyjs-webpack-plugin
、optimize-css-assets-webpack-plugin
。对图片可以直接用url-loader
或者配合使用image-webpack-loader
插件。
HTTP header 字段中 Accept 表示客户端可支持的数据类型(Content-Type),如text/css, application/json, 这些类型都是以MIME
规格定义的数据类型来表示的, 统称为MIME
类型。
MIME: Multipurpose Internet Mail Extensions
,多用途互联网邮件拓展。常见的MIME
类型:text/plain,text/html,image/jpeg,image/png,audio/mpeg,audio/ogg,audio/*,video/mp4,application/*,application/json。application/javascript,application/ecmascript,application/octet-stream。
MIME
完整列表:https://www.iana.org/assignments/media-types/media-types.xhtml
raycast
射线拾取:是基于几何相交性计算的方式,从鼠标点击的地方,沿着视角方向发射一条射线。通过射线与三维模型的几何香蕉性来判断物体是否被拾取到。THREEJS内置了Raycast
的类,提供一个射线,可以根据不同方向去发射射线,根据射线是否被阻挡来判断是否碰到了物体。
GPU
的拾取方式:一般做法是给每个mesh
一种颜色,然后绘制一遍,在鼠标所在的位置调用readPicel
读取像素颜色,根据颜色和模型的对应关系,反推当前拾取的Mesh
。flex: 1; === flex: 1 1 auto;
首先绝对定位脱离了文档流,它的后面的元素会补它的位置。他会寻找最近的已定位的祖宗元素进行定位,如果没有,那么根据body进行定位。
注意,如果没有写top、bottom、left、right,那么元素会待在他原来的位置。同时有top和bottom时,top的优先级最高,同时有left和right以left优先级高。
JWT是由三段信息构成的,将这三段信息文本用.
链接一起就构成了Jwt字符串。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
JWT的构成:头部(header),载荷(payload),签证(signature)。
头部承载两部分信息:声明类型,声明加密的算法:
{
'typ': 'jwt',
'alg': 'HS256'
}
然后对头部进行base64加密。
payload是存放有效信息的地方:标注中注册的声明,公共的声明,私有的声明:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后用base64加密
signature是签证信息,这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。
CommonJs是被加载的时候运行,esModule是编译的时候运行;
commonJs输出的值是浅拷贝,esModule输出的是引用;
commentJs具有缓存。在第一次被加载时,会完整运行整个文件并输出一个对象,拷贝(浅拷贝)在内存中。下次加载文件时,直接从内存中取值;
一个完整的TCP数据帧通常由以下部分组成:帧头 + 数据 + 校检位 + 帧尾。其中检验位是为了保证数据在传输过程中的完整性,采用一种指定的算法对原始数据进行计算,得出一个校检值。接受方收到数据,采用同样算法对原始数据进行计算,如果计算结果和接收到的校检值一致,说明数据正确,否则说明传输过程中出现了差错,丢弃该帧,请求重发。
常用的校检算法有奇偶校检、检验和、CRC、还有LRC、BCC等不常用的校检算法。
valueOf
toString
TypeError
异常