Web tips
Smooth scroll
const scrollDown = () => {
window.scrollBy({
top: 20,
})
if (keepScroll) {
window.requestAnimationFrame(scrollDown)
}
}
Request header
-
Host 请求的目标服务器域名。未指定端口时,默认
443
(https) 或80
(http)Host: developer.mozilla.org
-
Origin 发送请求的源域名
Origin: https://developer.mozilla.org
-
Referer 发送请求的页面地址(完整或部分地址)
Referer: https://developer.mozilla.org/en-US/docs/Web/JavaScript Referer: https://example.com/page?q=123 Referer: https://example.com/
-
Location 页面重定向的页面地址(绝对或相对地址)。仅用于响应状态为
3xx
或201
Location: /index.html
Use emoji as favicon
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⌛</text></svg>">
Audio
Proxy
Proxy 用来为代理其它对象,便于控制对该对象的读写等基础操作
new Proxy(target, handler)
const target = {
message1: 'Hello',
message2: 'everyone'
}
const handler = {
get: function (target, prop, receiver) {
return 'world'
}
}
const proxy = new Proxy(target, handler)
console.log(proxy.message1) // world
history.pushState
可以手动添加历史记录和状态,用于浏览器的前进和后退
history.pushState(state, title, [, url])
Get selected text
window.getSelection().toString()
动态添加脚本、样式等
const script = document.createElement("script");
script.setAttribute("src", "https://example.com/example.js");
document.body.appendChild(script);
const style = document.createElement("link");
style.setAttribute("href", "https://example.com/example.css");
document.body.appendChild(style);
可折叠元素
<summary>
: The Disclosure Summary element
I have keys but no doors. I have space but no room. You can enter but can’t leave. What am I?
A keyboard.<details>
<summary
>I have keys but no doors. I have space but no room. You can enter but can’t
leave. What am I?</summary
>
A keyboard.
</details>
元素到顶部的距离
offsetTop -> offsetParent
HTMLElement.offsetTop: 元素到父元素(offsetParent)的距离。一般是固定值。
topPos = element.offsetTop;
getBoundingClientRect().top -> viewport
getBoundingClientRect().top 获取元素到 viewport 的距离。随页面滚动而变化。
domRectTop = element.getBoundingClientRect().top;
元素高度
窗口高度
window.innerHeight
设置图片高度
imgDom.height = 200;
普通元素高度
dom.style.height = '50px';
点击选中所有文本
function selectText(containerid) {
if (document.selection) {
// IE
var range = document.body.createTextRange();
range.moveToElementText(document.getElementById(containerid));
range.select();
} else if (window.getSelection) {
var range = document.createRange();
range.selectNode(document.getElementById(containerid));
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
}
asiidoc 文档
与 markdown 类似的文档书写格式,一个例子:https://github.com/billziss-gh/winfsp/blob/master/doc/WinFsp-Tutorial.asciidoc
文件对象转为 base64 字符串
File 是 Blob 的子类,可以使用 FileReader 读取
const getBase64 = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = (error) => {
reject(error);
};
});
};
使用 rel="noopener"
避免target="_blank"
导致的安全问题
问题:a
标签单独使用target="_blank"
属性时,目标网站会获取原网站的权限(window.opener 对象),导致很严重的安全问题。
建议处理方案:使用rel="noopener noreferrer"
<a href="{src}" target="_blank" rel="noopener noreferrer">Out Link</a>
https://mathiasbynens.github.io/rel-noopener 很好地解释了这个问题。
避免表单提交时自动在 URL 上添加问号(?)
假设定义了表单
<form onSubmit={submit}>
...
</form>
在提交响应中需要取消浏览器事件的默认行为
submit = (e) => {
e.preventDefault();
};
DOM 与 string 的相互转换
string to DOM
const parser = new DOMParser();
const dom = parser.parseFromString(text, "text/html");
DOM to string
// whole dom content
const div = document.createElement("div");
console.log(div.outerHTML);
// content inside dom
console.log(node.innerHTML);
WebRTC: 浏览器实时交换数据
自定义请求 header
注意 key 中尽量不要包含下划线。部分服务器出于安全考虑会去掉这些请求头。
获取事件定义时的 DOM
获取事件定义所在的 DOM
event.currentTarget
获取导致事件触发的 DOM
event.target
滑动条实现:input[type="range"]
<input
type="range"
value="1"
min="0.5"
max="10"
className="slide"
id="myRange"
/>
var slider = document.getElementById("myRange");
slider.oninput = function () {
this.value;
};
检查如何移动到当前页面的
performance.navigation.type
// 0: link
// 1: reload
// 2: back_forward
// 255: other
Sticky 失效问题
经常是由于父元素包含滚动样式(例如设置了样式 overflow: scroll)导致的。可以取消父元素的滚动,改为监听 window 的滚动。
事件捕获和冒泡
DOM 事件流传递有两种模型,捕获(capture):父元素到子元素;冒泡(bubble):子元素到父元素。现行标准中,由目标元素(子元素)触发的完整的事件流包含先捕获后冒泡两个阶段,即父 ->(捕获) 子 ->(冒泡) 父
。
使用addEventListener
的第三个参数可以指定是否在捕获阶段触发事件(默认冒泡)。如果指定为捕获阶段,可以达到比默认冒泡提前触发响应事件的效果。
使用stopPropagation
可以阻止事件继续传递。
最内部的子元素定义多个事件时按注册顺序触发。
<div id="div1">
div1
<div id="div2">div2</div>
</div>
<script>
document.getElementById("div1").addEventListener(
"click",
function (e) {
console.log("click div1 at capture");
},
true
);
document.getElementById("div2").addEventListener(
"click",
function (e) {
console.log("click div2 at capture");
},
true
);
document.getElementById("div1").addEventListener("click", function (e) {
console.log("click div1 at bubble");
});
document.getElementById("div2").addEventListener("click", function (e) {
console.log("click div2 at bubble");
});
</script>
点击div1
后的 console
click div1 at capture
click div2 at capture
click div2 at bubble
click div1 at bubble
table 设置列宽度
设置 table-layout 属性为 fixed
.table-fixed {
table-layout: fixed;
}
.table-fixed th.small {
width: 30%;
}
.table-fixed td {
word-wrap: break-word;
}
显示任意 Unicode
☺ 对应编码:U+263A
👏 对应编码:U+1F44F
HTML 直接展示
<span>☺</span>
JavaScript 处理后展示
// 0xFFFF 以下 (16-bits)
String.fromCharCode(0x263a);
// 所有 Unicode (21 bits)
String.fromCodePoint(0x1f44f);
table-layout
指定 table 中 cells, rows, columns 的布局
auto: cells 的宽度会适应内部的内容 fix: cells 的宽度由第一行的 cells 决定
table {
table-layout: fixed;
width: 100px;
}
viewport
将移动设备上浏览器默认宽度设置为屏幕宽度。(默认会大于屏幕宽度)
<meta name="viewport" content="width=device-width, initial-scale=1" />
<a>
下载链接
<a href="path/to/file.ext" download="filename">Downalod Link</a>
<ruby>
元素,添加上标
<ruby>
汉 <rp>(</rp><rt>Han</rt><rp>)</rp> 字 <rp>(</rp><rt>zi</rt><rp>)</rp>
</ruby>
汉
字
input(type=number) 输入小数
input(type="number") 输入类型为数值。可以设置最小最大值。容易被忽视的一点是,通过修改 step 可以输入小数(float)。
下面例子中,允许输入最小 0.1,最大 10,间隔为 0.1 的数值。
<input type="number" step="0.1" min="0" max="10" />