js干货-Bom,Dom事件及各种案例

BOM :
浏览器的一窗口 window 对象
不同的窗口不共享 window
实际上全局变量的和全局函数都属于window对象的自定义属性和方法
window 对象的属性
navigator 浏览器的相关信息
userAgent(字符串) 可以用于判断用户登录的设备

history 访问历史记录
length 这个窗口打开过几个页面
back() 回退一步
forward() 前进一步
go(-1/1/2)

location 地址栏
host 主机+端口号 www.jd.com:80
hostname 主机 /域名 www.jd.com
port 端口号 80
href 显示地址栏的完整信息 可获取可设置 ‘https://www.jd.com’
location.href = ‘http://www.baidu.com’
protocal 获取协议 http / https
pathname 路径
search 地址栏中问号后面的一串
reload() 刷新页面 不建议过多使用
location.assign(url) 替换当前文档 可以被历史记录
location. replace(url) 替换当前文档 不会被历史记录

location.reload() ==> 取值 ture false 不取值 默认为false
true ==> 刷新页面 不使用缓存
false ==> 刷新页面 使用缓存

location.reload()//  一直会刷新页面
 setTimeout(function () {
            // location.href = 'http://www.baidu.com'
            // location.assign('http://www.baidu.com')
            location.replace()
        }, 3000)

document (dom就是bom的一部分)
host 主机+端口号 www.jd.com:80

console.log(document);
        // doctype 文档声明
        console.log(document.doctype);
        // documentElement 文档的根对象html
        console.log(document.documentElement);
        console.log(document.body);
        console.log(document.head);
        console.log(document.title);

        setTimeout(function () {
            // title属性可读可写
            document.title = '百度一下'
        }, 2000)

        // console.log(document.div);   // undefined自由属性可以,div不是一个页面中必须的,所以undefined

window的方法
open()打开新窗口
window.open(url,name,窗口的特征) 返回值:被打开的窗口
close()关闭窗口
scollBy(x,y) 滚动条 单位像素 移动
scollTo(x,y) 滚动条 单位像素 达到

window事件 即BOM事件👇
元素.onload 当页面所有内容加载完毕之后再执行(文档、css、js、images…)

// onload 页面资源加载完毕之后再执行js
        window.onload = function () {
            var a = 10;
            console.log(a);

            var obj = document.getElementById('a');
            console.log(obj);
        }

元素.onresize 当视口大小发生改变时,触发事件

  // 页面尺寸发生改变时触发
        window.onresize = function () {
            console.log(666);
        }

元素.onscoll 当移动滚动条时触发事件

 // 页面滚动触发
        window.onscroll = function () {
            console.log("窗口大小改变ing");
            if(window.innerWidth>960){
                box.style.background="blue";
            }else if(window.innerWidth>750){
                box.style.background="pink";
            }else if(window.innerWidth>375){
                box.style.background="gray";
            }else(window.innerWidth>375){
                box.style.background="purple";
            }
        }

元素.onfocus 获取焦点 页面有了焦点就执行
元素.onblur 失去焦点 页面失去焦点就执行

window.onfocus = function () {
console.log(‘获取焦点’);
}
window.onblur = function () {
console.log(‘失去焦点’);
}


DOM页面的宽高问题
1.可视高度 包含滚动条
document.documentElement.innerWidth
document.documentElement.innerHeight

2.可视高度 不包含滚动条
document.documentElement.clientHeight
document.documentElement.clientWidth

  1. 页面的实际高度(页面被卷去的高度 – 滚动条距离顶部的距离)
    document.documentElement.scrollHeight
    document.documentElement.scrollWidth
    document.documentElement.scrollTop
    document.documentElement.scrollLeft

案例👇
被卷的高度= document.documentElement.scrollHeight实际高度-document.documentElement.clientHeight可视高度

案例
返回底部👇

<style>
    body {
        width: 100%;
        height: 3000px;
    }

    div {
        width: 300px;
        height: 300px;
        position: fixed;
        right: 0;
        bottom: 0;
        background: #000;
    }
</style>

<body>
    <div id="goback"></div>
</body>
<script>
    var root = document.documentElement || document.body;
    $("goback").onclick = function () {
        root.scrollTop = 0;
        console.log(root.scrollTop);
    }
    function $(id) {
        return document.getElementById(id);
    }
</script>

判断到达底部

var root=document.documentElement||document.body;
window.onscoll=function(){
    //怎样才算到达底部 页面的实际高度-页面的可视高度
    //页面在快要底部的时候就要请求新的数据
    //随便给一个10
    if(root.scrollTop>=root.scrollHeight-root.clientHeight-10){
        alert("别拉了 到底了")
    }
}

ie的兼容写法 将documentElement替换成(body)

 // 获取根元素的兼容写法
        var root = document.documentElement || document.body;

        console.log(root.clientHeight);

        console.log(root.scrollHeight);

        console.log(root.scrollTop);

获取内容的方法
innerHTML 可识别标签
value 表单
innerText 不识别标签

document 的获取元素的相关方法(ES5)
document.getElementById("") ==> id 只有一个,唯一性
document.getElementsByClassName("")[0] ==> class有多个,获取的是一个伪数组(拥有长度,可以通过下角标访问,但是不具有数组的拓展方法)
Tag 标签
document.getElementsByTagName("")[0] ==> 标签
name 多用于表单 标签

新增的获取查找元素的方法(ES6)
查询选择器 参数是任意css选择器的写法
querySelector() 找第一个
querySelectorAll()找所有的

获取元素再改变元素的几种方式
ele.innerHTML=new html content
ele.attribute=new value
ele.setAttribute(attribute,value)
ele.style.property=new style

<div id="a"></div>
    <p class="a">pppp</p>
    <div class="a"></div>
    <input type="text" name="username">
    <input type="text" name="username2">
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        console.log(document.getElementById('a'));//<div id="a"></div>

        console.log(document.getElementsByClassName('a'));//[p.a, div.a]
        console.log(document.getElementsByClassName('a')[0]);//<p class="a">pppp</p>

        console.log(document.getElementsByTagName("input"));//[input, input, username: input, username2: input]
        console.log(document.getElementsByTagName("input")[0]);//<input type="text" name="username">

        console.log(document.getElementsByName('username'));// [input]
        console.log(document.querySelector('.a'));//类选择器<p class="a">pppp</p>
        console.log(document.querySelector('#a'));//id选择器 <div id="a"></div>
        console.log(document.querySelector('p'));//标签选择器 <p class="a">pppp</p>

        console.log(document.querySelector("ul li"));//<li>1</li>
        console.log(document.querySelector("ul li:nth-child(2)"));//<li>2</li>
        console.log(document.querySelectorAll("ul li"));//<li>1</li>
                                                        //<li>2</li>
                                                        //<li>3</li>

添加和删除元素
document.createElement(element) 创建元素
document.removeChild(element) 删除元素
document.appendChild(element) 添加元素
document.replaceChild(element) 替换元素

获取元素后添加事件处理程序
document.getElementById.οnclick=function(){ }

获取元素后获取元素的属性
attributes 获取元素的所有属性
getAttribute() 获取单个属性值
setAttribute(attribute,value) 添加属性 可覆盖
removeAttribute()移除

获取元素后获取元素的类名
className
classList
remove() 删除类名
add() 添加类名
replace(old , new) 替换类名
Contains()查找 返回布尔值

 <img src="" alt="">
    <a href="" target=""></a>
    <div id="a" class="bb" qq="q" data-hh="h"></div>
    <script>
        var Odiv = document.querySelector("#a");
        console.log(Odiv);
        // 获取元素

        console.log(Odiv.attributes);//id class qq data-hh
        // 获取元素的属性值

        console.log(Odiv.getAttribute('id'));//a
        // 获取元素的单个属性值

        Odiv.setAttribute("my", "hh");
        // 添加属性
        Odiv.setAttribute('class', 'haha hehe')
        // 更改属性<div id="a" class="haha hehe" qq="q" data-hh="h" my="hh"></div>

        Odiv.removeAttribute("my", "hh");
        // 移除属性<div id="a" class="haha hehe" qq="q" data-hh="h"></div>

        // 只有自有属性可以简写  obj.id  obj.href
        // 自定义属性不能简写
        console.log(Odiv.id);   //a
        console.log(Odiv.my);   // undefined

        // class也是自有属性  但是class是关键字
        console.log(Odiv.className);  // 字符串haha hehe
        console.log(Odiv.classList);  // 伪数组["haha", "hehe", value: "haha hehe"]
        console.log(Odiv.classList[1]);//hehe

    </script>

<style>
    ul {
        display: flex;
    }

    li {
        list-style: none;
        padding: 20px;
    }

    .active {
        color: red;
    }
</style>

<body>

    <ul>
        <li class="item active">首页</li>
        <li class="item">新闻中心</li>
        <li class="item">企业文化</li>
    </ul>
    <script>
        var oLi1 = document.querySelector("ul li:nth-child(1)");
        var oLi2 = document.querySelector("ul li:nth-child(2)");
         //oLi2.onclick = function () {
            //oLi1.className = 'item';//换
           // oLi2.className += ' active';//加
       // }
        
        oLi2.onclick = function () {
            // this.classList.add("active")
            //this永远指向绑定事件的这个对象oLi2
            // oLi2.classList.add("active")
            oLi1.classList.remove("active")
            oLi2.classList.replace("item", "active")
        }
        //一般把active显示当前页取的类名
    </script>
</body>

切换状态👇

var oLis = document.querySelectorAll("ul li");
for (i = 0; i < oLis.length; i++) {
            oLis[i].onclick = function () {
                for (var j = 0; j < oLis.length; j++) {
                    oLis[j].classList.remove("active");
                }
                // this.classList.add("active")
                this.className += " active"
            }
        }

循环绑定事件
事件处理函数是异步的
在事件处理函数中 this指向绑定事件的这个对象
在普通函数中 this指向window

特殊标签(表单标签)的特殊属性

<body>
    <button>按钮</button>
    <!-- 默认button可以点 disabled="false" -->
    <!-- <button disabled="disabled">按钮</button> -->
    <input type="text" disabled>
    <input type="checkbox" checked="false">
    <select name="" id="">
        <option value="1">11</option>
        <option value="2" selected>22</option>
        <option value="3">33</option>
    </select>
</body>
<script>
    var oBtn = document.querySelector("button");
    var oChk = document.querySelector('input[type="checkbox"]');
    setTimeout(function () {
        oBtn.disabled = true;//点击后就变灰色
        oChk.checked = false;//点击不勾选
    }, 2000)

</script>

DOM的增删改查

查询
查询指定元素
1.根据id获取元素
document.getElementById(“id属性的值”);

2.根据标签名字获取元素
document.getElementsByTagName(“标签的名字”);

3.根据name属性的值获取元素
document.getElementsByName(“name属性的值”);

4.根据类样式的名字获取元素
document.getElementsByClassName(“类样式的名字”);

5.根据选择器获取元素
document.querySelector(“选择器”);
document.querySelectorAll(“选择器”);

获取到元素后再👇
parentNode 找父元素

children找儿子们
childNodes 找儿子,节点集合(包含换行,标签,文本,注释等节点)

previousSibling 前一个兄弟节点
previousElementSibling 前一个兄弟元素
nextSibling 后一个兄弟节点
nextElementSibling 后一个兄弟元素

firstChild 找第一个子节点 ==childNodes[0]
firstElementChild 找第一个子元素
lastChild
lastElementChild

新增
创建元素 var new=document.createElement(“p”)
插入元素 ele.appendChild(new)插入最后位置
ele.insertBerore(new,old) 把new元素插入到指定的old前面

创建文本 var text=document.createTextNode(‘呵呵’)
插入文本 ele.appendChild(text)

ele.innerHTML += " "

删除
ele.remove() 删除自己
ele.removeChild()删除自己指定的子元素,不能删除隔代子孙
ele.innerHTML = ’ ’ 删除所有的子元素

修改
ele.replaceChild(new,old )

复制(克隆)
cloneNode() 默认false 只复制标签自己
cloneNode(true) 复制标签及子元素

js当中 换行,注释,标签,属性都称为节点
只有标签称为元素 element

有两个特殊属性允许访问完整文档:
document.body - 文档的 body
document.documentElement - 完整文档

nodeType 节点类型 数字(只读)
文本节点 3
标签节点 1
注释节点 8
属性节点 2

nodeName 节点的名称 字符串(只读)
文本节点 #text
标签 P / H3 / DIV
注释 #comment

nodeValue 节点的值 字符串

  <div class="a">
        111
        <p>11</p>
        <span>222</span>
        <!-- 注释 -->
        <h3></h3>
    </div>
        var oDiv = document.querySelector('div');
        var childNodes = oDiv.childNodes;

        console.log(childNodes[0].nodeName);  // #text
        console.log(childNodes[0].nodeType);  // 3
        console.log(childNodes[0].nodeValue);  // 3

        console.log(childNodes[1].nodeName);  // P
        console.log(childNodes[1].nodeType);  // 1
        console.log(childNodes[1].nodeValue);  // null

        console.log(childNodes[5].nodeName);  // #comment
        console.log(childNodes[5].nodeType);  // 8
        console.log(childNodes[5].nodeValue);  // null


        console.log(document.nodeType);  // 9

        console.log(document.doctype.nodeType);  // 10

        console.log(oDiv.attributes[0].nodeType);
 

创建新 HTML 元素(节点)
如需向 HTML DOM 添加新元素,您必须首先创建这个元素(元素节点),然后将其追加到已有元素。
实例👇

<div id="div1">
<p id="p1">这是一个段落。</p>
<p id="p2">这是另一个段落。</p>
</div>

<script>
var para = document.createElement("p");//创建新标签元素
var node = document.createTextNode("这是新文本。");
para.appendChild(node);//向<p>元素追加这个文本节点

var element = document.getElementById("div1");//查找一个已有的元素
element.appendChild(para);//已有的元素追加新元素
//var child = document.getElementById("p1");
//element.insertBefore(para, child);//也可以
</script>
<body>
    <p>111</p>
    <ul id="list"></ul>
    <script>
        // 页面的回流与重绘    渲染

        // 所有css都会引发重绘   不一定回流
        // 回流必定会引发重绘

        // margin-top    translateY
        // font-size:100px   transform:scale()

        // display:none   opacity:0    visibility:hidden

        var oUl = document.querySelector('#list');

        // 创建10个li

        // for (var i = 0; i < 10; i++) {
        //     var oLi = document.createElement('li');
        //     oLi.innerHTML = i;
        //     oUl.appendChild(oLi)   // 引发10次回流
        // }

        // 文档碎片
        var fragment = document.createDocumentFragment();
        console.log(fragment);
        for (var i = 0; i < 10; i++) {
            var oLi = document.createElement('li');
            oLi.innerHTML = i;
            fragment.appendChild(oLi)
        }
        oUl.appendChild(fragment)  // 只会引发一次回流

        // 要尽量的减少DOM操作
    </script>
</body>

css样式可以设置也可以获取
设置
ele.style.color = ‘red’
ele.style.cssText = ‘color:red;font-size:30px’ 可一次性设置多个样式
ele.classList.add(‘c’) 推荐
获取
ele.style.color 只能获取行内样式
getStyle(ele,attr) 自己封装的兼容的函数
getComputedStyle
currentSyle

  // 获取样式的兼容写法
    function getStyle(ele, attr) {
        if (window.getComputedStyle) {
            return getComputedStyle(ele)[attr]
        }
        return ele.currentStyle[attr]
    }
 var oDiv = document.querySelector('div');
        // oDiv.style.color = 'green';
        oDiv.style.background = 'gray';
        oDiv.style.fontSize = '30px';
        // oDiv.style.cssText = "font-size:30px;border:1px solid #000";
        oDiv.classList.add('c');

        // getComputedStyle(ele).属性
        // ele.currentStyle.属性

        // console.log(getComputedStyle(oDiv).height);


        // console.log(oDiv.currentStyle.height);


        console.log(getStyle(oDiv, 'height'));

ele.style.width 获取的是css设置的宽
ele.clientWidth width + padding
ele.offsetWidth width + padding + border
ele.offsetLeft / offsetTop 距离最近的具有定位的祖先元素的距离

事件:被触发并得到回应
事件:事件源+事件处理函数

常见的事件绑定方式

//1.行内js 
<button onclick=("fn("hello")")>按钮</button>
function fn(n){
    console.log(n)
}

//2.直接获取对象,会覆盖前面的事件
var btn=document.querySelector("button")
btn.onclick=function(){
   
}

//3.事件监听addEventListener("click",function(){},是否支持捕获流(默认不支持false))  
//优势:可同时绑定多个同类型的事件,不会覆盖
btn.addEventListener("click",function(){
    console.log(777);
})
//事件监听的兼容写法(IE低版本)
btn.attachEvent("onclick",function(){
     console.log(777);
})

事件监听程序的方法允许您向相同元素添加多个事件,同时不覆盖已有事件:

//绑定--封装后的兼容写法
function addEvent(ele,type,cb){
    if(window.addEventListener){
        ele.addEventListener(type,cb)
    }else{
        ele.attachEvent("on"+type,cb)
    }
}

addEvent("btn","click",function(){
console.log(777);
})


移除事件绑定(用空对象覆盖之前的函数)
<button onclick=("fn("hello")")>按钮</button>
function fn(n){
    console.log(n)
}
setTimeout(function(){
    btn.onclick=null
},2000)

事件监听方式绑定的方式如果移除需要挨个移除,具名函数好移除

//移除--封装后的兼容写法
function removeEvent(ele,type,cb){
    if(window.EventListener){
        ele.removeEventListener(type,cb)
    }else{
        ele.detachEvent("on"+type,cb)
    }
}

removeEvent("btn","click",fn1)


//fn1具名函数

案例👇

<button onclick="fn()">按钮</button>
    <script>
        function fn() {
            console.log(2);
        }
        var oBtn = document.querySelector('button');
        setTimeout(function () {
            oBtn.onclick = null;
            // oBtn.removeEventListener('click', fn1)
            // oBtn.removeEventListener('click', fn2)
            //不考虑兼容的移除绑定的写法
            removeEvent(oBtn, 'click', fn1)
        }, 3000)

        oBtn.addEventListener('click', function () {
            console.log(6);
        })

        oBtn.addEventListener('click', fn1)
        oBtn.addEventListener('click', fn2)
        function fn1() {
            console.log(7);
        }
        function fn2() {
            console.log(8);
        }
        //fn写成具名函数好移除
        
        function removeEvent(ele, type, cb) {
            if (window.removeEventListener) {
                ele.removeEventListener(type, cb)
            } else {
                ele.detachEvent('on' + type, cb)
            }
        }
    </script>

事件监听的参数实际上有三个
addEventListener(事件类型,事件处理函数,是否支持捕获流)
(默认不支持false捕获流,即默认true冒泡流从内到外))

事件流: 事件捕获阶段,处于目标阶段,事件冒泡阶段

捕获流:从外到内event capturing Netscape
冒泡流:从内到外event bubbling IE

主流浏览器都支持冒泡流

事件对象:浏览器专门记录事件发生的整个过程的一个对象
事件处理函数的第一个参数

//this -> body  绑定事件的对象   
//target -> p   指向具体触发事件的标签 
//事件对象的兼容写法
document.onclick=function(e){
    //event是IE低版本的事件对象
    var e=e||event;
    var target=e.target||e.srcElement;
}

阻止事件冒泡(不向外传播)

e.stopPropagation();//阻止事件冒泡
if(e.stopPropagation){
    e.stopPropagation()
}else{
    //低版本IE阻止事件冒泡的方式
   e.cancleBubble=true 
}

案例👇

<style>
        .big {
            width: 500px;
            height: 500px;
            background-color: #000;
            border: 1px solid #000;
        }

        .box {
            width: 300px;
            height: 300px;
            background-color: #0f0;
            border: 1px solid #0f0;
            margin: 100px;
        }

        .small {
            width: 100px;
            height: 100px;
            margin: 100px;
            background-color: #f00;
        }
</style>
    
    
<div class="big">
     <div class="box">
         <div class="small">1111111</div>
     </div>
</div>
<script>
        // 事件不向外传播  --- 阻止事件冒泡
        $('.big').addEventListener('click', function () {
            console.log('big');
        })
        $('.box').addEventListener('click', function () {
            console.log('box');
        })
        $('.small').addEventListener('click', function (e) {
            var e = e || event;
            // 阻止事件冒泡
            // e.stopPropagation();
            if (e.stopPropagation) {
                e.stopPropagation()
            } else {
                // 低版本IE阻止事件冒泡的写法
                e.cancelBubble = true
            }
            console.log('small');
        })
        function $(e) {
            return document.querySelector(e)
        }
    </script>

事件委托(委托给别人做)
原理:事件冒泡(给父元素添加事件,判断哪个子元素触发的)

性能:页面上的事情处理函数越多,性能就越差

解决两个问题:
1. 事件处理函数过多 消耗性能
2. 无法给未来的对象添加事件

事件委托优点:
只有一个事件处理函数
可以给未来的对象添加事件绑定 !!!

<ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    
 var oUl = document.querySelector('ul')
 
 setTimeout(function () {
        var li = document.createElement('li');
        li.innerHTML = '我是后来的6';
        oUl.appendChild(li)
  }, 1000)
  
 oUl.addEventListener('click', function (e) {
            // console.log(666);
            var e = e || event;
            var target = e.target || e.srcElement;
            console.log(target.innerHTML);
            console.log(this);
            // this 和 target 的区别
          //this 永远指向绑定事件的这个对象
          //target 更具体的标签 p h3  li ...
        })

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值