第九步:web-js
web-js
1、script
- script标签用在html文件中,包涵javascript脚本语言的标签
- 属性值:
- [async]:异步加载脚本文件,但不会阻塞其他文件
- [defer]:延迟执行,等待其他资源加载绘制完成后,才开始执行
- [src]:执行外部链接的JavaScript脚本文件
2、BOM
1、全局变量
全局变量window,或者globalThis。
window === globalThis
- 所有在全局作用域下的,没有被包裹的,方法和变量都会添加到全局对象下面
- window.open([url], [name], [spces]):打开一个新的页面窗口,地址可选
window.open("", "", "width=100, height=100")
- url:打开窗口的地址,没有则打开新页面
- name:窗口名称,没有设置则会同窗口打开新页面,有设置这回打开新窗口新页面
- spces:窗口的属性
height=100,width=100;
- height:窗口高度
- width:窗口宽度
- left:窗口的left
- top:窗口的top
- fullscreen:是否窗口最大化
- location:是否显示地址栏
- Menubar:是否显示菜单栏
- resizable:是否可拖动调节窗口大小
- scrollbars:是否显示滚动条
- status:是否显示状态栏
- toolbar:是否显示工具栏
- window.document:返回页面的文档对象
- window.close():关闭窗口
2、浏览器大小
- window.screenLeft:浏览器窗口在电脑屏幕中,距离屏幕左侧的距离
- window.screenTop:浏览器窗口在电脑屏幕中,距离屏幕上侧的距离
- window.devicePixelRatio:浏览器的dpr
- window.outerWidth:浏览器窗口的宽度
- window.outerHeight:浏览器窗口的高度
- window.innerWidth:浏览器视口的宽度
- window.innerHeight:浏览器视口的高度
- document.documentElement.clientWidth:浏览器视口的宽度
- document.documentElement.clientHeight:浏览器视口的高度
- 滚动:视口应是没有滚动的,滚动的是里面的元素。例如body的滚动,div的滚动
3、定时器
- setTimeout(callback, delay, [args]):一定时间后执行某些代码,返回一个时间ID
- setInterval(callback, delay, [args]):每隔一段时间执行某些代码,返回一个时间ID
- clearTimeout(时间id);取消定时器
4、系统对话框
- alert(msg):弹窗显示
- confirm(msg):判断弹窗,返回输入的true或false
- prompt(msg):输入弹窗,返回输入的内容
5、location对象
处理url的信息
- location:读取url的信息对象
- localtion.*:读取信息对象的值
hash、host、hostname、href、pathname、port、protocol、search、
username、password、origin
- URLSearchParams:构建解析query
- let qs = new URLSearchParams(query)
- qs.has(key):判断是否还有key
- qs.get(key):获取key的值
- qs.set(key, value):设置key的值
- qs.delete(key):删除key
- qs.toString():输入字符串
- location.assign(url):跳转到url页面
- location.replace(url):跳转到url页面,且刷新history
- location.reload():刷新当前页面
- location.reload(true):重新从服务器加载,刷新当前页面
- location.toString():返回url字符串
6、history对象
- 历史跳转数:
const length = history.length
; - 返回上一个历史:
history.back()
; - 返回下一个历史:
history.forward()
; - 返回多个历史:
history.go(-2)
; // 后退两页,正数为前进,url为到指定url
7、navigator对象
- navigator.webdriver:是否被自动化控制
- navigator.userAgent:浏览器信息
- navigator.cookieEnable:是否支持cookies
- navigator.onLine:是否联网
- navigator.languages:用户偏好语言
- navigator.clipboard.readText():返回Promise对象,读取剪贴板内容
- navigator.clipboard.writeText():返回Promise对象,向剪贴板写入内容
- navigator.mediaDevices.getDisplayMedia(options):返回一个Promise,共享屏幕或窗口的内容。
- video: true 表示请求视频流。
- audio: true 表示请求音频流。
- navigator.mediaDevices.getUserMedia(options):返回一个Promise,请求用户媒体设备。
- video: true 表示请求视频流。
- audio: true 表示请求音频流。
- MediaStream 对象表示媒体流,它可以包含音频和视频轨道。上面两个方法返回的都是MediaStream对象。
3、DOM
1、获取元素节点
- document.write(“字符串”);直接设置文档流内的所有内容
- document.documentElement:读取html元素信息
- document.head:读取head元素信息
- document.title:读取title元素信息
- document.body:读取body元素信息
- document.getElementById(“id”); 通过id获取元素
- document.getElementByClassName(“className”); 通过class获取元素
- document.getElementByTagName(“tagName”); 通过标签获取元素
- document.querySelector(“css选择器”);通过css选择器获取匹配的第一个元素
- document.querySelectorAll(“css选择器”);通过css选择器获取匹配的所有元素,返回伪数组
- 伪数组转数组:let arr = Array.from(伪数组)
2、节点位置
内容位置读取不受border-box的样式影响
- node.clientHeight:读取节点内容高度,包含上下padding,内容宽度
- node.clientWidth:读取节点内容宽度,包含左右padding,内容高度
- node.clientTop:读取节点border-top宽度
- node.clientLeft:读取节点border-left宽度
- node.offsetHeight:读取节点总高度,包含内容高度,上下padding,上下border
- node.offsetWidth:读取节点总宽度,包含内容宽度,左右padding,左右border
- node.offsetTop:读取节点 到 父节点 top距离
- node.offsetLeft:读取节点 到 父节点 left距离
元素设置overflow: scroll之后,通过scrollHeight获取真实内容高度
- node.scrollHeight:获取节点总高度
- node.scrollWidth:获取节点总宽度
- node.scrollTop:获取节点下滑距离
- node.scrollLeft:获取节点右滑距离
3、节点属性
- node.id:读取节点id
- node.className:读取节点className
- node.classList:读取节点className,返回数组
- node.getAttribute(key):获取节点 行内设置 的属性值
- node.setAttribute(key, value):设置节点 行内设置 的属性值
- node.removeAttribute(key):删除节点 行内设置 的属性值
- getComputedStyle(node):获取节点的css样式对象
- node.style.* = value; 设置节点的css行内样式
- node.dataset.* :读取节点设置的
data-*
- node.disabled:节点是否可操作
- node.hidden:节点是否显示,本质还是在控制display的样式
4、节点内容
- node.innerText:读写节点的内容
- node.innerHTML:读写节点的内容,包含子节点
- node.value:读写可输入节点的内容
- node.checked:读写 选择节点 的是否选中
- node.files:读取input上传的文件列表
5、节点方法
- node.scroll(x, y):设置节点的滚动位置
- node.scroll(options):设置节点滚动位置和滚动行为
- top:下滑距离
- left:右滑距离
- behavior:[auto,smooth平滑滚动]
- node.querySelect(“css选择器”)
- node.querySelectAll(“css选择器”)
- node.scrollIntoView(options):滑动父节点,让node节点显示
- behavior:[auto,smooth平滑滚动]
- block:水平方向对齐,[start顶部对齐,center中心对齐,end底部对齐]
- inline:垂直方向对齐,[start顶部对齐,center中心对齐,end底部对齐]
6、节点关系
- node.childElementCount:读取子节点数量
- node.children:读取所有子节点,包含文本节点
- node.childNodes:读取所有元素子节点
- node.firstChild:读取第一个子节点
- node.firstElementChild:读取第一个元素子节点
- node.lastChild:读取最后一个字节但
- node.lastElementChild:读取最后一个子节点
- node.parentNode:读取父节点
- node.parentElement:读取元素父节点
- node.previousSibling:读取上一个节点
- node.previousElementSibling:读取上一个元素节点
- node.nextSibling:读取下一个节点
- node.nextElementSibling:读取下一个元素节点
7、创建节点
- document.createElement(tagName):创建并返回一个新元素节点
- document.createTextNode(text):创建并返回一个新文字节点
- node.cloneNode([boolean]):复制node节点
- true:复制node全部节点,包含子节点
- false:仅复制node节点
- node.remove():节点删除自身
8、增删改
- node.appendChild(childNode):node元素节点从尾部新增一个childNode节点
- node.insertBefore(new, search):node节点中,在search前面插入new
- node.insertAfter(new, search):node节点中,在search后面插入new
- node.removeChild(childNode):node节点删除childNode子节点
- node.replaceChild(new, old):node节点中,new节点替换old节点
- node.innerHTML = “”:清空node节点
4、事件
1、事件绑定
- node.onclick = fn;
- node.addEventListener(type, fn, [options])
- type:事件类型
- fn:监听执行函数
- options
- capture:是否捕获阶段触发事件处理函数
- once:是否只触发一次
- passive:是否阻止默认行为,但不阻止滚动事件冒泡
2、事件解绑
- node.onclick = null;
- node.removeEventListener(type, fn, [options])
- fn必须和绑定的fn一致,才能解除绑定
3、事件冒泡
- 事件的机制是先捕获,到达目标,然后冒泡。
- 先捕获:先从html一级一级向下寻找,直到找到触发元素
- 触发元素会执行绑定事件的函数
- 冒泡:执行完成后,会查询上一级的父元素
- 如果上一级父元素有相同的监听事件,则执行父元素的绑定事件的函数
- 一级一级向上执行,就是事件冒泡。
点击子元素,那么也会点击父元素,毕竟父元素包裹子元素。
4、鼠标事件
- node.onclick = fn;鼠标点击
- node.ondblclick = fn; 鼠标双击
- node.oncontextmenu = fn;鼠标右击
- node.onmousemove = fn;鼠标移动
- node.onmousedown = fn;鼠标按下
- node.onmouseup = fn;鼠标弹起
- node.onmousewhell = fn; 鼠标滚轮事件
- 鼠标移入
- node.onmouseenter;
- node.onmouseover;
- 鼠标移出
- node.onmouseleave;
- node.onmouseout;
- 鼠标直接进入子元素,此时鼠标也进入了父元素。
- 此时如果绑定的是onmouseover,会判断为只进入子元素,只会触发子元素的,父元素的事件会由冒泡触发
- 但如果绑定的是onmouseenter,会判断为进入子元素,也进入父元素。会先触发父元素,然后触发子元素,但不会再冒泡
- 鼠标移出同理
4、键盘事件
- node.onkeypress = fn;键盘敲击
- node.onkeydown = fn;键盘按下
- node.onkeyup = fn;键盘弹起
5、输入事件
- node.onfocus = fn;获取焦点事件
- node.onblur = fn;失去焦点事件
- node.submit = fn;敲击回车事件
- node.onchange = fn;内容发生变化事件
- node.oninput = fn;内容输入事件
- node.oninvalid = fn;验证失败事件
6、滚动事件
- node.onscroll = fn;
7、其他事件
- window.onload = fn;加载完成,最后执行
- window.onunload = fn;浏览器关闭后执行
- window.onresize = fn;窗口大小变化事件
- node.oncopy = fn;复制事件
- node.onpaste = fn;粘贴事件
8、事件对象
- 事件函数的this,指向监听节点元素
- 事件函数默认会有一个事件对象参数,包含事件的信息
e.stopPropagation()
:阻止事件冒泡e.preventDefault()
:阻止默认事件
e.target
:获取触发的准确元素对象e.key
:获取键盘按键e.keyCode
:获取键盘按键的编码e.target.value
:元素对象的输入值e.target.checked
:元素对象的选择值,是否选中,布尔值
e.screenX
:鼠标相对于电脑屏幕的x位置e.screenY
:鼠标相对于电脑屏幕的y位置e.pageX
:鼠标相对于可视区的x位置e.pageY
:鼠标相对于可视区的y位置e.clientX
:鼠标相对于盒子的x位置e.clientY
:鼠标相对于盒子的y位置
9、事件委托
10、事件触发
- node.click():触发节点的点击事件
- node.focus():触发节点的聚焦事件
- node.scroll(x, y):触发节点的滚动事件,并设置滚动位置
6、本地存储
1、cookie
-
浏览器刷新就会失效
-
由于
cookie
操作困难,所以MDN提供了一种封装,方便cookie操作export class DocCookies { static getItem(sKey) { return ( decodeURIComponent( document.cookie.replace( new RegExp( "(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$" ), "$1" ) ) || null ); } /** * 设置一个cookie * * @param {string} sKey cookie的键名 * @param {string} sValue cookie的值 * @param {number|string|Date} vEnd cookie的过期时间,可以为数字(秒),字符串(日期格式),或者Date对象 * @param {string} sPath cookie的路径 * @param {string} sDomain cookie的域名 * @param {boolean} bSecure 是否为安全cookie * @returns {boolean} 设置成功返回true,否则返回false */ static setItem(sKey, sValue, vEnd, sPath, sDomain, bSecure) { if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; } var sExpires = ""; if (vEnd) { switch (vEnd.constructor) { case Number: sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd; break; case String: sExpires = "; expires=" + vEnd; break; case Date: sExpires = "; expires=" + vEnd.toUTCString(); break; } } document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : ""); return true; } static removeItem(sKey, sPath, sDomain) { if (!sKey || !this.hasItem(sKey)) { return false; } document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : ""); return true; } static hasItem(sKey) { return new RegExp( "(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") + "\\s*\\=" ).test(document.cookie); } static keys() { var aKeys = document.cookie .replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "") .split(/\s*(?:\=[^;]*)?;\s*/); for (var nIdx = 0; nIdx < aKeys.length; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); } return aKeys; } static clear() { document.cookie = ""; } }
-
DocCookies.getItem(key):获取key键对应的值
-
DocCookies.setItem(key, value, [end], [path], [domain], [secure]):设置key的值
-
DocCookies.removeItem(key, [path], domain):删除key键
-
DocCookie.hasItem(key):判断cookie是否含有key键
-
DocCookie.keys():返回数组,所有的key键
-
DocCookie.clear():清空所有值
2、sessionStorage
- 浏览器刷新不会失效,关闭时才会失效
- sessionStorage.getItem(key):获取key键对应的值
- sessionStorage.setItem(key, value):设置key键的值
- sessionStorage.removeItem(key):删除key键
- sessionStorage.clear():清空所有值
3、localStorage
- 浏览器刷新不消失,关闭不消失,只能手动清除
- localStorage.getItem(key):获取key键对应的值
- localStorage.setItem(key, value):设置key键的值
- localStorage.removeItem(key):删除key键
- localStorage.clear():清空所有值
7、JSApi
1、formdata
-
let formdata = new formData(obj);实例化formdata数据
-
formdata.append(key, value);添加key的值为value
-
给一个key添加多个值
for (let i = 0; i < files.length; i++) { formdata.append("file", files[i]); }
-
formdata.delete(key):删除key键
-
formdata.get(key):获取key键
-
formdata.set(key, value):修改key键的值
-
formdata.forEach((v, k) => {}):遍历
-
formdata.has(key):检测是否有key
2、fileApi
node.files
:读取文件列表- file.name:文件名称
- file.size:文件字节大小
- file.type:文件类型
- File继承Blob,也有Blob的截取方法slice
3、blobApi
- Blob:二进制大对象,里面可以存储大量的二进制编码格式的数据,Blob对象不可修改,从Blob中读取内容的唯一方式是使用FileReader
- let blob = new Blob(array, option):创建blob对象
- array:由ArrayBuffer,ArrayBufferView,Blob,DOMString等对象组成
- options
- type:文件类型
- endings:编码方式,不常用
文件MIME类型 | 描述 |
---|---|
text/plain | 纯文本文档 |
text/html | HTML文档 |
text/Javascript | Javascript文件 |
text/css | css文件 |
application/json | JSON文件 |
application/pdf | PDF文件 |
application/xml | XML文件 |
image/jpeg | JPEG图像 |
image/png | PNG图形 |
image/gif | GIF图像 |
image/svg+xml | SVG图像 |
audio/mpeg | MP3文件 |
video/mpeg | MP4文件 |
- blob.slice(start, end[, type]):分片,截取
- start:开始位置
- end:结束位置,不包含end
- type:文件类型,没有就是blob的原始值
3、fileReader
-
专门用于读取blob、file类型的api
-
let reader = new FileReader();实例化对象
-
reader.readAsArrayBuffer(blob):读取blob,结果返回一个ArrayBuffer对象
-
reader.readAsBinaryString(blob):读取blob,结果返回一个二进制字符串
-
reader.readAsText(blob):读取blob,结果返回一个文本字符串
-
reader.readAsDataURL(blob):读取blob,返回一个64位的URL字符串,可以直接给img的src用
-
获取结果
reader.onload = function(e) { console.log(e.target.result); // 获取到读取的结果 }
4、ObjectUrl
- URL.createObjectURL(blob):读取blob,返回一个链接,可以直接给img的src用
- URL.revokeObjectURL(url):释放URL
8、请求与资源
1、fetch
- fetch(url, options):发送请求,返回一个promise对象,包含请求结果
- url:请求地址
- options:配置
- method:请求方式,默认为GET,[GET, POST, DELETE, PUT]
- body:请求的数据,字符串格式,或者formdata
- header:请求头
- post请求,发送json数据时
- body的数据需要转换为字符串
- 请求头contentType的值需要设置为
application/json
- 结果:
- res.json():结果转换为json格式,返回一个promise对象
- res.text():结果转换为文本格式,返回一个promise对象
- res.blob():结果转换为二进制大对象,返回一个promise对象
- res.arrayBuffer():结果转换为二进制,返回一个promise对象
- res.status:响应状态码
- res.headers:响应头
-
单文件上传
let file = input.files[0]; let fromdata = new FormData(); formdata.append("file", file); fetch(url, { method: "POST", body: formdata, }) .then(res => res.json()) .then(res => console.log(res));
-
多文件上传
let files = input.files; let fromdata = new FormData(); for (let i = 0; i < files.length; i++) { formdata.append("files", files[i]); } fetch(url, { method: "POST", body: formdata, }) .then(res => res.json()) .then(res => console.log(res));
-
大文件上传
let file = input.files[0]; let filename = file.name; let filetype = file.type; let chunks = []; let size = 1024 * 1024 * 4; // 每4m一片 for (let i = 0; i < file.size; i+= size) { chunks.push(file.slice(i, i+size)); } let appList = []; chunks.forEach((chunk, index) => { let formdata = new FromData(); formData.append("index", index); formData.append("file", chunk); appList.push( fetch(url, { method: "POST", body: formdata }); ) }) Promise.all(appList).then(() => { fetch(url, { method: "POST", contentType: "application/json", body: JSON.stringify({ filename, filetype }) }) })
-
文件下载
fetch(url) .then(res => res.blob()) .then(blob => { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = '图片.png'; a.click(); URL.revokeObjectURL(url); a.remove(); })
2、web-socket
- let socketlint = new WebSocket(url);创建websocket链接对象
- socketlint.send(data):发送消息
- socketlint.onmessage = (e) => { let data = e.data }:接收消息
- 注意:发送和接收的消息都是字符串,所有需要JSON.stringify和JSON.parse进行处理
- 注意:由于发送和接收过于灵活,所有要和后端进行沟通,如何处理消息
- 注意:需要有聊天室,或者频道的概念。
10、原生拖放
1、需要拖动的元素draggable
-
需要拖动的元素设置
draggable="true"
-
绑定
drag
事件:ondrag="handleDrag"
-
或者绑定
dragstart
事件:和上面的事件一样上面两个事件对象都含有拖放独特的
api
-
dataTransfer
用来存放拖放时存储的值
拖放容器无法获取拖放的元素信息,所有需要通过事件值传递获取
e.dataTransfer.setData('text/plain', e.target.id)
2、放置容器droppable
-
添加
dragover
事件:ondragover="handleDragover"
-
添加
drop
事件:ondrop="handleDrop"
-
两个事件处理函数都要阻止默认事件
e.preventDefault()
浏览器默认是不允许拖放的
-
在
drop
事件里使用dataTransfer
获取传递值let id = e.dataTransfer.getData('text/plain')
- 然后再通过id获取当前拖拽元素,并添加到容器中
droppable.appendChild(document.getElementById(draggedId));
3、事件解释
drag
:拖拽开始时触发的事件dragstart
:和上面事件同理dragover
:拖拽移入容器区域触发事件dragleave
:拖拽移出容器区域触发事件drop
:放入容器时触发事件dataTransfer
:拖拽事件对象特殊api,用于数据传递
4、教程链接:https://www.bilibili.com/video/BV1i5411E7hk
<body>
<div class="logo" id="logo"></div>
<div class="box" id="box" ondrop="drop(event)"></div>
<script>
var logoDom = document.querySelector('.logo')
logoDom.draggable = true
// logoDom.ondragstart = function (event) {
// event.dataTransfer.setData("Text", event.target.id);
// }
var boxDom = document.querySelector(".box")
boxDom.ondragover = function(event) {
event.preventDefault();
}
boxDom.ondrop = function(event) {
event.preventDefault();
// var data = event.dataTransfer.getData("Text");
// event.target.appendChild(document.getElementById(data));
boxDom.appendChild(logoDom);
}
</script>
</body>
11、多线程
1、主线程
- let worker = new Worker(“js文件路径”):创建子线程
- worker.postMessage(data):给子线程发送消息
- worker.onmessage = (e) => { let data = e.data }:接受子线程的消息
- worker.onerror = (error) => {}:接受子线程出现的错误
- worker.terminate():主动关闭子线程
2、子线程
- 子线程的js文件中,主作用域会有一个self的全局遍历
- self.postMessage(data):给主线程发送消息
- self.onmessage = (e) => { let data = e.data }:接受主线程的消息
- self.close():子线程主动关闭
12、调试
- console.log():页面输出
- debugger:代码断点,只有在打开控制台时,debugger才会生效
- navigator.webdriver:可以判断是否被自动化控制,进行网页安全拦截
13、浏览器渲染
1、获取文档
- url进行dns解析,获取服务器地址
- 请求服务器,获取html文档
2、加载文档
- 浏览器解析html文档,根据从左到右,从上到下,生成DOM树。
- 浏览器解析css文档,生成CSSOM树
- 浏览器将DOM树和CSSOM树结合,构建渲染树。渲染树会过滤掉display:none的节点
- 浏览器根据渲染树,开始进行布局,此时页面还处于不可见状态
- 浏览器根据布局进行绘制,生成可见的页面
14、浏览器缓存
- 浏览器会根据响应头的
cache-control
判断是否缓存,如何缓存 cache-control: no-cache
:此时为协商缓存,不使用本地缓存cache-control: no-store
:禁止浏览器缓存cache-control: public
:可以被所有用户端缓存cache-control: private
:只能被终端用户浏览器缓存cache-control: max-age=300
:强行缓存5分钟
- 强缓存:一段时间内,浏览器请求只会从缓存中获取数据
- 协商缓存1:(根据文件时间判断)
- 请求时,请求头会携带 第一次响应时响应头的Last-Modify的值,放在if-Modify-Since里
- 服务器会根据文件修改时间,和请求头里的if-Modify-Since的值进行比较
- 如果比较一致,返回304。浏览器就会从缓存中获取数据
- 如果不一致,就会返回数据,浏览器就会刷新缓存中的数据
- 协商缓存2:(根据文件内容判断)
- 请求时,请求头会携带 第一次响应时响应头的ETag的值,放在if-None-Match里
- 服务器会根据文件唯一标识,和请求头里的if-None-Match的值进行比较
- 如果比较一致,返回304。浏览器就会从缓存中获取数据
- 如果不一致,就会返回数据,浏览器就会刷新缓存中的数据
15、加密
1、公钥加密
2、md5加密
- 使用插件
md5
进行hash不可逆加密 md5(password)
:完成加密
16、屏
1、开启全屏
function launchFullscreen() {
let element = document.documentElement;
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
}
}
2、关闭全屏
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
3、适配
适配就是预设Npx = 1rem。然后动态设置html的字体大小。保持比例不变
- 1920 * 1080 的屏幕大小
- 1920px = 100vw
- 1080px = 100vh
- 100px = 5.21vw
- 预设 100px = 1rem;
- 所以 html的字体大小 = (显示区大小 / 设计稿1920) * 预设100
- 其他元素的就可以换算rem设置尺寸
- 优点:精确,兼容,便于调整预设
- 缺点:性能消耗,页面卡顿
- 预设 100px = 1rem
- 所以 html的字体大小 = 5.21vw
- 其他元素的就可以换算rem设置尺寸
- 优点:页面流畅,能够配合响应式布局
- 缺点:不精确,不兼容,预设固定
- 自动将px转换为rem的插件:
postcss-pxtorem
- rootValue:px转换rem的除数,也就是rem的预设
- unitPrecision:精度
- propList:需要处理哪些属性,建议为
['*']
,转换所有 - replace:是否直接更换属性值,而不是添加备用属性
- selectorBlackList:不进行px转换的css选择器,建议
['ignore']
- mediaQuery: 是否在媒体查询的css代码中也进行转换
- minPixelValue:设置要替换的最小像素值,默认为0
- exclude:哪些文件不进行转换,建议
/node_modules/i
,排除node_modules文件
4、截屏
-
使用插件
dom-to-image
-
截图并显示
let node = document.getElementById("my-node"); let img = document.getElementById("my-img"); domtoimage.toPng(node).then((url) => { img.src = url; })
-
截图并保存
let node = document.getElementById("my-node"); domtoimage.toBlob(node).then((blob) => { let url = URL.createObjectURL(blob); let a = document.createElement("a"); a.href = url; a.download = "截图保存.png"; a.click(); URL.revokeObjectURL(url); a.remove(); })
-
截图压缩并保存
let node = document.getElementById("my-node"); domtoimage.toJpeg(node).then((url) => { let a = document.createElement("a"); a.href = url; a.download = "截图保存.jpeg"; a.click(); URL.revokeObjectURL(url); a.remove(); })
17、录制
1、屏幕录制
- 使用
navigator.mediaDevices.getDisplayMedia
开启屏幕共享 stream.clone()
:关闭流stream.getTracks()
:获取tracks流
-
使用
MediaRecorder
实例化录制对象 -
mediaRecorder.ondataavailable
:监听开始录制 -
mediaRecorder.onstop
:监听结束录制,能够监听stop,也能监听流关闭 -
mediaRecorder.start()
:开启录制 -
mediaRecorder.stop()
:手动结束录制
// 开启录制
async function recordScreenStart(camera = false) {
let api = camera ? "getUserMedia" : "getDisplayMedia";
// 获取分享流
let stream = await navigator.mediaDevices[api]({ video: true });
// 录制视频流
const mediaRecorder = new MediaRecorder(stream, {
mimeType: "video/webm; codecs=vp9",
});
// 录制视频流的数据可用事件处理函数
const chunks = [];
mediaRecorder.ondataavailable = function (e) {
chunks.push(e.data);
};
// 录制视频流结束事件处理函数
mediaRecorder.onstop = function () {
const blob = new Blob(chunks, { type: "video/webm; codecs=vp9" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "video.webm";
a.click();
URL.revokeObjectURL(url);
a.remove();
};
// 开始录制视频流
mediaRecorder.start();
return stream;
}
// 结束录制
function recordScreenStop(stream) {
stream.getTracks().forEach((track) => track.stop());
}
2、视频录制
- 使用
navigator.mediaDevices.getUserMedia
- 然后和上面一样
3、拍照
-
需要canvas去绘制图片
let video = document.getElementById(".video"); async function camera() { let stream = await navigator.mediaDevices.getUserMedia({ video: true }); video.srcObject = stream; video.onloadedmetadata = () => { video.play(); // 创建canvas,并绘制图片 let canvas = document.createElement("canvas"); canvas.width = 600; canvas.height = 337.5; let ctx = canvas.getContext("2d"); ctx.drawImage(video, 0, 0, canvas.width, canvas.height); let url = canvas.toDataURL("image/png"); // 下载图片 let a = document.createElement("a"); a.href = url; a.download = "photo.png"; a.click(); // 删除元素 a.remove(); canvas.remove(); // 结束录制 video.srcObject = null; video.pause(); stream.active = false; stream.clone(); }; }
18、其他
1、软件调用
- 首先需要外部软件应用的支持,外部软件必须在系统中有注册,否则无法调用
- 软件调用其实就是一个a标签的超链接跳转
- 如果打开某个pdf,就是
file://path/xxx.pdf
- 打开vscode,就是
vscode://open/
- 打开其他软件,就需要其他软件的支持,但基本都是
xxx://open/
- 手机浏览器的调试框,使用
vconsole
插件 - script引入vconsole插件后,在使用
let vconsole = new VConsole()
- 此时就打开了一个调试框
2、二维码
- 使用插件
qrcode
- 生成图片链接:
const imgsrc = await qrcode.toDataURL(url)
- 渲染到canvas:
qrcode.toCanvas(canvasnode, url, fn(err) => {})