最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • DOM编程

    正文概述 掘金(饥人谷一言)   2021-02-06   416

    你可以看到

    如何获取元素

    节点的增删改查

    DOM跨线程操作

    要说的话

    到这里总算不是门外汉了,这才是程序员的开始。

    --资料来源于饥人谷

    DOM编程

       JS用document操作网页,这就是Document Object Model文档对象模型。

       什么是DOM呢,就是把网页抽象成一个document对象,并对它进行操作的一种方式就是DOM

    • 网页其实是一棵树

       看一下代码结构

    DOM编程

       看树每个节点

    DOM编程

       JS 如何操作这棵树

    浏览器往window上加一个document即可

    DOM编程

    • JS 用document 操作网页

       这就是Document Object Mod,DOM

    • DOM很难用

       API很长,不好用,不得不来封装

    d


    获取元素,也叫做标签

    获取任意元素的API

       1. window.idxxx或者直接idxxx

       2. document.getElementByld('idxxx')如果id和全局变量冲突了可以用这个

       3. document.getElementsByTagName('div')[0]找到所有标签名为div的元素,只有加下标才可以来操作对应div。 比如

    DOM编程

       4. document.getElementsByClassName('red')[0]根据class类名来获取,比如把所以类名class为red的标签用下标获取到,取第0个下标即第1个元素。

       5. document.querySelector('#idxxx')可以像css选择器一样写的很复杂,比如某div里的span并且还是div的第二个儿子

    DOM编程

       document.querySelectorAll('.red')[0]找到所有满足这个条件的元素

    • 用哪一个

       工作中用querySelectorquerySelectorAll要兼容IE的才用getElement(s)ByXXX

    获取特定元素

    • 获取html根元素

       document.documentElement    好长啊

    如果你打出它的标签名的话:document.documentElement.tagName获取html元素的标签名

    DOM编程

    • 获取head元素

       document.head

    • 获取body元素

       document.body

    • 获取窗口(窗口不是元素)

       window

    window虽然不是一个标签,但我们有时确实会获取到这个window,然后可以添加一些事件监听

    • 获取所有元素

       document.all

      可以看到当前页面一共有多少个标签。

    获取到的元素是个啥

       获取到的所有元素显然是一个对象,我们需要搞清它自身有哪些属性以及它的原型。

       抓一只div对象来看看let div = document.getElementsByTagName('div')[9]。然后用console.dir(div1)看原型链。可以看到六层原型链

    元素的六层原型链

    先上图

    DOM编程

    • 第一层原型HTMLDivElement.prototype

       这里面是所有div共有的属性,不用细看。

    • 第二层原型HTMLElement.prototype

       这里面是所有HTML标签共有的属性,不用细看

    • 第三层原型Element.prototype

       这里面是所有XML、HTML标签的共有属性,你不会以为浏览器只能展示HTML吧

    • 第四层原型Node.prototype

       这里面是所有节点共有的属性,节点包括XML标签文本注释、HTML标签文本注释等等

    • 第五层原型EventTarget.prototype

       里面最重要的函数属性是addEventListener

    • 最后一层原型就是Object.prototype 了

    节点?元素?傻傻分不清

    在任意一个节点上输入.nodeType可以获取到它的node类型    节点包括元素和文本等,元素就是标签,叫法不同而已。

    • 节点Node包括以下几种

       1表示元素Element,也叫标签Tag

       3表示文本Text

       8表示注释Comment

       9表示文档Document

       11表示文档片段DocumentFragment

       记住1和3即可

    图示例

    DOM编程


    节点的增删改查

       程序员的宿命就是增删改查

    • 创建一个标签节点

       let div1 = document.createElement('div')

       document.createElement('style')

       document.createElement('script')

       document.createElement('li')

    好长啊,所以要去使用jQuery,vue,react

    • 创建一个文本节点

       text1 = document.createTextNode('你好')

    • 标签里面插入文本

       div1.appendChild(text1)   --Node提供的接口

       div1.innerText= '你好'或者div1.textContent= '你好'   --Element提供的接口

       但是不能用div1.appendChild('你好')

    • 插入页面中

       你创建的标签默认处于JS线程中,你必须把它插到head或者body里面,它才会生效

       用document.body.appendChild(div),或者,已在页面中的元素.appendChild(div),才可以把div放入对应位置

    appendChild
    • 代码

       假如页面中有 div#test1 和 div#test2

    let div = document.createElement( 'div ' )
    test1.appendChild(div)
    test2.appendChild(div)
    
    • 请问最终div 出现在哪里?

      • test1里面

      • test2里面

      • test1里面和test2里面

    • 两种方法

       旧方法:parentNode.childChild(childNode) 找到粑粑搧掉儿子

       新方法: childNode.remove() 不兼容IE。一样的效果

    • 思考

       如果一个node被移出页面(DOM树)

       那么它还可以再次回到页面中吗?

       还可以,只是从树移到了内存里

       彻底删掉要让它为空,内存就会把它当垃圾回收掉了。

    改属性

    • 写标准属性

    改id:div1.id = "div1"

       改全class: div.className = 'red blue'(全覆盖,每次改会把之前的覆盖了)

       改一部分className:div.className += ' red'(在原来的基础上加上空格red。)

       改class: div.classList.add('red') 新的API, classList可以告诉你class有哪些,长度多少。

       改style: div.style = 'width: 100px; color: blue;'(原先的无了,被覆盖了)

       改style的一部分:div.style.width = '200px'

       大小写:div.style.backgroundColor = 'white'就是把-后面接的字母变成大写。或者div.style['background-color']。

       改data-*属性: div.dataset.x = 'dw'(div.dataset。在属性名前加上data-,通过dataset.属性名就可以得到内容。改的话直接 = '要改的') 自定义属性。

    • 读标准属性

    基本上名字上一一对应的

       div.classList / a.href 这种可能会有问题,例子

       div.getAttribute('class') / a.getAttribute('href')获取原原本本的值

       两种方法都可以,但值可能稍微有些不同

    改事件处理函数

    还可以改on开头的属性

    • div.onclick默认为null

    代码示例

       默认点击div不会有任何事情发生,但是如果你把div.onclick改为一个函数fn,那么点击div的时候,浏览器发现这个div的onclick是有的,于是就会调用这个onclick函数,并且浏览器是用call调用的fn.call(div, event)(触发元素的引用,事件的详细信息)。fn.call(div, event)里div会被当做this,第一个参数就是event则包含了点击事件的所有信息,如坐标。函数是被调的,这样就可以传个参数。

    • div.addEventListener

       是div.onclick的升级版.onclick只能写一个函数,写第二个会覆盖前面的。addEventListener可以写无数个函数。

    改内容

       改儿子

    • 改文本内容

       div.innerText = 'xxx' IE写的

       div.textContent = 'xxx' 标准浏览器

       两者几乎没有区别,浏览器同时支持这两个

    • 改HTML内容

       div.innerHTML = '<strong>重要内容</strong>'内容太多太多字符(2W字符左右)可能会卡浏览器

    • 改标签

       div.innerHTML= "//先清空

       div.appendChild(div2)/再加内容

    改爸爸

    • 想要找一个新爸爸?

       newParent.appendChild(div)在这个新爸爸节点调用appendChild把自己放进去

       直接这样就可以了,直接从原来的地方消失,到新爸爸家里去了

    • 查爸爸

       node.parentNode或者node.parentElement

    • 查爷爷

       node.parentNode.parentNode 爸爸的爸爸叫爷爷以此类推

    • 查子代

       node.childNodes(包括文本节点)或者node.children(不包括文本节点)

       console.log(node.childNodes.length)打印出子节点的长度。可能会获取到你不想要的,空格也算一个长度(包括文本节点)。 代码示例

       一般用node.children(不包括文本节点)

    • 思考:

    当子代变化时,两者也会实时变化吗?

       都会实时更新,但querySelectorAll不会实时更新

    • 查兄弟姐妹

       node.parentNode.childNodes不仅要排除所有文本节点还要排除自己

       node.parentNode.children还要排除自己

    • 查看老大

       看第一个儿子

       node.firstChild

    • 查看老幺

       node.lastChild

    • 查看上一个哥哥/姐姐

       node.previousSibling有可能查看到文本节点

       node.previousElementSibling查找元素的兄弟

    • 查看下一个弟弟/妹妹

       node.nextSibling

    • 遍历一个div里面的所有元素

    先遍历当前节点在遍历子节点

    travel = (node, fn) =>{
      fn(node)
      if(node.children){
        for(let i=0;i<node.children.length;i++){
          travel(node.children[i], fn)
        }
      }
    }
    travel(div1, (node) =>console.log(node))
    
    

    DOM是跨线程的

       浏览器分为渲染引擎和JS引擎,这两个在不同线程,互不相干

       跨线程操作

    • 各线程各司其职

       JS引擎不能操作页面,只能操作JS

       渲染引擎不能操作JS,只能操作页面

       document.body.appendChild(div1)

       这是JS调用,理论只能存在内存里,为什么可以出现在屏幕上呢,这句JS是如何改变页面的?

    • 跨线程通信

       当浏览器发现JS在body里面加了个div1对象

       浏览器就会通知渲染引擎在页面里也新增一个div元素

       新增的div元素所有属性都照抄div1对象

    图示跨线程操作

    DOM编程

       时间花在浏览器发现并通知上,显得更新div的操作会比其他的所有操作都要慢

    插入新标签的完整过程

    • 在div1放入页面之前

       你对div1所有的操作都属于JS线程内的操作

    • 把div1放入页面之时

       浏览器会发现JS的意图

       就会通知渲染线程在页面中渲染div1对应的元素

    • 把div1放入页面之后

       你对div1的操作都有可能会触发重新渲染

       div1.id = 'newld'可能会重新渲染,也可能不会

       div1.title = 'new'可能会重新渲染,也可能不会。可以看CSS tricks

       如果你连续对div1多次操作,浏览器可能会合并成一次操作,也可能不会(以前动画里提到过,代码示例)

    属性同步

    • 标准属性

       对div1的标准属性的修改,会被浏览器同步到页面中。比如id、className、title等

    • data-*属性

    同上

    • 非标准属性

       对非标准属性而且也不是data的修改,则只会停留在JS线程中 ,不会同步到页面里

       比如x属性,示例代码

    • 启示

       如果你有自定义属性,又想被同步到页面中,请使用data-作为前缀

    图示

    DOM编程

    Property v.s.Attribute

    • property属性

       指的是JS线程中div1的所有属性(也就是div的在内存里的那个对象),叫做div1的property(比如id是它的property,className也是它的property)

    • attribute也是属性

       指的是渲染引擎中div1对应 标签的属性(比如id='',那id=''就是它的属性),叫做attribute

    • 区别

       大部分时候,同名的property和attribute值相等

       但如果不是标准属性,那么它俩只会在一开始时相等

       但注意attribute只支持字符串

       而property支持字符串、布尔等类型


    DOM操作慢么?

    网上都说 DOM 操作慢,实际上只是比 JS 操作慢,DOM 操作比网络请求还是快很多的。

       关于这一部分内容,大家可以延伸阅读参考一些文章:

    • 为什么说DOM操作很慢

    • 为什么经过10年的努力DOM操作还是这么慢

    DOM编程


    起源地下载网 » DOM编程

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元