javascript基础3

DOM

简介

  • DOM:Document Object Model文档对象模型
  • JS通过DOM来对HTML文档进行操作,操作WEB页面
    • 文档:网页,一个HTML页面
    • 对象:网页的每一部分都转换为对象
    • 模型:使用模型表示对象之间的关系,方便获取对象

节点和属性

  • 网页的最基本组成部分,网页找那个的每一个部分都可以称为是一个节点。比如html标签、属性、文本、注释、整个文档都是一个节点。
  • 节点类型不同。
    • 文档节点:整个HTML文档
    • 元素节点:HTML中的HTML标签
    • 属性节点:元素的属性
    • 文本节点:HTML标签中的文本内容

  • 节点类型不同,属性和方法也不同

/**
* 浏览器已经提供了文档节点,这个对象是window
* 可以在页面中直接使用,文档节点代表的是整个网页
*/
console.log(document);//document
<button id="btn">我是一个按钮</button>
<script>
    //获取btn对象
    let btn=document.getElementById("btn");
    console.log(btn);//button#btn
    //修改按钮文字
    btn.innerHTML='我是一个哥哥    按钮';
</script>

事件

用户和浏览器的一些交互行为。例如,点击按钮,鼠标移动,关闭窗口。

  • 可以在事件对应的属性中设置一些js代码,这样当事件被触发时,这些代码将会执行。
//这种方式不方便使用,结构耦合
<button id="btn" onclick="alert('你点我干嘛')">我是一个按钮</button>


  • 为事件绑定函数处理响应,当事件被触发时,对应的函数会被执行
<button id="btn">我是一个按钮</button>
<script>
var btn=document.getElementById('btn');
btn.onclick=function(){
    alert('你还点');
};
</script>

文档加载

浏览器加载页面

  • 自上而下,读取一行执行一行
  • 如果将script代码写到html页面上边,则在script代码执行时,页面还没有加载,导致页面加载时无法获取到函数。
  • 所以将script代码写到html页面下边,确保页面加载完毕以后再执行js代码。
  • 如果想要写在页面上边,需要:onload()事件,将在加载完页面之后触发
    <script>
            window.onload=function(){
            //获取id为btn的按钮
            let btn=document.getElementById('btn');
            //为按钮绑定一个单击响应函数
            btn.onclick=function(){
                alert('hello');
            };
        };
    </script>
    

DOM查询

获取元素节点

通过document对象调用

1.getElementById() 根据id获取一个元素节点对象

var bj = document.getElementById("bj");

2.getElementsByTagName() 根据标签名获取一组元素节点对象

  • 这个方法会给我们返回一个类数组对象,所有查询到的元素都会封装到对象中
  • 即使只有一个元素,返回的也是数组
var lis = document.getElementsByTagName("li");
//可以循环打印

3.getElementsByName() 根据name属性获取一组元素节点对象

  • innerHTML用于获取元素内部的HTML代码,对于自结束标签,这个属性没有意义
  • 读取元素节点属性,元素.属性名
  • 读取class属需要使用 元素.className
var inputs = document.getElementsByName("gender");

获取元素节点的子节点

通过具体的元素节点调用

1. getElementsByTagName() 返回当前节点的指定标签名后代节点

//获取city节点
let city=document.getElementById("city");
//获取city下边的 li
let btn04_lis_num=city.getElementsByTagName("li")
for (let i = 0, len = btn04_lis_num.length; i < len; i++) {
	console.log(btn04_lis_num[i].innerHTML);
}

2. childNodes 当前节点的所有子节点

  • 会获取包括文本节点在内的所有节点
  • 会将空白文本当成文本节点
//获取city节点
let city=document.getElementById("city");
// 返回city的所有子节点
let btn05_lis_num=city.childNodes;

3. children 当前节点的所有子元素(即标签)

let btn05_lis_num_1=city.children;
for (let i = 0, len = btn05_lis_num_1.length; i < len; i++) {
	console.log(btn05_lis_num_1[i].innerHTML);//北京、上海、东京、首尔
}

4. firstChild 当前节点的第一个子节点

  • firstElementChild 第一个子元素 (推荐使用)

5. lastChild 当前节点的最后一个子节点

    • lastElementChild 最后一个子元素(推荐使用)
//获取phone节点
let phone=document.getElementById("phone");
// 返回phone的第一个子节点
let btn06_lis_num=phone.firstChild;
console.log(btn06_lis_num.innerHTML);
// 返回phone的最后一个子节点
let btn06_lis_num_1=phone.lastChild;

6. parentChild 当前节点的父节点

  • 只返回一个父节点
  • innetHtml 内部html代码
  • inneText 内部文本内容,自动去除html
let bj=document.getElementById("bj");
let bj_parent=bj.parentNode;
console.log(bj_parent.nodeName);

7. previousSibling 前一个兄弟节点

8. nextibling 后一个兄弟节点

let android=document.getElementById("android");
let android_previous=android.previousSibling;
console.log(android_previous.innerHTML);

其他方法

1.body body的引用

let body=document.body;
console.log(body); //<body>...</body>

2.documentElement html根标签

let de=document.documentElement;
console.log(de);

3.document.all 页面中所有的标签

let all=document.all;
//all=document.getElementsByTagName("*");同效
console.log(all);
//HTMLAllCollection(9)[html, head, meta, meta, meta, title, script, body, script, viewport: meta]

3.getElementsByClassName 根据class名查找节点

CSS选择器查询节点

1.querySelector(str) 根据CSS选择器查询节点

  • 只会返回一个节点(多个,则返回1个)
//查询类名box1下的所有div
document.querySelector(".box1 div");

1.querySelectorAll(str)

  • 返回一组节点
  • 封装到数组中返回(即使符合条件的元素只有一个)
document.querySelectorAll(".box1 div");

DOM增删改

1.createElement(str) 创建元素节点

  • document调用
    2. appendChild() 将新的子节点添加到指定的父节点末尾
  • 父节点调用
let gz=document.createElement("li");
gz.innerHTML="广州";

let city=document.getElementById("city");
city.appendChild(gz);
//city.innerHTML += `<li>广州</li>`

3.insertBefore(新节点,旧节点) 在指定的子节点前插入新的子节点

  • 父节点调用
let bj=document.getElementById("bj");
city.insertBefore(gz,bj);

3.replaceChild(新节点,旧节点) 使用指定的子节点替换已有的子节点

  • 父节点调用
city.replaceChild(gz,bj);

4.removeChild(指定节点) 删除指定子节点

  • 父节点调用
city.removeChild(bj);
//bj.remove();
//bj.parentNode.removeChild(bj)

DOM操作CSS内联样式

  • 通过style修改的属性都是内联样式(但是如果在样式中写!important,此时修改js失效)
  • 如果CSS样式名中有**-**,需要将样式名修改为驼峰 font-style-->fontStyle
  • 通过style属性,读取和设置的都是内联样式,无法读取样式表中的样式
元素名.style.property=a;

box1.style.width="300px";
//修改为驼峰
box1.style.backgroundColor="yellow";

DOM操作CSS当前样式

  • 当前元素正在显示的样式(CSS和内联,谁生效,读取谁)
  • currentStyle只能在 ie 支持
    • 如果获取样式的没有设置,会获取到默认样式
  • getComputedStyle(元素,可以传递伪元素,一般为null)
    • 返回对象,封装元素对应的样式
    • 如果获取样式的没有设置,会获取到真实的值,而不是默认样式
    • 不支持ie8及一下浏览器
  • 以上二者都是只读样式
//只能在 ie8 使用
元素.currentStyle.样式名
console.log(box1.currentStyle.width);

//getComputedStyle(元素名,null) 正常浏览器
getComputedStyle(box1,null).width;

  • getStyle(obj,name) 自定义
//获取元素当前样式  处理兼容性问题
function getStyle(obj,propertyName){
    if(window.getComputedStyle){
    //正常浏览器
    //getComputedStyle是全局属性
        return getComputedStyle(obj,null)[name];
    }
    else{
        //ie8
        return obj.currentStyle[name];
    }
}

DOM操作其他样式的相关属性

1. clientWidth 元素可见宽度

2. clientHeight 元素可见高度

  • 不带px,返回数字,可以直接计算
  • clientWidth=内容区+内边距
  • 这些属性都是只读的
 #box1{
    width: 100px;
    height: 100px;
    background-color: red;
    padding: 10px;
    border: 10px solid blue;
}

console.log("clientWidth="+box1.clientWidth);//120

3. offsetwidth offsetHeight 获取元素整个宽度和高度

  • offsetwidth=内容区+内边距+边框
console.log("offsetWidth="+box1.offsetWidth);//140

4. offsetParent 获取当前元素的定位父元素

  • 获取到离当前元素最近的开启了定位的祖先元素
  • 如果找不到则返回body
let op=box1.offsetParent
console.log(op);//div2

5. offsetLeft offsetTop 当前元素相对于其父元素的偏移量

console.log(box1.offsetLeft);                
console.log(box1.offsetTop); 

6. scrollHeight scrollWidth 整个滚动区域的宽度和高度

<div id="box4">
    <div id="box5"></div>
</div>
#box4{
    width: 200px;
    height: 300px;
    background-color: #bfa;
    overflow: auto;
}
#box5{
    width: 250px;
    height: 600px;
    background-color: yellow;
}

console.log(box4.scrollHeight);//600
console.log(box4.scrollWidth);//250

7. scrollLeft scrollTop 滚动条滚动的距离

console.log(box4.scrollLeft);//滚动条的水平偏移量
console.log(box4.scrollTop);//滚动条的垂直偏移量

可以判断滚动条是否到底了
当scrollHeight-srollTop=clientHeight说明,垂直滚动条到底了

事件对象

  • 当响应函数触发被触发时,浏览器每次都会将事件对象作为实参传递给响应函数
  • 事件对象封装了当前对象的一切信息
e就是事件对象
p.onclick=function(e){}
  • 在IE8中,不会传递事件对象。而是将事件对象作为window的对象存储的
let x=window.e.clientX;

处理兼容性

if(!event){
    event=window.event;
}
event=event || window.event;

1. onmousemove 鼠标移动事件

let areaDiv=document.getElementById("areaDiv");
let showMsg=document.getElementById("showMsg");
areaDiv.onmousemove=function(e){
    e=e || window.e;
    // 在showMsg显示鼠标的坐标
    //浏览器知道鼠标的坐标
    showMsg.innerHTML="("+e.clientX+","+e.clientY+")";
        }

clientX  获取鼠标在当前可见窗口的坐标
//div是相对于html页面的
//当页面超出浏览器窗口,鼠标位置和div的偏移量就不同了

pageX  鼠标相当于页面的坐标(ie8不支持)
let x=e.pageX;
let y=e.pageY;
    // 获取鼠标滚动条的距离
	// 谷歌认为浏览器的滚动条是body的
	// let st=document.body.scrollTop;
	// 火狐等认为浏览器滚动条是html的
	// let st1=document.documentElement.scrollTop;
	// 处理兼容性
	st=document.body.scrollTop || document.documentElement.scrollTop;

事件的冒泡Bullbe

  • 事件的向上传导:当后代元素事件被触发时,其祖先相同的事件也会被触发
点击span,触发span的响应函数,
然后触发div的响应函数,
然后触发body的响应函数
<body>
    <div id="box1">
        我是box1
        <span id="s1">我是span</span>
    </div>
</body>

<script>
    window.onload=function(){
        //为s1绑定单击响应函数
        let s1=document.getElementById("s1");
        s1.onclick=function(){
            alert('我是span的单击函数');
        }
        //为box1绑定单击响应函数
        let box1=document.getElementById("box1");
        box1.onclick=function(){
            alert('我是div的单击函数');
        }
        //为body绑定单击响应函数
        document.body.onclick=function(){
            alert('我是body的单击函数');
        }
    }
</script>

取消冒泡用事件对象取消冒泡

s1.onclick=function(e){
    e.cancelBubble=true;
}

事件的委派

  • 将事件统一绑定给共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数处理事件
  • 通过委派,减少绑定的次数,提高性能
//为每个超链接绑定点击事件
//当创建新的超链接时,需要重新绑定响应事件,代码冗余
for (let i = 0, len = allA.length; i < len; i++) {
    allA[i].onclick=function(){
}

//将点击事件绑定到共同的祖先元素ul上
u1.onclick=function(){
    // 绑定到ul上,这样点击超链接,事件可以冒泡到ul上,也
    alert('msg');
}

target 触发事件的对象

问题:绑定到父元素,父元素的整个内容区都会触发事件,效果不好

//判断点击a才会执行触发事件
u1.onclick=function(event){
    //判断点击a才会执行触发事件
    event=event || window.event;
    //target:触发事件的对象
    if(event.target.className=='link'){
        alert('msg');
    }
}

事件监听器绑定 addEventListener

使用对象.事件绑定函数

  • 只能同时为一个元素的一个事件绑定给一个响应函数
  • 如果绑定多个,后边的会覆盖前边的

事件监听器绑定函数addEventListener()

  • 可以绑定多个函数
  • 参数
    • 事件类型,不要on,例如click
    • 回调函数:当事件触发时调用回调函数
    • 是否在捕获阶段触发事件,一般为false
  • 多个事件按照函数绑定的顺序执行(1,2,3)
  • 返回绑定事件的对象
btn01.addEventListener("click",function(){
    alert('msg');
},false);
btn01.addEventListener("click",function(){
    alert('dddddd');
},false);
  • 不支持IE8及以下浏览器
    • 使用attachEvent()
    • 参数:1.事件类型,要on
    • 2.回调函数
    • 后绑定,先执行(3,2,1)
    • 返回window
btn01.attachEvent("onclick",function(){
    alert('dddddd');
});

处理兼容性

function bind(obj,eventStr,callback){
    // 判断对象
    if(obj.addEventListener){
        //正常浏览器
        obj.addEventListener(eventStr,callback,false);
    }
    else{
        
        //IE8及以下
        // obj.attachEvent("on"+eventStr,callback);
        
        //this是由调用方式决定的
        //修改this为btn01
            // callback是浏览器调用的,所以this=window
            //修改callback由匿名函数调用
        obj.attachEvent("on"+eventStr,function(){
            // 在匿名函数中调用回调函数,由自己调用
            //然后使用call()方法改变this的指向
            callback.call(obj);
        });
    }

事件的传播

事件的冒泡--->由内向外传播

事件的捕获--->由外向内传播

W3C综合:

  • 捕获阶段
    • 在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但默认此时不会触发事
  • 目标阶段
    • 事件捕获到目标元素,捕获结束
  • 冒泡阶段
    -事件从目标元素向祖先元素传播,依次触发祖先元素上的事件
  • 如果希望在捕获阶段就触发事件,可以将addEventListener的false设置为true

E8及以下浏览器没有捕获

问题

  1. 当我们拖拽网页中的内容时,浏览器会默认去搜索
    引擎中搜索内容,导致拖拽功能异常

在对应的事件后添加  return false
  1. 当调用一个元素的setCapture()方法以后,这个元素会将下一次所有的鼠标按下的相关事件捕获到自身身上
只捕获一次,只有IE支持,需要处理兼容性
box1.setCapture && box1.setCapture()
btn01.setCapture();//点击按钮2时执行的也是按钮1

box1.releaseCapture();//取消捕获,同理

滚轮事件 onmousewheel

火狐不支持该事件。

火狐:DOMMouseScroll,并且使用事件监听器绑定
事件监听器取消默认行为:enevt.preventDefault();
s但是IE8不兼容,所以如下:
enevt.preventDefault && enevt.preventDefault()
box1.onmousewheel=function(e){
    //判断鼠标滚轮的方向
    e=e||window.e;
    console.log(e.wheelDelta);//获取鼠标滚轮的方向
    //向上滚 正数  向下滚 负数 
    //火狐不支持wheelDelta  使用e.detail
    if(e.wheelDelta>0 || e.detail<0){
        // 向上滚
        box1.style.height=box1.clientHeight-10+"px";
    }else{
        // 向下滚
        box1.style.height=box1.clientHeight+10+"px";
    }
    /**
     * 当滚轮滚动时,若浏览器有滚动条,则滚动条会随之移动
     * 这是浏览器的默认行为,取消 return false

键盘事件 onkeydown onkeyup

  • 键盘事件一般绑定到一些可以获取焦点的对象或者document
document.onkeydown=function(){
    //按键被按下
}
document.onkeyup=function(){
    //按键松开

onkeydown

  • 如果按键一直按着,则事件一直被触发
  • 当onkeydown连续触发时,第一次和第二季次隔稍微长一些(放置误操作)
  • 可以通过keyCode获取按键的ASCII编码
  • altKey alt是否被按下 按下返回true
  • ctrlKey 是否被按下 按下返回true
  • shiftKey shift是否被按下 按下返回true
e=e||window.e;
console.log(e.keyCode+"被按下");

onkeydown

  • 不会连续触发

取消事件默认行为 return false

e=e|| window.e;
if(e.keyCode>=48 && e.keyCode<=57){
    return false;
}

BOM

DOM:通过js操作网页

BOM:浏览器对象模型

  • 通过js操作浏览器
  • BOM提供了一组对象,用来完成浏览器的操作
    • window
    • navigator
    • History
    • Screen

window

  • 代表占整个浏览器的窗口,同时也是网页中的全局对象
  • 属性和方法
    • setInterval(fun,time)定时调用(每间隔一段时间调用一次)时间:毫秒
      • setInterval返回的数字代表计时器的编号
    setInterval(function(){
        c.innerHTML++;
    }, 1000);
    
    • setTimeout()延时调用(隔一段时间以后执行,只执行一次)
    setTimeout(function(){
        console.log('ddd');
    },2000);
    
    • clearInterval(计时器数字标识或名称)关闭计时器
      • 可以接受任何参数。
        若参数有效,则停止计时器;若参数无效,则什么也不做。
    let timer=setInterval(function(){
    c.innerHTML++;
    if(c.innerHTML==11){
        c.innerHTML(timer);
    }
    }, 1000);
    
    clearInterval(timer);
    
    • clearTimeout(timer):关闭延时调用
  • 当前浏览器的信息,通过该对象识别不同的浏览器
  • 由于历史原因,navigator对象中的大部分属性都不能帮助识别浏览器。
  • 一般使用userAgent来判断浏览器的信息。字符串中包含描述浏览器信息的内容
  • 若userAgent无法判断,还可以浏览器特有的信息来判断。
//正则表达式判断
if(/firefox/i.test(navigator.userAgent)){
    console.log("火狐");
}else if(/chrome/i.test(navigator.userAgent)){
    console.log("chrome");
}else if(/msie/i.test(navigator.userAgent)){
    console.log("IE");
}


//IE11不好判断时
if("ActiveXObject" in window)
{
    console.log("IE11");
}else{
    console.log("不是IE");

Location

  • 代表浏览器的地址栏信息,通过Location可以操作浏览器跳转页面
  • 如果直接将location修改为一个完整的路径或相对路径,页面则跳转到该路径,并生成历史记录。
  • 属性和方法
    • assign():跳转到其他页面。有历史记录
    location.assign();
    
    • reload():重新加载当前页面,刷新
    location.reload();
    
    location.reload(ture);强制清空缓存,刷新
    
    • replace():使用新的文档替换当前文档。不能生成历史记录

History

  • 代表浏览器的历史记录,可以操作浏览器的历史记录
  • 由于隐私的原因,不能获取具体的历史记录,只能操作浏览器前后翻页
  • 只在当次访问时有效
  • 属性和方法
    • length:获取到当次访问链接的数量
    console.log(history.length);
    
    • back():回退到上一个页面
    history.back();
    
    • forward():跳转到下一个页面
        history.forward();
    
    • go(num):跳转到指定页面,参数表示向前跳转几个页面
      • 正数向前,负数向后
    history.go(2);
    

Screen

  • 代表用户屏幕信息,显示器的相关信息

这些BOM对象在浏览器中都是作为window对象的属性保存的,可以window调用,也可以直接使用。

console.log(navigator);
console.log(location);
console.log(history);
console.log(screen);

类的操作

  • 浏览器通过style修改样式,每修改一个样式,浏览器就重新渲染一次页面,效率低下
// 不建议大量用次方法
box1.style.width="200px";
box1.style.height="200px";
box1.style.backgroundColor="yellow";
  • 仅用一行代码,修改多个样式
    • 修改元素的class属性
    //不再通过js改变具体的样式,是js和CSS分离
    <div id="box1" class="b1"></div>
    
    //js  修改box的class属性
    box1.className="b2";
    
    box1.className+=" b2";
    addClass(box1,"b2")//用函数添加
    
/**
 * 切换
 * 有,则添加
 * 没有  则删除
 */
function toggleClassName(obj,cn){
    let reg=new RegExp("\\b"+cn+"\\b");
    if(!hasClass(obj,cn)){
        obj.className +=" "+cn;
    }else{
        removeClassName(obj,cn);
    }
}

// 判断是否已经存在指定的class属性值cn
function hasClass(obj,cn){
    //使用正则表达式判断
    // let reg=/\bb2\b/;//\b单词边界
    let reg=new RegExp("\\b"+cn+"\\b");
    return reg.test(obj.className);
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值