Js开发者10bet::玩DOM也要专业范儿

来源:http://www.chinese-glasses.com 作者:Web前端 人气:198 发布时间:2020-04-22
摘要:时间: 2019-09-22阅读: 118标签: dom 前言: HTML5向WebAPI新引入了document.querySelector以及document.querySelectorAll两个方法用来更方便地从DOM选取元素,功能类似于jQuery的选择器 后传一:与jQuery的区

时间: 2019-09-22阅读: 118标签: dom

前言:
HTML5向Web API新引入了document.querySelector以及document.querySelectorAll两个方法用来更方便地从DOM选取元素,功能类似于jQuery的选择器
后传一:与jQuery的区别

别再害怕 DOM 了,让我们充分挖掘 DOM 的潜力,你会真的爱上它。

10bet 1

2008 年,当我刚成为一名专业 Web 开发人员参加工作时,我了解一些 HTML、CSS 和 PHP 的知识。那时我也在学习 JavaScript,因为它可以用来显示和隐藏元素和制作下拉菜单之类很酷的事情。

代码段1:

当时我在一家小公司工作,我们主要为客户创建 CMS 系统。彼时我们需要一个多文件上传器,这是当时的原生 JavaScript 无法实现的功能。

10bet 2

经过一番搜索,我发现了一个基于 Flash 的精美解决方案,还有一个名为 MooTools 的 JavaScript 库。MooTools 有一个很酷的 $ 函数来选择 DOM 元素,并带有诸如进度条和 Ajax 请求之类的模块。几周后我发现了 jQuery,仿佛打开了新世界的大门。它不再需要冗长、笨拙的 DOM 操作,取而代之的是简单、可链接的选择器,并且还附带了一堆有用的插件。

看以上代码,想问大家一个问题,结果输出什么?也就是oDiv 会获取到几个元素?
A. div2 B. div2 div3 C. div1 div2 div3 D. null

快进到 2019 年,今天的世界由框架统治。如果你作为 Web 开发人员的事业生涯始于过去十年中,那么你很可能接触不到什么“原始”的 DOM。你甚至可能根本用不着它。

答案是: b 取后代元素,相当于jQuery里边的find
代码段2:

尽管诸如 Angular 和 React 之类的框架让 jQuery 的热度大减,但它仍在被 6600 万个网站所使用,这是一个惊人的数字,约占全球所有网站的 74%。

10bet 3

jQuery 的遗产给人留下了深刻的印象,它给标准带来的影响力有一个很好的例子,那就是模仿 jQuery 的 $ 函数的 querySelector 和 query-SelectorAll 方法。讽刺的是,这两种方法可能是 jQuery 热度下降的最大元凶,因为这两种方法替代了 jQuery 最常用的功能:轻松选择 DOM 元素。

代码段1 与 代码段 2 相比他们的输出一样?

但是原生 DOM API 很冗长。我的意思是说,一边是 $,另一边却是 document.query-SelectorAll。这就是让开发人员抵触原生 DOM API 的原因所在。但实际上这完全没必要。

10bet 4

原生 DOM API 很棒,而且非常有用。是的,它很冗长,但这是因为它们是低级构建块,上面是要构建抽象的。而且如果你真的不想多打字的话:所有现代编辑器和 IDE 都提供出色的代码完成功能。你也可以为最常用的功能加上别名,我会在后文给出示例。

HTMLCollection 是一个接口,表示 HTML 元素的集合,它提供了可以遍历列表的方法和属性。
NodeList 引号来访问列表中的节点(索引号由0开始)

我们开始吧!

HTMLCollection 对象和 NodeList 对象很相似,但前者可能既能用名称索引也能用数字索引。
作者:苏墨橘链接:https://www.zhihu.com/question/34183746/answer/59043879来源:知乎
proto(隐式原型)与prototype(显式原型)1.是什么
显式原型 explicit prototype property:

选择元素单元素

每一个函数在创建之后都会拥有一个名为prototype的属性,这个属性指向函数的原型对象。

要使用任何有效的 CSS 选择器选择单个元素,请输入:

隐式原型 implicit prototype link:
JavaScript中任意对象都有一个内置属性[[prototype]],在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过proto来访问。ES5中有了对于这个内置属性标准的Get方法Object.getPrototypeOf(). Note: Object.prototype 这个对象是个例外,它的proto值为null
二者的关系:

document.querySelector(/* your selector */)

隐式原型指向创建这个对象的函数(constructor)的prototype

可以使用下面的任何选择器:

代码段3:

document.querySelector('.foo')// class selectordocument.querySelector('#foo')// id selectordocument.querySelector('div')// tag selectordocument.querySelector('[name="foo"]')// attribute selectordocument.querySelector('div + p  span')// you go girl!

10bet 5

如果没有匹配的元素,它将返回 null。

输出什么结果:
A. span1 B. span2 C. span1 span2 D. div2 span1 span2

多元素

答案: C
按照jQuery的语法:

要选择多个元素,请输入:

10bet 6

document.querySelectorAll('p')// selects all p elements

答案因该是:span1

你可以用 document.querySelectorAll,用法与 document.querySelector 相同。任何有效的 CSS 选择器都可以,唯一的区别是 querySelector 将返回单个元素,而 querySelectorAll 将返回包含找到的元素的静态 NodeList。如果没有找到任何元素,它将返回一个空的 NodeList。

原因:、
当在一个DOM元素上调用querySelector/querySelectorAll的时候,查找机制是这样的:首先在document的范围内进行查找所有满足选择器条件的元素,在上面这段代码中,我们的选择器是div > span,就是所有的直接父元素为div的span元素。然后,再看哪些元素是调用querySelector/querySelectorAll的元素的子元素,这些元素将会被返回。
所以,在DOM元素上调用querySelector/querySelectorAll的时候要小心,最好加上ID选择器进行一个限定,例如上面的代码可以写成:

NodeList 是一个可迭代的对象,它类似数组,但实际上不是数组,因此它没有相同的方法。你可以在其上运行 forEach,但不能用 map、reduce 或 find。

10bet 7

如果确实需要在其上运行数组方法,则可以使用解构或 Array.from 将其转换为数组:

constarr = [...document.querySelectorAll('p')];orconstarr =Array.from(document.querySelectorAll('p'));arr.find(element ={...}); // .find() now works

10bet 8

querySelectorAll 方法与诸如 getElements-ByTagName 和 getElementsByClassName 之类的方法的不同之处在于,这些方法返回的是实时收集的 HTMLCollection,而 query-SelectorAll 返回的是静态的 NodeList。

就会准确的返回我们预期的span1了。
在W3C官方文档中,有提到使用:context (现已更名为:scope)伪类来限制选择器开始工作的上下文,也就是说,可以这样写:

因此,如果执行 getElementsByTagName(‘p’), 一个p将从文档中删除,也会从返回的 HTMLCollection 中删除。

10bet 9

但如果执行 querySelectorAll(‘p’),一个p将从文档中删除,但它仍将存在于返回的 NodeList 中。

但是实际测试的结果是 Safari 6.0.4 和 Chrome 27 统统没有按照预期工作,因为W3C也说了,这个不是标准的。前言:
HTML5向Web API新引入了document.querySelector以及document.querySelectorAll两个方法用来更方便地从DOM选取元素,功能类似于jQuery的选择器
后传一:与jQuery的区别

另一个重要的区别是,HTMLCollection 只能包含 HTMLElement,而 NodeList 可以包含任何类型的 Node。

10bet 10

相对搜索

代码段1:

你不一定需要在 document 上运行 query-Selector(All)。你可以在任何 HTML-Element 上运行它以执行相对搜索(relative search):

10bet 11

constdiv =document.querySelector('#container');div.querySelectorAll('p')// finds all p tags in #container only

看以上代码,想问大家一个问题,结果输出什么?也就是oDiv 会获取到几个元素?
A. div2 B. div2 div3 C. div1 div2 div3 D. null

但这仍然很冗长!

答案是: b 取后代元素,相当于jQuery里边的find
代码段2:

如果你还是觉得打的字太多了,则可以为两种方法起别名:

10bet 12

const$ =document.querySelector.bind(document);$('#container');const$$ =document.querySelectorAll.bind(document);$$('p');

代码段1 与 代码段 2 相比他们的输出一样?

搞定。

10bet 13

爬一爬 DOM 树

HTMLCollection 是一个接口,表示 HTML 元素的集合,它提供了可以遍历列表的方法和属性。
NodeList 引号来访问列表中的节点(索引号由0开始)

使用 CSS 选择器选择 DOM 元素意味着我们只能沿着 DOM 树向移动。没有 CSS 选择器可以沿树向上选择父项。

HTMLCollection 对象和 NodeList 对象很相似,但前者可能既能用名称索引也能用数字索引。
作者:苏墨橘链接:https://www.zhihu.com/question/34183746/answer/59043879来源:知乎
proto(隐式原型)与prototype(显式原型)1.是什么
显式原型 explicit prototype property:

但是我们可以使用 closest() 方法向 DOM 树上面移动,该方法也能用任何有效的 CSS 选择器:

每一个函数在创建之后都会拥有一个名为prototype的属性,这个属性指向函数的原型对象。

document.querySelector('p').closest('div');

隐式原型 implicit prototype link:
JavaScript中任意对象都有一个内置属性[[prototype]],在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过proto来访问。ES5中有了对于这个内置属性标准的Get方法Object.getPrototypeOf(). Note: Object.prototype 这个对象是个例外,它的proto值为null
二者的关系:

这将找到 document.querySelector(‘p’) 选择的段落中最接近的父div元素。你可以将这些调用链接起来,往树上多爬几层:

隐式原型指向创建这个对象的函数(constructor)的prototype

document.querySelector('p').closest('div').closest('.content');

代码段3:

添加元素

10bet 14

向 DOM 树添加一个或多个元素的代码很容易变得冗长拖沓,因而臭名昭著。假设你要在页面上添加以下链接:

输出什么结果:
A. span1 B. span2 C. span1 span2 D. div2 span1 span2

ahref="/home"Home/a

答案: C
按照jQuery的语法:

你需要:

10bet 15

constlink= document.createElement('a');link.setAttribute('href','/home');link.className ='active';link.textContent ='Home';document.body.appendChild(link);

答案因该是:span1

现在想象一下,这套操作要在 10 个元素上重复十次……

原因:、
当在一个DOM元素上调用querySelector/querySelectorAll的时候,查找机制是这样的:首先在document的范围内进行查找所有满足选择器条件的元素,在上面这段代码中,我们的选择器是div > span,就是所有的直接父元素为div的span元素。然后,再看哪些元素是调用querySelector/querySelectorAll的元素的子元素,这些元素将会被返回。
所以,在DOM元素上调用querySelector/querySelectorAll的时候要小心,最好加上ID选择器进行一个限定,例如上面的代码可以写成:

至少 jQuery 允许你执行以下操作:

10bet 16

$('body').append('a href="/home"Home/a');

其实原生也有等效操作,想不到吧?

10bet 17

document.body.insertAdjacentHTML('beforeend','a href="/home"Home/a');

Paste_Image.png

使用 insertAdjacentHTML 方法,你可以在第一个参数指示的四个位置向 DOM 中插入任意有效的 HTML 字符串:- ‘beforebegin’:元素之前。

就会准确的返回我们预期的span1了。
在W3C官方文档中,有提到使用:context (现已更名为:scope)伪类来限制选择器开始工作的上下文,也就是说,可以这样写:

‘afterbegin’:在元素的第一个子元素之前。‘beforeend’:在元素的最后一个子元素之后。‘afterend’:元素之后。

10bet 18

!-- beforebegin --p!-- afterbegin --foo!-- beforeend --/p!-- afterend --

但是实际测试的结果是 Safari 6.0.4 和 Chrome 27 统统没有按照预期工作,因为W3C也说了,这个不是标准的。

这样就能更容易地指定插入新元素的确切位置。假设你要在这个p之前插入a,如果没有 insertAdjacentHTML,则必须执行以下操作:

constlink =document.createElement('a');constp =document.querySelector('p');p.parentNode.insertBefore(link, p);

现在我们只要:

constp = document.querySelector('p');p.insertAdjacentHTML('beforebegin', 'a/a');

这也是插入 DOM 元素的一种原生等效方法:

本文由10bet发布于Web前端,转载请注明出处:Js开发者10bet::玩DOM也要专业范儿

关键词:

最火资讯