当前位置: 首页 > news >正文

第九步: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;
      1. height:窗口高度
      2. width:窗口宽度
      3. left:窗口的left
      4. top:窗口的top
      5. fullscreen:是否窗口最大化
      6. location:是否显示地址栏
      7. Menubar:是否显示菜单栏
      8. resizable:是否可拖动调节窗口大小
      9. scrollbars:是否显示滚动条
      10. status:是否显示状态栏
      11. 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对象

  1. 历史跳转数:const length = history.length;
  2. 返回上一个历史:history.back();
  3. 返回下一个历史:history.forward();
  4. 返回多个历史: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;

  1. 鼠标直接进入子元素,此时鼠标也进入了父元素。
  2. 此时如果绑定的是onmouseover,会判断为只进入子元素,只会触发子元素的,父元素的事件会由冒泡触发
  3. 但如果绑定的是onmouseenter,会判断为进入子元素,也进入父元素。会先触发父元素,然后触发子元素,但不会再冒泡
  4. 鼠标移出同理

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/htmlHTML文档
text/JavascriptJavascript文件
text/csscss文件
application/jsonJSON文件
application/pdfPDF文件
application/xmlXML文件
image/jpegJPEG图像
image/pngPNG图形
image/gifGIF图像
image/svg+xmlSVG图像
audio/mpegMP3文件
video/mpegMP4文件
  • 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获取传递值

    1. let id = e.dataTransfer.getData('text/plain')
    2. 然后再通过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、调试

  1. console.log():页面输出
  2. debugger:代码断点,只有在打开控制台时,debugger才会生效
  3. navigator.webdriver:可以判断是否被自动化控制,进行网页安全拦截

13、浏览器渲染

1、获取文档

  1. url进行dns解析,获取服务器地址
  2. 请求服务器,获取html文档

2、加载文档

  1. 浏览器解析html文档,根据从左到右,从上到下,生成DOM树。
  2. 浏览器解析css文档,生成CSSOM树
  3. 浏览器将DOM树和CSSOM树结合,构建渲染树。渲染树会过滤掉display:none的节点
  4. 浏览器根据渲染树,开始进行布局,此时页面还处于不可见状态
  5. 浏览器根据布局进行绘制,生成可见的页面

14、浏览器缓存

  1. 浏览器会根据响应头的cache-control判断是否缓存,如何缓存
  2. cache-control: no-cache:此时为协商缓存,不使用本地缓存
  3. cache-control: no-store:禁止浏览器缓存
  4. cache-control: public:可以被所有用户端缓存
  5. cache-control: private:只能被终端用户浏览器缓存
  6. cache-control: max-age=300:强行缓存5分钟

  • 强缓存:一段时间内,浏览器请求只会从缓存中获取数据
  • 协商缓存1:(根据文件时间判断)
    1. 请求时,请求头会携带 第一次响应时响应头的Last-Modify的值,放在if-Modify-Since里
    2. 服务器会根据文件修改时间,和请求头里的if-Modify-Since的值进行比较
    3. 如果比较一致,返回304。浏览器就会从缓存中获取数据
    4. 如果不一致,就会返回数据,浏览器就会刷新缓存中的数据
  • 协商缓存2:(根据文件内容判断)
    1. 请求时,请求头会携带 第一次响应时响应头的ETag的值,放在if-None-Match里
    2. 服务器会根据文件唯一标识,和请求头里的if-None-Match的值进行比较
    3. 如果比较一致,返回304。浏览器就会从缓存中获取数据
    4. 如果不一致,就会返回数据,浏览器就会刷新缓存中的数据

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

  1. 预设 100px = 1rem;
  2. 所以 html的字体大小 = (显示区大小 / 设计稿1920) * 预设100
  3. 其他元素的就可以换算rem设置尺寸
  4. 优点:精确,兼容,便于调整预设
  5. 缺点:性能消耗,页面卡顿

  1. 预设 100px = 1rem
  2. 所以 html的字体大小 = 5.21vw
  3. 其他元素的就可以换算rem设置尺寸
  4. 优点:页面流畅,能够配合响应式布局
  5. 缺点:不精确,不兼容,预设固定

  • 自动将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) => {})

相关文章:

  • Go基础语法阶段核心内容(5天)
  • ESP32(4)TCP通信
  • 免费实用工具,wps/office/永中通吃!
  • Matlab 高效编程:用矩阵运算替代循环
  • 淘宝商品详情商品评论数据爬取的技术之旅
  • 数据结构 -- 树和二叉树
  • 系统架构图
  • tongweb7控制台无法访问
  • 第59天:Web攻防-XSS跨站反射型存储型DOM型接受输出JS执行标签操作SRC复盘
  • Linux|静态库 共享库
  • redis十大应用数据类型具体使用及其应用
  • Go语言不定长参数使用详解
  • 【蓝桥杯】第十三届C++B组省赛
  • 删除排序链表中的重复元素(js实现,LeetCode:83)
  • 解决远程卡在下载vscode-server的问题,一键安装脚本
  • 网站搭建(node.js安装后hexo无法安装的修复步骤)
  • C语言之数据结构:链表
  • 嵌入式硬件篇---龙芯UART通信
  • vscode使用ssh同时连接主机CentOS:user和ubuntu20.04:docker
  • MATLAB 2024b深度学习新特性全面解析与DeepSeek大模型集成开发
  • “ChatGPT严选”横空出世了,“DeepSeek严选”还要等多久?
  • 神十九飞船已撤离空间站,计划于今日中午返回东风着陆场
  • 深入贯彻中央八项规定精神学习教育中央指导组派驻地方和单位名单公布
  • 港交所与香港证监会就“中概股回流意向”已与部分相关企业进行接触
  • 中共中央、国务院关于表彰全国劳动模范和先进工作者的决定
  • BNEF:亚洲、中东和非洲是电力基础设施投资的最大机会所在