Dom节点类型和事件冒泡捕获

Dom

  • 获取dom节点
    • document.getElementById("div1").childNodes 获取到div1节点的子节点集合。包含元素节点,文本节点啥的都有,回车符都可以获取到
    • document.getElementById("div1").children 获取到的是元素节点的集合
    • div1.removeChild(),删除节点
    • div1.appendChild(),插入节点
  • attribute 属性节点
    • 可以使用js向元素里面动态的添加属性
    • getAttribute(‘xxx’)获取某个属性
    • setAttribute(‘xx’, ‘xxx’)设置属性和属性值
  • property
    • nodeName 元素的名字。p标签的nodeName就是 P
      • 元素节点的 nodeName 是标签名称(大写)
      • 属性节点的 nodeName 是属性名称
      • 文本节点的 nodeName 永远是 #text
      • 文档节点的 nodeName 永远是 #document
    • nodeType 元素的节点类型。共12种,常用的有
      • 元素节点(1)(Element)
      • 属性节点(2)(attr)
      • 文本节点(3)(Text)
      • 注释节点(8)
      • 文档节点(9)
    • nodeValue
      • 对于文本节点,nodeValue 属性包含文本。
      • 对于属性节点,nodeValue 属性包含属性值。
      • 文档节点和元素节点,nodeValue 属性的值始终为 null
  • Dom查询的优化
    • 将查询到的dom节点使用变量保存下来,length啥的都先放到变量里面,再循环
    • 创建个文档片段,在里面将dom操作完,再一起放到页面中
      • const falg = document.createDocumentFragment()

事件

Dom0级事件

  • dom0级事件就是onclick 这种,直接个一个元素绑定事件

  • Dom0级和Dom2级事件中,直接运行的函数this都指向当前dom

        const div1 = document.getElementById("div1");
        div1.onclick = function () {
          console.log(this) //<div id="div1"></div>
          alert("div1")
        };
    
  • 移除事件 btn.onclick = null

Dom2级事件

  • 可以给一个dom绑定多个事件,按照写的代码顺序执行diffrent函数

  • 移出事件removeEventListener(btn, click, fn)。删除事件时,参数必须和定义事件的参数一样。不一样就删除不掉。所以fn是匿名函数时,无法删除

  • Dom2事件运行顺序,先捕获进来再冒泡回去。

    先是捕获阶段,从document 到 html,再到body。

    然后是冒泡节点,从当前div到body,到html,到document

  • addEventListener 的第三个参数默认是false,表示在冒泡阶段执行回调函数,是true时,回调函数是在捕获进去的时候执行

事件绑定

  • 编写一个通用的事件监听函数
    function bindEvent (ele, type, fn) {
        ele.addEventListener(type, fn)
    }
    
    const btn1 = document.getElementById('btn1')
    //调用时往里面传梯三个参数。元素,事件类型,事件回调函数
    bindEvent(btn1, 'click', e => {
        e.preventDefault()//如果是a标签,点击会跳转,取消掉默认事件
        console.log(e.target)//是谁触发了这个事件
        console.log('点击btn')
    })
    
  • 事件的冒泡流程
    • 从子元素身上开始,往父级元素上面冒泡。如果对所有元素进行监听,会发现,点击一个子元素,所有子元素的祖先都被点击了一次

    • 可以通过**e.stopPropagation()**来阻止冒泡

      可以通过**e.preventDefault()**来阻止默认行为

      bindEvent(body, 'click', e => {
          e.preventDefault()
          console.log(e.target)
          console.log('body clicked')
      })
      //点击div2,事件会在div2里面执行一次,再到上面的body里面执行一次
      bindEvent (div2, 'click', e => {
          //e.stopPropagation()//阻止冒泡
          console.log(e.target)
          console.log('div2 clicked')
      })
      
  • 事件代理

    基于事件冒泡的机制

    当子元素不确定时,无法给子元素绑定监听事件,可以将事件监听绑定到父元素上,由父元素触发子元素上的东西.比如监听所有p标签的点击事件

    function bindEvent(ele, type, fn) {
        //这里addEventListener()可以有三个参数,
        //第三个参数默认是false,表示冒泡,true为捕获
        ele.addEventListener(type, fn)
    }
    const div1 = document.getElementById('div1')
    bindEvent(div1, 'click', e => {
        e.preventDefault()
        if(e.target.nodeName === 'P') { //比如点击button或者空白,就不会触发p事件
            console.log('P clicked')
        }
    })
    
  • 真正的事件代理

    addEventListener()可以有三个参数,第三个参数默认是false,表示冒泡时执行,true为捕获时执行

    function bindEvent(ele, type, selector, fn) {
        //这个函数需要传四个参数,但是有时候不需要事件代理,传三个参数就行,不传selector
        if (fn == null) {
            fn = selector
            selector = null
        }
        ele.addEventListener(type, event => {
            const target = event.target
            if (selector) {
                //存在代理时
                if (target.matches(selector)) {
           //这个matches,后面括号里的是一个标准的css选择器。
           //前面的ele是个元素节点时,matches里面的选择器可以匹配到ele,就会返回true
                    fn.call(target, event)
                }
            }else {
                // 普通绑定
                fn.apply(target, event)
            }
        })
    }
    const div1 = document.getElementById('div1')
    
    //这里传递参数不能使用箭头函数,箭头函数没有this,获取到的this就是window
    bindEvent(div1, 'click', 'p',  function (event) {
        event.preventDefault()
        console.log(this.innerHTML)
    })
    
  • 事件阻止
    • 阻止默认事件 event.preventDefault()
    • 阻止冒泡 event.stopPropagation()
    • 阻止事件,不管是冒泡还是捕获,都可以使用return false阻止
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值