一、html补充
1、id选择器原则上不能重复,是因为通过getElementById只能获取到第一个,但可以通过querySelectorAll来获取一个数组。id选择器会被挂载到window上,只存在唯一id时,值是单个元素,id重复时,值是数组。
2、移动端点击会有300ms延迟,因为存在双击缩放,所以会在300ms内判断是否是双击,为了解决此问题可以设置user-scalable=no来禁止缩放(网上说该标签只能解决Android端延迟问题,未实际测试)
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
3、为了能够使用es6模块化,需要添加 type="module"
<script type="module">
import xxx from 'xxx.js'
</script>
// 代表将default变量的值赋为1
const a = 1
export default a
4、jsonp跨域,利用script标签的src属性不受浏览器同源策略的影响,该方法需后端配合返回callback(data)的形式。注意,只支持get请求。
<!-- 仅在加载时执行一次 -->
<script src="xxx"></script>
// 回调函数
function test(data) {
console.log(data);
}
// 手动创建执行
const script = document.createElement('script')
script.src = "https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=36543,38092,37907,37990,37800,37926,38087,26350,37957,22160,38009,37881&wd=a&req=2&bs=script%E5%8A%A0%E8%BD%BD%E5%A4%B1%E8%B4%A5%E4%BC%9A%E6%89%A7%E8%A1%8Cload%E4%BA%8B%E4%BB%B6%E5%90%97&pbs=script%E5%8A%A0%E8%BD%BD%E5%A4%B1%E8%B4%A5%E4%BC%9A%E6%89%A7%E8%A1%8Cload%E4%BA%8B%E4%BB%B6%E5%90%97&csor=1&cb=test&_=1675218105457"
script.onload = () => {
// 加载成功后需删除
script.remove()
}
script.onerror = () => {
// 加载失败后逻辑
}
document.body.appendChild(script)
二、css补充
1、元素永远不会成为鼠标事件的target
pointer-events: none;
2、sass、scss与less
SASS版本3.0之前的后缀名为.sass,而版本3.0之后的后缀名.scss。.sass是有严格的缩进规范并且没有{ }和 ' ; ',而.scss则和css的规范是一致的。可以把scss看作sass的升级版本。
less与scss类似,语法稍有不同,且没有if、else语句和for循环等。
3、background复合属性
/* background-origin指定的是背景图片的原点位置,对背景颜色不生效 */
background: url() no-repeat right 32px top 32px/contain padding-box, #C0EB5E;
4、单行或多行文本溢出显示省略号
// 单行
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
// 多行
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
5、文本两端对齐
<div class="root">
<div class="info-title">账户名</div>
<div class="info-title">账号</div>
<div class="info-title">支行地址</div>
<div class="info-title">开户行号</div>
</div>
.info-title {
width: 120px;
height: 40px;
line-height: 40px;
text-align: justify;
text-align-last: justify; // 该行在ios不生效,故使用下面伪元素方案兼容
}
.info-title::after {
display: inline-block;
content: "";
overflow: hidden;
width: 100%;
height: 0;
}
6、告知浏览器哪些属性可能会变化以达到性能优化的目的(尽量不用)
will-change: filter;
7、同时满足选择器才生效
/* 同时携带a与b两个类名 */
.a.b {}
/* div标签 且 携带b类名 */
div.b {}
/* id为a 且 携带b类名 */
#a.b {}
8、伪类选择器
/* 匹配html根元素,优先级更高 */
:root {}
9、border-radius
div {
height: 200px;
width: 200px;
background-color: aqua;
/* 表示左上角被水平半径100、垂直半径200的椭圆切割;其余3角无圆角 */
border-radius: 100px 0 0 0/ 200px 0 0 0;
}
10、长宽都为父元素的50%,利用padding的百分比是根据父元素宽度来的(注意仅垂直方向有效)
div {
width: 50%;
padding: 25% 0;
/* padding-top: 50%; */
background-color: red;
}
11、长英文换行
word-break: break-all; // 放不下就截断
overflow-wrap: anywhere; // 先看下一行是否可以放下,放不下再截断(这玩意兼容性有点差,用break-word代替)
12、字体
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
'Helvetica Neue',
'Segoe UI',
Helvetica,
Arial,
'PingFang SC',
'Microsoft YaHei',
'WenQuanYi Micro Hei',
sans-serif;
三、js基础
1、isNaN不能用来判断是否是非数字,isNaN表示能不能被转化为数字
isNaN(null); // false
isNaN('100'); // false
2、void(expression),执行expression后返回undefined
// a?.name 会被 babel 转换为:
a === null || a === void 0 ? void 0 : a.name
<!-- 以下两种写法都表示什么都不做 -->
<a href="javascript:;">点我</a>
<a href="javascript: void(0);">点我</a>
3、Object.hasOwn() 旨在取代 Object.prototype.hasOwnProperty(),因为它适用于使用 Object.create(null) 创建的对象以及覆盖了继承的 hasOwnProperty() 方法的对象,但是兼容性较差,目前不建议使用。
4、let、const声明的变量不在window上,而是存在于Script域里
作用域链:Block => Local => [ Closure ] => Script => Global
5、正则表达式
// 特性一:懒惰,可以加g变成非懒惰模式
const reg = /\d{3}/
console.log(reg.exec('111-222')); // ['111', index: 0, input: '111-222', groups: undefined]
console.log(reg.exec('111-222')); // ['111', index: 0, input: '111-222', groups: undefined]
const reg2 = /\d{3}/g
console.log(reg2.exec('111-222')); // ['111', index: 0, input: '111-222', groups: undefined]
console.log(reg2.exec('111-222')); // ['222', index: 4, input: '111-222', groups: undefined]
// 特性二:贪婪,可以加?变成非贪婪模式
const reg = /a+/
console.log(reg.exec('aaaaaa')); // ['aaaaaa', index: 0, input: 'aaaaaa', groups: undefined]
const reg2 = /a+?/
console.log(reg2.exec('aaaaaa')); // ['a', index: 0, input: 'aaaaaa', groups: undefined]
/**
* 分组
* 1、捕获型分组 ()
* 2、非捕获型分组 (?:)
* 3、先行断言 (?=)
* 4、先行否定断言 (?!)
* 5、后行断言 (?<=)
* 6、后行否定断言 (?<!)
*/
'1-2'.replace(/(\d)-(\d)/, '0$1-0$2') // 01-02,$1捕获到了1,$2捕获到了2
'1-2'.replace(/(?:\d)-(\d)/, '0$1-0$2') // 02-0$2,$1捕获到了2,$2未捕获
/\d+(?=%)/.exec('1 is 100%') // ['100', index: 5, input: '1 is 100%', groups: undefined]
/\d+(?!%)/.exec('1 is 100%') // ['1', index: 0, input: '1 is 100%', groups: undefined]
// 如何将浮点数点左边的数每三位添加一个逗号,如 12000000.11 转化为『12,000,000.11』?
function format(number) {
return number && number.replace(/(?!^)(?=(\d{3})+\.)/g, ",");
}
6、在ES6中提供了class与extends关键字;在typescript中提供了interface与implements关键字。类不能继承接口,接口不能实现接口和类。
7、Symbol
const sa = Symbol("a");
const sb = Symbol("a");
console.log(sa === sb); // false
const sc = Symbol.for("a");
const sd = Symbol.for("a");
console.log(sc === sd); // true
const obj = {
[sa]: 123,
sa: 789,
};
console.log(obj[sa], obj.sa); // 123 789
四、ts相关
4.1、声明文件
1、三斜线指令
types 用于引用另一个库的声明,而 path 用于引用另一个文件的声明:
/// <reference types="foo" />
/// <reference path="bar.d.ts" />
五、BOM相关
1、浏览器窗口宽度,确切的说是布局视口的宽度(包含滚动条宽度)
window.innerWidth
2、页面被卷起来的高度,window.pageYOffset与window.scrollY均可,但为了跨浏览器兼容,推荐使用pageYOffset,IE<9则两个属性都不支持
// 完整兼容性写法
const scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
3、页面滚动,scroll和scrollTo基本一致,表示滚动到那个位置,scrollBy表示滚动多少距离
window.scrollTo( 0, 1000 );
window.scrollTo({
top: 1000,
behavior: "smooth"
});
4、load 事件在整个页面及所有依赖资源如样式表和图片都已完成加载时触发(即使是异步加载,也需要等待),可以挂载到window、 body、 frame、 frameset、 iframe、 img、 link、 script、 style等节点上;DOMContentLoaded事件在DOM加载完成后立即执行,无需等待样式表、图像和子框架的完全加载,一般挂载到document上,可以冒泡到window上。
// load事件可以通过两种方式挂载
window.addEventListener('load', (event) => {});
window.onload = (event) => { };
// DOMContentLoaded事件只能通过addEventListener挂载
document.addEventListener('DOMContentLoaded',function(e){});
5、location在当前标签页跳转及刷新
// 在新标签页中打开
window.open('https://www.baidu.com')
// 跳转页面且保留历史记录
location.href = 'https://www.baidu.com'
location.assign('https://www.baidu.com')
// 跳转页面,不保留历史
location.replace('https://www.baidu.com')
// 刷新页面,参数为true表示强制刷新
location.reload(boolean)
6、history
// 前进一页
history.forward()
// 后退一页
history.back()
// delta为正,向前移动;为负,向后移动;不传或为0,等同于location.reload()
// location.reload()的兼容性似乎要更高一点点,但差距不大
history.go(delta)
7、navigator
navigator.userAgent // 查看浏览器信息
navigator.sendBeacon() // 主要用于埋点上报
navigator.clipboard // 操作剪切板
// cut copy paste事件有一个 clipboardData 属性也可以访问剪切板
六、DOM相关
1、通过querySelector、querySelectorAll查询元素
// css怎么写,内部就可以怎么写;下面表示选择ul下的类名为item的li元素
document.querySelectorAll('ul li.item')
2、元素的原生属性和自定义属性,均可通过getAttribute来获取
// 自定义属性规范,以data-开头,例:
// <input id="input" type="text" value="123" data-letter="a" />
// 获取所有属性
console.log(input.attributes)
// 原生属性还可以通过 . 来获取
console.log(input.value); // 123
// 自定义属性还可以通过 dataset 来获取
console.log(input.dataset.letter); // a
delete input.dataset.letter // 删除属性
3、操作元素类名,className与classList
// <div id="box" class="item item2 item3">123</div>
box.classList.add("item4"); // 增加类名item4
box.classList.remove("item"); // 删除类名item
box.classList.toggle("item2"); // 切换,如果有item2,则去掉;反之,则增加
4、DOM节点包括元素节点、属性节点、文本节点、注释节点、文档节点document、文档类型节点doctype等
<i>我是i</i>
<div id="box">
123
<p id="child">456</p>
<!-- 789 -->
</div>
// 获取父节点,html元素的parentNode为document
console.log(box.parentNode);
// 获取父元素节点,html元素的parentElement为null,且兼容性比parentNode差一点,所以尽可能使用parentNode
console.log(box.parentElement);
// 获取所有子节点,可以有nodeType属性分辨具体是哪种节点
console.log(box.childNodes); // NodeList(5) [text, p, text, comment, text]
// 获取子元素节点
console.log(box.children); // HTMLCollection [p]
// 获取第一个子节点,最后一个用lastChild
console.log(box.firstChild); // #text
// 获取第一个子元素节点,通过box.children[0]来获取的兼容性更高一点
console.log(box.firstElementChild); // p
// 获取上一个兄弟节点,下一个用nextSibling
console.log(box.previousSibling); // #text
// 获取上一个兄弟元素节点
console.log(box.previousElementSibling); // i
// 创建元素节点
// 创建多个元素时,innerHTML的效率比createElement更高,前提是通过数组push的方式,而不是字符串拼接
const myDiv = document.createElement('div')
// 插入节点,在box的最后插入myDiv,与append类似,但append的兼容性很差
box.appendChild(myDiv)
// 插入到child的前面
box.insertBefore(myDiv, child)
// beforebegin 类似 insertBefore
<p>
// afterbegin
foo
// beforeend 类似 appendChild
</p>
// afterend
insertAdjacentElement(position, element)
/**
* 上面俩方法只能插入节点,若想在react中想插入组件:
* 1、使用 ReactDOM.render(myCmp, target),会完全替换掉target内的内容,该方法在react 18版本已被弃用
* 2、可使用 ReactDOM.createRoot 代替上述方法
* 3、使用 ReactDOM.createPortal(myCmp, target),会往target末尾追加内容;portal节点的冒泡是根据react树来的,而不是根据真实dom树来的
*/
// 删除子节点
box.removeChild(child)
// 删除自己
box.remove()
// 替换节点,用myDiv替换掉child
box.replaceChild(myDiv, child)
// 克隆节点,传入true代表深克隆,不传或者传false代表浅克隆
box.cloneNode([boolean])
5、offsetWidth、offsetHeight表示盒子的实际大小,包含padding和border。offsetParent是一个只读属性,返回一个指向最近的包含该元素的定位元素或者最近的table,td,th , body元素。offsetTop、offsetLeft为只读属性,返回当前元素相对于其 offsetParent 元素的顶部内边距的距离。
6、clientWidth、clientHeight表示盒子内容和padding的大小,不包含border且超出盒子的部分不计算。clientTop、clientLeft表示上、左边框的大小。
7、scrollWidth、scrollHeight表示盒子内容和padding的实际大小,不包含border;scrollTop、scrollLeft表示被卷起来的长度。
8、getBoundingClientRect()返回一个对象,该对象使用 left、top、right、bottom、x、y、width 和 height 这几个以像素为单位的只读属性描述整个矩形的位置和大小。除了 width 和 height 以外的属性是相对于视图窗口的左上角来计算的,包含padding和border。
9、input事件和change事件
DOM 的oninput和onchange: 1、oninput在输入内容的时候,持续调用,通过e.target.value可以持续取值,失去焦点和获取焦点不会被调用。 2、onchange在输入期间不会被调用,在失去焦点且失去焦点时的value与获得焦点时的value不一致(输入内容有变化)的时候才会被调用。
React的onInput和onChange: React依靠了onChange事件实时处理用户输入,所以行为与onInput基本一致。onChange和onInput通过e.target.value和e.currentTarget.value均可以取到值,但在typescript中,onInput的e.target.value会报错:类型“EventTarget”上不存在属性“value”,故一般使用onChange的e.target.value来取值。
10、click事件
// 点击位置到可视窗口左上角的距离
e.clientX
e.clientY
// 点击位置到文档页面左上角的距离
e.pageX
e.pageY
// 点击位置到触发元素(target)左上角的距离,实验属性,可能会有兼容性问题
e.offsetX
e.offsetY
11、事件冒泡是在dom结构上的冒泡,和实际的位置无关。