• 作者:老汪软件技巧
  • 发表时间:2024-12-02 21:06
  • 浏览量:

简言

最近在做前端知识的复习和整理,有了一些自己新的体会。更多在于记录,通过反复的温习,写笔记消除自己以前学习知识点的误区

浏览器JS对象

JS在浏览器的运行环境中,一般由以下三部分组成

ECMAScript核心:作为JS的标准规范,描述了JS中的语法和基本对象BOM(Browser Object Model):浏览器对象模型,提供了用以控制浏览器行为的APIDOM(Document Object Model):浏览器对象模型,提供了用以编辑网页文档的接口ECMAScript核心

ECMAScript是一种由Ecma国际通过ECMA-262标准化的脚本语言规范。

ECMAScript 与 JavaScript有什么区别?名称定义规则拓展性

ECMAScript

ECMAScript是由ECMA国际标准化的脚本语言规范

ECMA提供了脚本语言必须遵守的规范,准则和细节

ECMAScript作为一种开放的,被国际广为接受的脚本语言规范,具有很大的灵活性

JavaScript

ECMAScript规范下的具体实现

JavaScript不仅具备ECMAScript的核心功能和特性,还具备与特定环境(浏览器)的交互能力

虽然JavaScript也是一种流行的脚本语言,但他基于ECMAScript的规范

BOM常见的BOM对象Navigator-浏览器系统导航信息集合判断浏览器并返回浏览器名称

以下两段代码引用于/post/706808…

const getCurrentBrower = () => {
  const ua = navigator.userAgent;
  let browser;
  if (ua.indexOf("Firefox") > -1) {
    browser = "Mozilla Firefox";
  } else if (ua.indexOf("Opera") > -1 || ua.indexOf("OPR") > -1) {
    browser = "Opera";
  } else if (ua.indexOf("Trident") > -1) {
    browser = "Microsoft Internet Explorer";
  } else if (ua.indexOf("Edge") > -1) {
    browser = "Microsoft Edge";
  } else if (ua.indexOf("Chrome") > -1) {
    browser = "Google Chrome or Chromium";
  } else if (ua.indexOf("Safari") > -1) {
    browser = "Apple Safari";
  } else {
    browser = "unknown";
  }
  return browser;
};

判断当前是否为移动端

const mobileFlags = [
  /AppleWebKit.*Mobile.*/, // 移动终端
  /\(i[^;]+;( U;)? CPU.+Mac OS X/, // ios终端
  /Android/, // 安卓终端
  /iPhone/, // iPhone
  /iPad/, // iPad
];
const isMobile = () => {
  const ua = navigator.userAgent;
  for (let flag of mobileFlags) {
    if (flag.test(ua)) {
      return true;
    }
  }
  return false;
};

由此我们就可以在实际开发中得知:

什么设备下,做什么设备的样式布局;什么环境下,针对当前环境进行浏览器兼容处理,统一浏览器默认行为等

经典剪切板问题

大家都知道剪切板功能可以通过以下步骤实现:

Dom获取Input对象obj.select()document.execCommand('Copy', false, null)

但是某些极端情况下(iPhone5 10.2),ios无法通过上述步骤实现剪切功能(第二步未生效),那么我们就需要针对这种特殊情况做处理

// 以下是伪代码
if(isIOSDevice){
    selectRange()
    
    try{
        document.execCommand('Copy', false, null)
    }
    
    // ....
}
function selectRange() {
    let obj = document.getElementById("textAreas");
    // 获取元素内容是否可编辑或只读
    let editable = obj.contentEditable; 
    let readOnly = obj.readOnly;
    
    // 改变元素内容可编辑性和非只读
    obj.contentEditable = true
    obj.readOnly = false;
    
    // 创建Range对象,Range对象表示文档的连续范围区域
    let range = document.createRange()
    // 获取obj作为用户选中范围
    range.selectNodeContents(obj)
    
    // 获取用户选中文本范围或光标当前位置
    let selection = window.getSelection()
    // 清除之前已选范围
    selection.removeAllRanges()
    // 添加当前已选范围
    selection.addRange(range)
    
    // 为文本元素设置文本中被选中的范围(起始位置,结束位置),这个方法用于input,textarea
    obj.setSelctionRange(0, 999999)
}

经典键盘输入问题

微信小程序-iOS键盘弹出遮挡输入框

可以使用input的cursor-spacing属性

指定光标与键盘的距离,取 input 距离底部的距离和 cursor-spacing 指定的距离的最小值作为光标与键盘的距离

location - 浏览器地址,提供获取浏览器地址信息的能力location常用方法location.replace和location.href的区别

location.href和location.replace本质上都是浏览器中的页面重定向当进行重定向的时候,浏览器会发起一个HTTP请求,通常会收到一个301或者302的状态码,这取决于服务器返回的类型,如果是返回301,表示之前资源的路径被销毁或永久移动,服务器返回了新的资源地址回来,在未来请求中会直接访问新的资源地址

而location.href在重定向完成之后会添加新的历史记录

而location.replace则是现将当前的历史记录移出,在将新的历史记录移入,完成历史记录替换

如果当前页面是C,页面是由A -> B -> C跳转的

若 B -> C用的replace,则从C返回上一个页面,则回到A

若 B -> C用的href,则从C返回上一个页面,则回到B

screen - 表示显示区域History - 网页的历史记录

window.history.pushState(stateObject, title, url)

与新历史记录关联的状态对象,title名称可以设置为null,新URL且必须与当前域名同域

window.history.replaceState(stateObject, title, url)

路由方向 history 和 hash模式的对比,不存在利弊,只存在区别展示形态不同,hash会在路径上总是展示一个#,用以描述当前的hash值,而history更贴近普通路由(给用户有一致性的感觉,因此感受更加)原理上的不同,hash改变的是锚点(使用hashChange监听),而history是改变的页面栈中栈顶的状态(使用onPopState监听)history使用时,需要后台指向一个标准的文件(匹配到了文件就读取,没有匹配到文件就回退)或者是api

// 在ngixn中
location / {
    root  /usr/share/nginx/html;  # 静态文件目录
    try_files $uri /index.html;    
}

上述try_files会按照给定的文件顺序去检查文件是否存在,如果文件存在则返回文件,如果文件不存在则返回一个默认文件,上述代码$uri表示当前匹配到的pathname,/index.html表示如果pathname没有匹配到文件,则返回root路径下 /usr/share/nginx/html目录下的index.html文件,然后通过前端JS控制路由切换

如果页面白屏了,应该从哪些部分排查

打开浏览器控制台,查看日志

js浏览器对象模型__浏览器对象模型有哪些

检查是否因为js代码语法错误导致,或是方法,变量类型不正确(一般是访问了undefined或null的属性),引用了未定义的变量或函数

网络请求

检查是否是因为请求pending或是响应404,5xx之类的错误,导致静态资源并未完全加载或加载错误

JS加载和执行

如果使用了异步加载,确认异步加载的资源都能够被正确的加载,并且需要确认JS加载的顺序是否正确,可能某些脚本并未加载完就被执行导致白屏

CSS问题

有时候白屏可能是因为设置了display: none,或者是被错误地定位到了页面外部,或者是CSS文件并未加载或者加载错误,导致白屏

构建工具

确保使用webpack等构建工具在构建输出时没有错误,或者因为意外导致文件压缩错误等

缓存问题

确保成功加载的文件都是最新的,尤其是SPA引用中,可能存在index文件更新了,但是引用的css文件以及其他脚本文件没有更新,导致白屏的错误

兼容性问题

检查是否在不同的浏览器中都出现了白屏问题,如果只是某个特定的浏览器出现白屏问题,则可能因为浏览器不支持某些Web新特性,或者是存在不兼容的特性

前端框架问题

确保路由配置是否都正确,是否存在重定向错误或者是路由路径的解析问题

后端问题

确认后端返回的是否有错误代码,或是接口调用超时,或是返回的数据不符合预期,导致前端渲染失败

Web服务器配置问题如果使用了Nginx,Apache等代理服务器,检查配置文件中是否存在问题,尤其是静态文件的路径等

总结一下就是:从三个方向查看前端与浏览器、构建与网络、后端与Web服务器

DOM事件模型

浏览器一般有三种绑定事件的方式

// 1.在HTML标签上定义
"handler">
// 2.js获取dom,将事件绑定在dom上 <div id="box1">div> <script> const box1 = document.getElementById("#box1") box1.onclick = () => { console.log('box1') } script> // 3.js获取dom,并给dom添加事件监听 <div id="box2">div> <script> const box2 = document.getElementById("#box2") box1.addEventListener('click', ()=>{}, false) script>

其他用法

DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Documenttitle>
  head>
  <style>
    #divA {
      width: 200px;
      height: 200px;
      border: 1px solid red;
    }
    #divB {
      width: 100px;
      height: 100px;
      border: 1px solid green;
    }
    #divC {
      width: 50px;
      height: 50px;
      border: 1px solid blue;
    }
  style>
  <body>
    <div id="divA">
      <div id="divB">
        <div id="divC">
          <a href="https://www.baidu.com" id="aA">点我a>
        div>
      div>
    div>
  body>
  <script>
    const divA = document.getElementById("divA");
    const divB = document.getElementById("divB");
    const divC = document.getElementById("divC");
    const aA = document.getElementById("aA");
    divA.addEventListener(
      "click",
      () => {
        console.log("divA");
      },
      false
    );
    divB.addEventListener(
      "click",
      () => {
        console.log("divB");
      },
      false
    );
    divC.addEventListener(
      "click",
      () => {
        console.log("divC");
      },
      false
    );
    aA.addEventListener(
      "click",
      (e) => {
        // e.stopPropagation();
        e.stopImmediatePropagation();
        e.preventDefault();
        console.log("aA-1");
      },
      false
    );
    aA.addEventListener(
      "click",
      () => {
        console.log("aA-2");
      },
      false
    );
  script>
html>

阻止冒泡事件

e.stopPropagation()

阻止浏览器默认事件

e.precentDefault()a标签的默认事件是跳转,阻止a标签的默认点击事件后,就不会跳转了

如果相同节点上绑定了多个同类型事件Click2,Click3等,如果既要阻止事件冒泡,又要阻止除自身(Click1)外其他同类型事件(Click2, Click3)触发

e.stopImmediatePropagation()此时只触发Click1;Click2与Click3甚至上层父级节点的事件不触发


上一条查看详情 +开发也能看懂的大模型:GNN
下一条 查看详情 +没有了