多张动图带你详细了解JavaScript[WebAPI]


一、WebAPI背景知识

1.什么是WebAPI

前面学习的JS分成三个大的部分

ECMAScript:基础语法部分
DOM API:操作页面结构
BOM API:操作浏览器

webAPI就包含了DOM+BOM
这个是W3C组织规定的

前面学习的JS基础语法主要学的是ECMAScript,这让我们建立基本的编程思维,相当于练武需要先扎马步
真正来写一个更加复杂的有交互式的页面,还需要WebAPI的支持,相当于各种招式

2.什么是API

API是一个更广义的概念,而WebAPI是一个更具体的概念,特指DOM+BOM
所谓的API本质上就是一些现成的函数/对象,让程序员拿来使用,方便开发

相当于一个工具箱

二、DOM基本概念

1.什么是DOM

DOM全称为Document Object Model,页面文档对象模型。
W3C标准给我们提供了一系列的函数,让我们可以操作

网页内容
网页结构
网页样式

2.DOM树

一个页面的结构是一个树形结构,称为DOM树
相当于html树形结构,为一个多子树结构(一个节点下可以有多个)
页面结构形如:
在这里插入图片描述
重要概念:

  • 文档:一个页面就是一个文档,使用document表示
  • 元素:页面中所有的标签都称为元素,使用element表示
  • 节点:网页中所有的内容都可以成为节点(标签节点,注释节点,文本节点,属性节点等),使用node表示

这些文档等概念在JS代码中就对应一个个的对象,这也就是”文档对象模型“的由来

三、事件初识

1.基本概念

JS要构建动态页面,就需要感知到用户的行为
用户对于页面的一些操作(点击、选择、修改等)操作都会在浏览器中产生一个个事件,被JS获取到,从而进行更复杂的交互操作

浏览器就是一个哨兵,在侦查敌情(用户行为),一旦用户有反应(触发具体动作),哨兵就会点燃烽火台的狼烟(事件),后方就可以根据狼烟来决定下一步的对敌策略

2.事件三要素

  1. 事件源:哪个元素触发的
  2. 事件类型:用户操作的类型,是点击、选中,还是修改
  3. 事件处理程序:事件发生之后需要做什么,进一步如何处理,往往是一个回调函数,在事件发生以后,由浏览器自动执行里边的代码

在这里插入图片描述

3.简单示例

<button id="btn">点我一下</button>
<script>
    var btn=document.getElementById('btn');
    btn.onclick = function () {
    
    
        alert("hello world");
    }
</script>

展示结果:
在这里插入图片描述

  • btn按钮就是事件源
  • 点击就是事件类型
  • function这个匿名函数就是事件处理程序
  • 其中btn.onclick = function()这个操作称为注册事件/绑定事件

注意: 这个匿名函数相当于一个回调函数,这个函数不需要程序员主动来调用,而是交给浏览器,由浏览器自动在合适的时机(触发点击操作时)进行调用

4.主要流程

1.事件源:学习如何选择页面元素(DOM API中,把这些页面元素也称为dom元素)
2.调用dom元素的API来做事情
<标签名 属性1名称=“属性1值” 属性2名称=“属性2值”>标签内容<标签名>
(1)设置属性(比如style属性就是样式,on开头的就是事件属性)
(2)设置标签内容
设置为普通文本:比如把p标签设置一些内容
设置为复杂的dom内容:比如有一个div,内部可以设置其他标签(如span)

四、获取元素

这部分工作类似于CSS选择器的功能

1.querySelector

这个是HTML5新增的,IE9及以上版本才能使用

前面的几种方式获取元素的时候都比较麻烦,而使用querySelector能够完全复用前面学过的CSS选择器知识,达到更快捷更精准的方式获取到元素对象

var element = document.querySelector(selectors);

在这里插入图片描述

  • selectors包含一个或多个要匹配的选择器的DOM字符串DOMString。该字符串必须是有效的CSS选择器字符串 ;如果不是,则引发SYNTAX_ERR异常
  • 表示文档中与指定的一组CSS选择器匹配的第一个元素的html元素Element对象
  • 如果您需要与指定选择器匹配的所有元素的列表,则应该使用querySelectorAll()
  • 可以在任何元素上调用,不仅仅是document。调用这个方法的元素将作为本次查找的根元素
 <div class="box">abc</div>
<div id="id">def</div>
<h3><span><input type="text"></span></h3>
<script>
    var elem1 = document.querySelector('.box');
    console.log(elem1);
    var elem2 = document.querySelector('#id');
    console.log(elem2);
    var elem3 = document.querySelector('h3 span input');
    console.log(elem3);
</script>

展示结果:
在这里插入图片描述

2.querySelectorAll

如果选择器返回多个元素,需要使用querySelectorAll方法,返回一个数组,内部包含匹配到的多个元素
使用querySelectorAll用法和上面类似

<div class="box">abc</div>
<div id="id">def</div>
<script>
    var elems = document.querySelectorAll('div');
    console.log(elems);
</script>

展示结果:
在这里插入图片描述

<p>张三今晚在学习</p>
<p>李四今晚在打游戏</p>
<p>王五今晚在和女朋友聊天</p>
<script>
    var arr = document.querySelectorAll("p");
    //数组的遍历
    //方式1:下标的方式
    for(let i=0;i<arr.length;i++){
    
    
        console.log(arr[i]);
    }
    //方式2:of的方式
    for(let e of arr){
    
    //类似Java中一个int[],for(int x : int[])
        console.log(e);
    }
</script>

五、操作元素

1.获取/修改元素内容

1.innerText
Element.innerText属性表示一个节点及其后代的”渲染“文本内容

//读操作
var renderedText = HTMLElement.innerText;
//写操作
HTMLElement.innerText = string;

不识别HTML标签,是非标准的(IE发起的),读取结果不保留html源码中的换行和空格

<div>
    <span>hello world</span>
    <span>hello world</span>
</div>
<script>
    var div = document.querySelector('div');
    //读取div内部内容
    console.log(div.innerText);
    //修改div内部内容,界面上会同步修改
    div.innerText = 'hello js <span>hello js</span>';
</script>

展示结果:
在这里插入图片描述
可以看到,通过innerText无法获取到div内部的html结构,只能得到文本内容,修改页面的时候也会把span标签当成文本进行设置
2.innerHTML
Element.innerHTML属性设置或获取HTML语法表示的元素的后代

//读操作
var content = element.innerHTML;
//写操作
element.innerHTML = htmlString;

1.先获取到事件源的元素
2.注册事件

识别html标签,W3C标准的,读取结果保留html源码中的换行和空格

展示结果:

<div>
    <span>hello world</span>
    <span>hello world</span>
</div>
<script>
    var div = document.querySelector('div');
    //读取页面内容
    console.log(div.innerText);
    //修改页面内容
    div.innerHTML = '<span>hello js</span>';
</script>

可以看到innerHTML不光能获取到页面的html结构,同时也能修改结构,并且获取到的内容保留空格和换行

innerHTML用的场景比innerText更多

2.获取/修改元素属性

可以通过Element对象的属性来直接修改,就能影响到页面显示效果
(1)可以使用console.dir查看元素对象中的属性

<img src="rose.jpg" alt="这是一朵花"  title="玫瑰花">
<script>
    var img = document.querySelector('img');
    console.dir(img);
</script>

展示结果:
在这里插入图片描述
此时可以看到img这个Element对象中有很多属性
在这里插入图片描述
(2)可以使用 对象.属性/对象[‘属性’] 来赋值或获取值

<img src="rose.jpg" alt="这是一朵花"  title="玫瑰花">
<script>
    var img = document.querySelector('img');
    //console.dir(img);
    console.log(img.src);
    console.log(img.title);
    console.log(img.alt);
</script>

展示结果:
在这里插入图片描述
还可以直接修改属性

<img src="rose.jpg" alt="这是一朵花"title="玫瑰花">
<script>
    var img = document.querySelector('img');
    img.onclick = function () {
    
    
        if(img.src.lastIndexOf('rose.jpg') !== -1) {
    
    
           img.src='./cui.jpg';
        }else {
    
    
           img.src = './rose.jpg';
        }
    }
</script>

此时点击图片就可以切换图片显示状态(需要提前把两个图片准备好)

展示结果:
在这里插入图片描述

(3)样式为style属性,稍微特殊一点:
<标签名 style=“样式属性1:样式值1;样式属性2:样式值2;”>
所以在js中获取或设置某个元素的样式,为

<p>点我试试呀</p>
<script>
    var p = document.querySelector("p");
    p.onclick = function () {
    
    
        var color = p.style.color;//获取p标签文本颜色,刚开始没有值(显示的时候默认黑色)
        if(color == '' || color == "black"){
    
    
            //css属性中-间隔的,js为style属性,驼峰式css属性
            p.style.color = "red";
            p.style.fontSize = "2em";//1个em为默认的一个字体大小
        }else{
    
    
            p.style.color = "black";
            p.style.fontSize = "1em";
        }
    }    
</script>

展示结果:
在这里插入图片描述

在修改的css样式属性比较多的时候,不方便,可以使用class来设置标签样式,再调整class属性就行(对应dom元素className属性)

<span class="day">这是要切换的内容</span>
<script>
    var span=document.querySelector("span");
    span.onclick = function () {
    
    
         //获取当前点击时的class
         //<span class="">标签中的class属性,在js的元素对象属性对应为className
         var cls = span.className;
         if(cls=="day"){
    
    
             span.className = "black";
         }else{
    
    
             span.className = "day";
         }
    }
</script>

3.获取/修改表单元素属性

表单(主要是指input标签)的以下属性都可以通过DOM来修改

  • value:input的值
  • disabled:禁用
  • checked:复选框会使用
  • selected:下拉框会使用
  • type:input的类型(文本、密码、按钮、文件等)

(1)文本框(type=text),密码框(type=password),里边显示的内容,是value属性来设置
按钮(type=button),按钮显示的内容,是value属性设置
普通标签(如< span >,< p >,< h >)显示的内容,是标签内容,表单元素显示内容为value属性,两者区分开
(2)复选框:checked属性
在html标签中,属性值设置为“checked”为选中,在js中,需要设置为true/false

代码示例: 切换按钮的文本

假设这是个播放按钮,在“播放”,“暂停”之间切换

<input type="button" value="播放">
<script>
    var btn = document.querySelector('input');
    btn.onclick = function () {
    
    
        if(btn.value == '播放') {
    
    
           btn.value = '暂停';
        }else{
    
    
           btn.value = '播放';
        }
    }
</script>

展示结果:
在这里插入图片描述

代码示例: 点击计数

使用一个输入框输入初始值(整数),每次点击按钮,值+1

<input type="text" id="text" value="0">
    <input type="button" id="btn" value="点我+1">
    <script>
        var text = document.querySelector('#text');
        var btn = document.querySelector('#btn');
        btn.onclick = function(){
    
    
            //=sum.value是返回字符串,字符串+1会转换为两个字符串拼接,就不对
            var num = +text.value;//+字符串,会转换为数值
            console.log(num);
            num++;
            text.value = num;
        }
    </script>

展示结果:
在这里插入图片描述

  • input具有一个重要的属性value,这个value决定了表单元素的内容
  • 如果是输入框,value表示输入框的内容,修改这个值会影响到界面显式;在界面上修改这个值也会影响到代码中的属性
  • 如果是按钮,value表示按钮的内容,可以通过这个来实现按钮中文本的替换

代码示例: 全选/取消全选按钮

1.点击全选按钮,则选中所有选项
只要某个选项取消,则自动取消全选按钮的勾选状态

<input type="checkbox" id="all">我全都要<br>
<input type="checkbox" class="girl">貂蝉<br>
<input type="checkbox" class="girl">小乔<br>
<input type="checkbox" class="girl">安琪拉<br>
<input type="checkbox" class="girl">妲己<br>
<script>
    var all = document.querySelector('#all');
    //子复选框
    var girls = document.querySelectorAll(".girl");
    all.onclick = function(){
    
    
    //html属性中,复选框checked值设置为checked字符串,js中复选框对象checked属性值为true/false
    //<input type='checkbox' checked='checked'复选框全部选中>
    for(girl of girls){
    
    
        girl.checked = all.checked;
    }
}
//优化用户体验:下边的复选框,全部都选择的时候,all复选框也选中
for(girl of girls){
    
    //每一个都绑定点击事件
    girl.onclick = function(){
    
    
        let allChecked = true;//all复选框是否被选中的变量
        for(it of girls){
    
    //所有子复选框判断是否被选中
            if(!it.checked){
    
    
                allChecked = false;
            }
        }
        all.checked = allChecked;
    }   
}
</script>

展示结果:
在这里插入图片描述

4.获取/修改样式属性

CSS中指定给元素的属性,都可以通过JS来修改
1.行内样式操作

element.style.[属性名] = [属性名];
element.style.cssText = [属性名+属性值];

“行内样式”,通过style直接在标签上指定的样式,优先级很高,适用于改的样式少的情况
代码示例: 点击文字则放大字体

style中的属性都是使用驼峰命名的方式和CSS属性对应的
例如:font-size=>fontSize,background-color=>backgroundColor等
这种方式修改只影响到特定样式,其它内联样式的值不变

<div style="font-size: 20px; font-weight: 700;">
    哈哈
</div>
<script>
    var div = document.querySelector('div');
    div.onclick = function(){
    
    
        var curFontSize = parseInt(this.style.fontSize);
        curFontSize += 10;
        this.style.fontSize = curFontSize + "px";
    }
</script>

展示结果:
在这里插入图片描述

2.类名样式操作

element.className = [CSS 类名];

修改元素的CSS类名,适用于要修改的样式很多的情况

由于class是JS的保留字,所以名字叫做className

代码示例: 开启夜间模式

  • 点击页面切换到夜间模式(背景变为黑色)
  • 再次点击恢复日间模式(背景变为白色)
<div class="container light">
     这是一大段话。<br>
     这是一大段话。<br>
     这是一大段话。<br>
     这是一大段话。<br>
</div>
<script>
    var div = document.querySelector('div');
    div.onclick = function () {
    
    
        console.log(div.className);
        if(div.className.indexOf('light')!=-1){
    
    
            div.className = 'container dark';
        }else{
    
    
            div.className = 'container light';
        }
    }
</script>

展示结果:
在这里插入图片描述

六、操作节点

1.新增节点

分为两个步骤

  1. 创建元素结点
  2. 把元素节点插入到dom树中

第一步相当于生了个娃,第二步相当于给娃上户口

1.创建元素节点
使用createElement方法来创建一个元素,options参数暂不关注
可以设置dom对象的属性,标签内容

var element = document.createElement(tagName[,options]);

代码示例:

<div class="container">

</div>
<script>
    var div = document.createElement('div');
    div.id = 'mydiv';
    div.className = 'box';
    div.innerHTML = 'hehe';
    console.log(div);
</script>

展示结果:
在这里插入图片描述
此时发现,虽然创建出新的div了,但是div并没有显示在页面上,这是因为新创建的节点并没有加入到DOM树中
上面介绍的只是创建元素节点,还可以使用

  • createTextNode创建文本节点
  • createComment创建注释节点
  • createAttribute创建属性节点

我们以createElement为主即可

2.插入节点到dom树中
1)使用appendChild将节点插入到指定节点的最后一个孩子之后
dom标签内包含的子节点不动,在最后添加element节点

element.appendChild(aChild)
<div class="container">

</div>
<script>
    var div = document.createElement('div');
    div.id = 'mydiv';
    div.className = 'box';
    div.innerHTML = 'hehe';

    var container = document.querySelector('.container');
    container.appendChild(div);
</script>

展示结果:
在这里插入图片描述
这个功能通过innerHTML也能实现:
先获取dom标签中所有的内容,再拼接后续要添加的节点html内容,最后再设置回dom标签中,但是这样效率比较差

<input type="text" id="content">
<input type="button" id="add" value="添加文本框内容为一个段落">
<div id="container">
     <h3>显示的内容</h3>
</div>
<script>
    //绑定点击事件,获取文本框内容,添加到container中
    var add = document.querySelector('#add');
    var content = document.querySelector('#content');
    var container = document.querySelector('#container');
    add.onclick = function(){
    
    
        //点击时,获取文本框内容
        var text = content.value;
        //第一种方式:innerHTML,先获取container中所有内容,在最后拼接<p>标签
        var html = container.innerHTML;
        html+="<p>";
        html+=text;
        html+="</p>";
        container.innerHTML = html;
        //以上修改container里边的内容,效率是比较差的:已有的标签选择器已经渲染了,但我们会重新设置,又会再次渲染
        //第二种方式:创建一个dom元素(<p>),然后添加到container内,作为最后一个子节点
        var p = document.createElement("p");//创建一个元素
        p.innerHTML = text;
        container.appendChild(p);//添加到dom树型结构中,并作为container最后子节点
    }
</script>

两种方式展示结果:
在这里插入图片描述

2)使用insertBefore将节点插入到指定节点之前

var insertedNode = parentNode.insertBefore(newNode,referenceNode);
  • insertedNode 被插入节点(newNode)
  • parentNode 新插入的节点的父节点
  • newNode 用于插入的节点
  • referenceNode newNode将要插入在这个节点之前

如果referenceNode为null,则newNode将被插入到子节点的末尾
注意:referenceNode引用节点不是可选参数

<div class="container">
     <div>11</div>
     <div>22</div>
     <div>33</div>
     <div>44</div>
</div>
<script>
    var newDiv = document.createElement('div');
    newDiv.innerHTML = '我是新的节点';

    var container = document.querySelector('.container');
    console.log(container.children);
    container.insertBefore(newDiv,container.children[0]);
</script>

展示结果:
在这里插入图片描述

注意1: 如果针对一个节点插入两次,则只有最后一次生效(相当于把元素移动了)

<div class="container">
    <div>11</div>
    <div>22</div>
    <div>33</div>
    <div>44</div>
</div>
<script>
    var newDiv = document.createElement('div');
    newDiv.innerHTML = '我是新的节点';

    var container = document.querySelector('.container');
    console.log(container.children);
    //此处的children里有4个元素
    container.insertBefore(newDiv,container.children[0]);
    //此处的children里有5个元素(上面新插了一个),0号元素是新节点
    //1号元素是11,2号节点是22,所以是插入到22之前
    container.insertBefore(newDiv,container.children[2]);
</script>

展示结果:
在这里插入图片描述
注意2: 一旦一个节点插入完毕,再针对刚刚的节点对象进行修改,能够同步影响到DOM树中的内容

<div class="container">
    <div>11</div>
    <div>22</div>
    <div>33</div>
    <div>44</div>
</div>
<script>
    var newDiv = document.createElement('div');
    newDiv.innerHTML = '我是新的节点';

    var container = document.querySelector('.container');
    console.log(container.children);
    container.insertBefore(newDiv,container.children[0]);
    //插入完毕后再次修改newDiv的内容
    newDiv.innerHTML = '我是新节点2';
</script>

展示结果:
在这里插入图片描述

2.删除节点

使用removeChild删除子节点

oldChild = element.removeChild(child);
  • child为待删除节点
  • element为child的父节点
  • 返回值为该被删除节点
  • 被删除节点只是从dom树中被删除了,但是依然在内存中,可以随时加入到dom树的其他位置
  • 如果上例中的child节点不是element节点的子节点,则该方法会抛出异常

3.补充知识

dom对象,其中包含属性:
dom.children: 返回该dom对象下一级所有的子节点数组
dom.parentNode: 返回该dom对象上一级的父节点
在这里插入图片描述


猜你喜欢

转载自blog.csdn.net/m0_51405559/article/details/122639917