自从大二初次接触前端以来,一直都有记markdown笔记的习惯.又因为掘金最近有一个活动.所以开了这个专栏。我会写一些业务相关的小技巧和前端知识中的重点内容之类的整理一下发上来。难免有点地方不够细致。欢迎大家指教
这篇文章涵盖了
- 前端竟态问题 | AbortController | abort | promise的取消
- 监听dom元素 | MutationObserver
- arguments
- postmessage | 父子组件
- innerText | textContent | nodeValue
- geo | speech | api 的 使用
- 常用正则
- try catch | settimeout | async 的错误处理和捕获
这些概念的辨析和区别
2.1.31 scolltop | clientheight | offsetheight | IntersectionObserver | clientx是可视坐标,pagex是绝对坐标
怪不得cvte 禁用 scale. scale 会让offsettop失去准度
layout 的尺寸
- clientxx: content + padding
- offsetxx可见尺寸:clientxx + 边框 + 滚动条 | 要是不是尺寸的话.受到 relative、absolute、fixed 的 影响
- scollxx :clientxx + 不可见
draw 的 尺寸
- getBoundclientreact ,得到的是放大 | 旋转 经过了css 的 transform 渲染之后的 尺寸。这里设置了zoom可能会有bug,得到的是放大后的尺寸。但是top什么的会不准确。
ini
1.document.documentElement.clientHeight获取屏幕可视窗口高度。
2. ele.offsetTop 元素相对于文档顶部的距离 //document.querySelector('#user-content').offsetTop
3.document.documentElement.scrollTop 滚动条滚动的距离 通过上面三个能够知道我们我们是否能够看到视图.但是这样子监听会照成回流。(判断元素位置我们可以通过3+1>2)
document.documentElement.clientHeight(可见区域高)+document.documentElement.scrollTop(用户滑动的距离) > 观测元素.offsetTop(元素距离顶部的距离)
4.IntersectionObserver
const io = new IntersectionObserver(ioes => {
ioes.forEach(ioe => {
const el = ioe.target;
const intersectionRatio = ioe.intersectionRatio;
if (intersectionRatio > 0 && intersectionRatio <= 1) {
console.log("能看见元素")
}else{
console.log("看不见")
}
el.onload = el.onerror = () => io.unobserve(el);
});
});
const imgs = Array.from(document.querySelectorAll('#user-content--getboundingclientrect'));
imgs.forEach(item => io.observe(item))
利用offsetTop和scrollTop和浏览器高度做比较 getBoundingClientRect返回相关位置属性
总结一共2个:scrollTop(字面意思) clientTop(局部正常基础少一点东西或者不正常,大局正常) offsetTop(正常)
xml
--1.固定(dom上常用属性)
clientWidth //1.1屏幕(不固定)的宽高
width //1.2屏幕(固定)宽高
scrollTop // 1.3滚动宽高
border-box下面,这三个一样, //1.3元素宽高
offsetHeight(元素本身的宽) | scrollHeight(元素高度-border*2+溢出来的元素高) | clientHeight(元素高度-border*2)
如果要是是content-box//1.3元素宽高
offsetHeight(元素+padding*2+border*2) | scrollHeight(元素高度+padding*2+溢出来的元素高-overflow-y: auto) | clientHeight(元素+padding*2)
//1.4元素距离顶部的距离
offsetTop(正常大全)
clientTop//顶部边框值
scrollTop:内部的滚动效果//document.querySelector(".box").scrollTop=100。(可以用来做页面滚动效果)
--2.事件:
clientX // 2.1以可见区域的左上角为原点
pageX // 2.2以页面本身的body为原点
offsetX(左内边框) | windowX (相对于屏幕)//2.3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<style>
* {
margin: 0;
padding: 0;
}
.container {
column-count: 2;
margin-top: 800px;
}
.box {
/* position: absolute; */
top: 10px;
margin: 10px;
background: red;
width: 100px;
height: 100px;
padding: 20px;
box-sizing: border-box;
word-wrap: break-word;
border: 1px solid black;
padding: 10px;
overflow-y: auto;
}
</style>
<div class="container">
<div class="box"> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<script>
</script>
</body>
</html>
dart
--0.基础知识
document.documentElement:可返回存在于 XML 以及 HTML 文档中的文档根节点(对应的是html标签)
document.body:提供了对 <body> 标签的直接访问(对应的是body标签)
在DTD已声明的情况下用documentElement,未声明的情况下用body
--1.可见区域宽高
document.documentElement.clientWidth; //height + padding + 水平滚动条高度
window.screen.width//屏幕宽度(不受窗口resize事件影响)
document.documentElement.clientHeight; //height + padding + 水平滚动条高度(doc为严格模式下面document.body失效,原因不明) | 考虑用document.documentElement.clientHeight
window.screen.height//屏幕高度(不受窗口resize事件影响)
2.滚动长度:
document.documentElement.scrollTop //严格模式下面用这个
document.body.scrollTop //兼容模式用这个
3.元素宽高
document.querySelector(".box").offsetWidth//获取元素的宽,这里需要注意我们的box-size:box还是content差距是很大的。
4.元素距离顶部距离
document.querySelector(".box").offsetTop//绝对数值
document.documentElement.scrollTop+document.documentElement.clientHeight,document.querySelector(".box").offsetTop
2.1.32 监听dom元素 | MutationObserver
javascript
function callback(mutationList, observer) {
mutationList.forEach((mutation) => {
switch(mutation.type) {
case 'childList':
/* 从树上添加或移除一个或更多的子节点;参见 mutation.addedNodes 与
mutation.removedNodes */
break;
case 'attributes':
/* mutation.target 中某节点的一个属性值被更改;该属性名称在 mutation.attributeName 中,
该属性之前的值为 mutation.oldValue */
break;
}
});
}
var targetNode = document.querySelector("#someElement");
var observerOptions = {
// 观察目标子节点的变化,是否有添加或者删除
childList: true,
// 观察属性变动
attributes: true,
// 观察后代节点,默认为 false
subtree: true
}
var observer = new MutationObserver(callback);
observer.observe(targetNode, observerOptions);
2.1.33 arguments
javascript
arguments默认获取剩下的参数
function fun(age, className) {
console.log(`${this.name}的年龄是${age}岁,是${className}班学生`)
}
箭头函数没有arguements
2.1.35 postmessage
子组件
javascript
let data="data1111111111"
window.postMessage(data,"*") //parent.postmessage vue里面
父组件
javascript
function parent(param){
console.log("测试:",param)
}
window.addEventListener("message",parent)
2.1.37 innerText | textContent | nodeValue
diff
--1.innerText获取可以显示的文本:display:none的不会输出,opacticy为0就是可以被输出。
--2.textContent能够获取所有子节点的文本内容。包括html和script。注意注释获取不到
--3.nodeValue只能是作用于文本节点或者注释节点本点。不然会是null
--4.innertext作用于html element后两个作用于node。
--5.注意一下html中换行和和注释节点也被算做了一个子节点
2.1.38 geo | speech | api
arduino
window.navigator.geolocation (http的定位可能会不准,因此最好是https-ios10)
//翻墙才能用
navigator.geolocation.getCurrentPosition(position => {
console.log('当前位置信息:', position)
})
------------------------------
//定位数据获取成功响应
function onSuccess(position){
alert('纬度: ' + position.coords.latitude + '\n' +
'经度: ' + position.coords.longitude + '\n' +
'海拔: ' + position.coords.altitude + '\n' +
'水平精度: ' + position.coords.accuracy + '\n' +
'垂直精度: ' + position.coords.altitudeAccura)
}
//定位数据获取失败响应
function onError(error) {
switch(error.code)
{
case error.PERMISSION_DENIED:
alert("您拒绝对获取地理位置的请求");
break;
case error.POSITION_UNAVAILABLE:
alert("位置信息是不可用的");
break;
case error.TIMEOUT:
alert("请求您的地理位置超时");
break;
case error.UNKNOWN_ERROR:
alert("未知错误");
break;
}
}
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(onSuccess , onError);
}else{
alert("您的浏览器不支持使用HTML 5来获取地理位置服务");
}
2.1.39 正则
xml
//(.)匹配任意一个 (?)匹配0-1个 *匹配1个以上 \d 匹配单个数字=[0-9]
//手机号 | 1开头+除了1之外的东西+中间9个结尾
const reg = /^[1][3,4,5,6.7,8,9][0-9]{9}$/g;
const reg = /[1][3,4,5,6.7,8,9][0-9]{9}/g;
let text ="我的手机号是19120636253,因此xxxxx/但是他的手机号码是18928125079"
--1.match | 输出匹配的 这玩意和 replace是好用的 text.replace(reg,"替换的内容")
console.log(text.match(reg)) //['19120636253','18928125079']
--2.search | 返回第一个元素位置
console.log(text.match(reg)) //6
--3. test | 看一下有没有符合要求的元素..表单校验的时候可以用
console.log(reg.test(text)) // true
--4.零宽先行 断言 (?=p) 要求与p匹配
//(?=a) 表示我们需要匹配某样东西的前面。 会带着?=一起输出出来,实操体验很差
//(?!a) 表示我们需要不匹配某样东西。
//(?<=a) 表示我们需要匹配某样东西的后面。
//(?<!a) 表示我们需要不匹配某样东西,与(?!a)方向相反。
var reg1 = /(?<=机号是)[0-9]{11}(?=,因)/g
let text ="我的手机号是19120636253,因此xxxxx但是他的手机号是18928125079,因但是,"
console.log(text.match(reg1))
console.log(reg1.exec(text))
var consoleName=["console","window.console"];
var consoleType= ["log", "info", "warn", "error" ,"assert" ,"count" ,"clear"];
//let rConsole = new RegExp("(" + consoleName.join("|") + ")" + ".(?:" + consoleType.join("|") + ")\s{0,}\([^;]*\)(?!\s*[;,]?\s*\/\*\s*NotClearConsole\s*\*\/)\s{0,};?", "gi");
let rConsole = /console.log(.*?)/g
let text ="console.log('ddddd');let a= 1;console.log('ddd')"
console.log(text.match(rConsole))
javascript
// 正则表达式
function getQueryObject(url) {
//假如不传值,默认也会有值
url = url == null ? window.location.href : url
//这一套组合技就是取到最后?后面的值
// url.lastIndexOf('?')找到位置
const search = url.substring(url.lastIndexOf('?') + 1)
const obj = {}
// 3.1 正则表达式 基本形式 /正则表达式主体/修饰符(可选)
// i 大小不那啥 g 全局匹配 不会在匹配一个后就停止
// JavaScript 中,正则表达式通常用于两个字符串方法 :
// search()-并返回子串的起始位置 和 replace()-替换 和 exec也常用
const reg = /([^?&=]+)=/g
// 先行断言 后行:后面的内容应匹配表达式 exp
var reg1 = /(?=三).*(?=b)/
console.log('123一二三abc'.match(reg1))
// 返回三a
console.log(reg1.exec(search))
// reg.exec(search,(rs, $1, $2) => {
// console.log($1, "$1")
// console.log($2, "$2")
// console.log(rs, "rs")
// const name = decodeURIComponent($1)
// let val = decodeURIComponent($2)
// val = String(val)
// obj[name] = val
// return rs
// })
//这样子写可以得到第一个参数匹配的内容
// replace的第一个参数是正则表达式,第二个参数有两种形式,第一种是string,那就是替换了
// 第二种就是传入函数,rs是匹配的内容,$1是第一个括号匹配的内容,$2是第二个括号匹配的内容
// 如果除了这两个参数外还有的话,那么就是offset(匹配到的索引),str(原始字符串)
// reg是正则表达式,传入
search.replace(reg, (rs, $1, $2) => {
console.log($1, "$1")
console.log($2, "$2")
const name = decodeURIComponent($1)
let val = decodeURIComponent($2)
val = String(val)
obj[name] = val
return rs
})
return obj
}
console.log("window.location", getQueryObject())
javascript
2.1.40 正则中使用变量
function count(str,all){
let reg =new RegExp(`${str}`,"g")
let temp = all.match(reg)
return temp
}
2.1.40 一些坑 | try catch | settimeout | async | 赋值
javascript
1.try catch的坑
1.1 setTimeout回调抛出的异常不能被try catch。 因为调用他的catch的settimeout入栈的时候,调用它的函数就是已经出栈了。简单地说setTimeout里的错误被异步抛出的
1.2 async函数里await发生的异常却可以try catch,
1.3 promise 第一层的错误不会冒泡出来,而是被 promise 吃掉了,只有通过 promise.catch 才可以捕获
然后在第二层也就是then里面可以
在第一层 return e 然后在第二层进行拿到值。根据这个东西我们可以解决 1.1的bug。包一层promise来捕获promise的错误
const p3 = () => new Promise((reslove, reject) => {
setTimeout(() => {
reject('async error');
})
});
function main3() {
p3().catch(e => console.log(e));
}
main3();
1.4 async 和 await 的捕获
这玩意能够直接直接捕获
2.从右到左
function display() {
var a = b = 10;
}
display();
/*
function display() {
a = 10 //严格模式下面会报错
var a = 10
}
*/