JaimeCheng / zxx-quiz-summary

zxx-quiz 小测收集总结
https://github.com/zhangxinxu/quiz
1 stars 0 forks source link

DOM基础测试34 - 节点遍历 #2

Open JaimeCheng opened 5 years ago

JaimeCheng commented 5 years ago

题目: 原issue

回答:

// 我的回答 9分
var as = document.getElementsByTagName('a')
// 2
var links = document.querySelectorAll('[href]');
// 3
links.forEach(el => {
   const val = el.getAttribute('href');
   if (val.indexOf('javascript:') === 0) {
      el.setAttribute('role', 'button')
   }
   if (val.indexOf('#') === 0) {
      el.setAttribute('rel', 'internal');
   }
   if (el.host !== location.host) {
      el.setAttribute('target', '_blank');
      el.setAttribute('rel', 'external nofollow noopener');
   }
})

满分回答

总结:

  1. 第二题没考虑周全任何标签都可能有href属性,也没了解什么是链接元素,不只有a还有 area;
  2. 第三题中,rel属性要设置包含那几个值,不能使用赋值,这样会覆盖掉原来的属性;
  3. 节点遍历如果考虑兼容性,最好是转成数组再用for循环遍历;
  4. 链接元素获取host;
  5. 直接 .href 和获取href属性值的区别;

> 在线demo <

JaimeCheng commented 5 years ago

zxx: 本期要点

  1. 获取所有a元素,两种方法:document.getElementsByTagName('a') 所有浏览器都支持,还有document.querySeletorAll('a'),IE8+。
  2. 答案是:document.links或者document.querySelectorAll(':link')都是可以的。链接元素和元素的区别:首先没有href属性的元素不是链接元素,其次链接元素还包括元素(带href)。document.querySelectorAll('[href]')的问题在于,普通元素设置href属性也能获取。
  3. NodeList直接forEach IE浏览器不支持,Chrome、Firefox也是最近几年才支持。需要转换成数组,使用[].slice.call(links),IE9+支持的。ES6 [...aLink],Arrar.from((links)转数组(其实没必要,因为支持ES6也就支持NodeList直接forEach)。如有要兼容IE8,那就是for循环。
  4. startsWith可以关注下,字符串前匹配。
  5. 链接地址和当前地址栏地址host匹配,eleLink.host == location.host。链接元素天然自带:host(包括端口), hostname, hash等属性,和location对象一样。不要使用hostname有bug,端口不一也会匹配,例如:\ 和URL //www.xxxx.com:90 会认为是一个域下,实际上不是的。
  6. rel属性值包含。就是不覆盖原来设置的rel属性值。需要用到relList,需要注意的是多个rel属性值赋值需要使用relList的add方法,而不是直接等于。直接等于不是赋值多个,而是一个,例如:element.relList = ['external', 'nofollow', 'noopener'],最后结果是\是不合法的,应该空格分隔。正确用法(出题本意):link.relList.add('external', 'nofollow', 'noopener')。relList和classList API细节都是一样的,只不过一个针对class属性,一个是rel属性。
  7. link.href.indexOf('#') > -1有bug,例如 href="//otherdomain.com#xxxx",还有一种/^#/.test(link.href)也是有bug的,因为href属性通过DOM对象直接获取是带有域名的,需要匹配getAttribute获取的href属性值,也就是这里可以/^#/.test(link.getAttribute('href'))