2022-01-09 浏览器相关面试知识点

一.详解浏览器事件捕获与冒泡

1. 事件委托/事件代理

捕获阶段-->目标阶段-->冒泡阶段

window.addEventListener('click',function(e){
  console.log('window捕获',e.target.nodeName,e.currentTarget.nodeName)
},true)
  • 第三个参数为true,则监听捕获事件,不传或者传false,则监听冒泡事件
  • e.target指的是点击的元素,e.currentTarget指的是当前触发事件的元素

2. 阻止事件的传播

e.stopPropagation()真正的作用是阻止事件的传播,既可以阻止事件的捕获也可以阻止事件的冒泡

面试题:

现在有一个页面,这个页面上有许多元素,div、p、button等
每个元素都有自己的click事件,都不相同
现在有一个新需求,一个用户进入这个页面的时候,会有一个状态:banned,我们可以在全局上拿到这个状态:window.banned
true的话表示当前用户被封禁,用户点击页面的任何元素都不执行原有逻辑,而是alert弹窗,提示你被封禁了;
false的话表示有操作权限。
请问:如何实现?
答:
方案一:在最外层的一个元素上绑定上一个捕获事件,即addEventListener里的第三个参数为true,如果window.bannedtruee.stopPropagation()

//const body = document.getElementsByTagName('body')
window.addEventListener('click',function(e){
  if(window.banner){
    e.stopPropagation()
    alert('你被封禁了')
    return
  }
  ...
},true)

方案二:window.bannertrue的时候展示一个全屏的最高层级(即:z-index:99999)的div遮罩,遮住整个页面。

3.阻止默认事件

e.preventDefault()
这个没啥好说的

4.兼容性问题

addEventListener --> firefox、Chrome、高版本IE、safari、opera
attachEvent --> IE7、IE8,除了政府网站,大部分公司不会再去针对他们做兼容了
IE浏览器里没有事件捕获,只有事件冒泡

针对兼容性做一下封装

class BomEvent{
  constructor(element){
    this.element = element
  }
  addEvent(type,handler){
    if(this.element.addEventListener){
      this.element.addEventListener(type,handler,false)
    } else if (this.element.attachEvent){
      this.element.attachEvent(`on${type}`,function(){
        // 这是处于ie7或8的一个环境,不支持箭头函数,所以这里做一下绑定
        handler.call(element)
      })
    }  else {
      this.element[`on${type}`]=handler
    }
  }

  removeEvent(type,handler){
    if(this.element.removeEventListener){
      this.element.removeEventListener(type,handler,false)
    }else if(this.element.detachEvent){
      this.element.detachEvent(`on${type}`,handler)
    }else{
      this.element[`on${type}`] = null
    }
  }
}

// IE浏览器里没有事件捕获,只有事件冒泡
function stopPropagation(event){
  if(event.stopPropagation){
    event.stopPropagation()  //标准w3c浏览器
  }else{
    event.cancelBubble = true // IE
  }
}

function preventDefault(event){
  if(event.preventDefault){
    event.preventDefault()
  }else{
    event.returnValue = false
  }
}

二:浏览器请求相关内容Ajax与fetch

原生ajax:

const xhr = new XMLHttpRequest()
xhr.open('GET','http://domain/service')   //建立连接,并没有发送请求

//监听状态
xhr.onreadystatechange = function(){
// 表示请求还没有完成
  if(xhr.readyState !== 4){
    return
  }else if(xhr.status === 200){
    // 请求成功
    console.log(xhr.responseText)
  }else{
    //报错了
    console.error(`HTTP error,status=${xhr.status},errorText = ${xhr.statusText}`)
  }
}
// 超时时间
xhr.timeout = 3000
xhr.ontimeout = ()=>{
  console.log('请求超时')
}

// 上传进度条
xhr.upload.onprogress = p => {
  const percent = Math.round((p.loaded / p.total)*100) + '%'
}

xhr.send()  //发送请求

fetch:浏览器新增的fetch,内部封装了promise

  fetch('http://domain/service',{
    method: 'GET',
    credentials: 'same-origin'  // 同域的请求会带上cookie
  }).then(response => {
    if(response.ok){
      //请求成功
      return response.json()
    }
    throw new Error(' http error')
  }).then(json => {
    console.log(json)
  }).catch(error => {
    console.error(error)
    // 统一的错误管理
    // 接收fetch出现的错误
    //  接收请求错误信息
  })

fetch不能直接通过catch来获取请求错误信息,而是要通过判断response.ok来返回出错误信息再通过catch来抓到错误信息

fetch自身不支持设置请求超时,我们自己来封装一个

function fetchTimeout(url,init.timeout=3000){
  return new Promise((resolve,reject)=>{
    fetch(url,init).then(resolve).catch(reject)
    
    setTimeOut(reject,timeout)
  })
}

中断一个请求

  //用于中断请求
  const controller = new AbortController()

  fetch('http://domain/service',{
    method: 'GET',
    credentials: 'same-origin', // 同域的请求会带上cookie
    signal:controller.sianal
  }).then(response => {
    if(response.ok){
      //请求成功
      return response.json()
    }
    throw new Error(' http error')
  }).then(json => {
    console.log(json)
  }).catch(error => {
    console.error(error)
  })

controller.abort()//用于中断请求

请求头request-header

referer:表示来源,你是从哪一个页面过来这个页面的,标识访问路径
user-agent:用来判断环境,设备标识

响应头response-header

access-control-allow-origin:跨域
用于做域名限制,跨域

  • access-control-allow-origin:/* ,不做限制

  • content-encoding: 是一个实体消息首部,用于对特定媒体类型的数据进行压缩。当这个首部出现的时候,它的值表示消息主体进行了何种方式的内容编码转换。这个消息首部用来告知客户端应该怎样解码才能获取在 Content-Type 中标示的媒体类型内容。

    <pre class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" lang="js" cid="n20" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">Content-Encoding: gzip
    Content-Encoding: compress
    Content-Encoding: deflate
    Content-Encoding: identity
    Content-Encoding: br</pre>

  • set-cookie:响应首部 Set-Cookie 被用来由服务器端向客户端发送 cookie。

status状态码

响应分为五类:信息响应(100199),成功响应(200299),重定向(300399),客户端错误(400499)和服务器错误 (500599)。

200 OK

请求成功。成功的含义取决于HTTP方法:

  • GET:资源已被提取并在消息正文中传输。

  • HEAD:实体标头位于消息正文中。

  • POST:描述动作结果的资源在消息体中传输。

  • TRACE:消息正文包含服务器收到的请求消息

201 Created

该请求已成功,并因此创建了一个新的资源。这通常是在POST请求,或是某些PUT请求之后返回的响应。

301 Moved Permanently

重定向。

被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。

302 Found

临时重定向。

请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。

304:协商缓存,服务器文件未修改

面试题

vue/react创建的单页面应用(spa),生成的index.html如果要做缓存应该做什么缓存?

答:协商缓存

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容