【前端三剑客三】JavaScript的手术刀剖析第三篇

一、事件

1.基本概念

  JavaScript中的很多代码,都是通过“事件”来触发的。

  事件就是浏览器对于用户的操作行为进行的一个统称。用户对于页面的一些操作(点击, 选择, 修改等) 操作都会在浏览器中产生一个个事件, 被 JS 获取到, 从而进行更复杂的交互操作。

  例如,鼠标在页面上移动,就会产生一个鼠标移动事件;
  例如,鼠标在页面某个位置点击,就会产生一个鼠标点击事件.再例如,鼠标滚轮,来滚动页面,就会产生一组滚动事件;
  例如,用户按下键盘的某个按键,也会产生一个键盘事件;
  例如,用户修改浏览器窗口大小,也会产生一个窗口大小改变事件。


2.事件三要素

  1. 事件源: 哪个元素触发的
  2. 事件类型: 是点击, 选中, 还是修改?
  3. 事件处理程序: 当事件产生之后,执行什么样的JavaScript代码。这里往往是一个回调函数。

示例一:

<div>
        <button id = "btn">我是一个按钮</button>
    </div>
    <script>
        let btn = document.getElementById('btn');
        btn.onclick = function(){
            alert("hello world");
        }
    </script>
  • btn 按钮就是事件源.
  • 点击就是事件类型。
  • f- unction 这个匿名函数就是事件处理程序
  • 其中 btn.onclick = function() 这个操作称为 注册事件/绑定事件

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

在这里插入图片描述


二、操作元素

操作 = 获取 + 修改

操作元素,主要有以下三种:

  1. 操作元素内容
  2. 操作元素属性
  3. 操作元素样式

1.操作元素内容

1.1.innerText

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

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

示例:


    <div>
        <span>hello world</span>
        <span>hello world</span>
    </div>

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

在这里插入图片描述

  可以看到, 通过 innerText 无法获取到 div 内部的 html 结构, 只能得到文本内容.修改页面的时候也会把 span 标签当成文本进行设置。


1.2.innerHTML

Element.innerHTML 属性设置或获取HTML语法表示的元素的后代。

// 读操作
var content = element.innerHTML;
// 写操作
element.innerHTML = htmlString;
  1. 先获取到事件源的元素
  2. 注册事件

示例一:

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

在这里插入图片描述
  可以看到 innerHTML 不光能获取到页面的 html 结构, 同时也能修改结构. 并且获取到的内容保留的空格和换行。

示例二:获取与修改内容

     <div id = "screen">
        <ul>
            <li>aaa</li>
            <li>bbb</li>
            <li>ccc</li>
        </ul>
     </div>
     <button id = "btn">获取内容按钮</button>
     <button id = "btn2">修改内容按钮</button>

     <script>
         let btn = document.querySelector('#btn');
         btn.onclick = function(){
             let screen = document.querySelector('#screen');
             console.log(screen.innerHTML);
         }

         let btn2 = document.querySelector('#btn2');
         btn2.onclick = function(){
             let screen = document.querySelector('#screen');
             screen.innerHTML = '<h1>修改后的内容</h2>';
         }
     </script>

在这里插入图片描述


示例三:显示数字

     <div id = "screen">0</div>
     <button id = "plus">+</button>

     <script>
         let plusBtn = document.querySelector('#plus');
         plusBtn.onclick = function(){
             //1.获取到screen里的值
             let screen = document.querySelector('#screen');
             let val = screen.innerHTML;
             val = parseInt(val);//由于js是动态类型,转换成数字之后,仍然可以赋值给val
             
             //2.把这个值+1
             val += 1;
             //3.把新值写回去
             screen.innerHTML = val;

         }
     </script>

在这里插入图片描述


2.操作元素属性

可以通过dom的 Element 对象的属性来直接修改, 就能影响到页面显示效果.

     <img src="pic.jpg" alt="图片">

     <script>
         let img = document.querySelector('img');
         img.onclick = function(){
             console.log(img.src);
             
         }
     </script>

在这里插入图片描述

我们可以在代码中直接通过这些属性来获取属性的值:

     <img src="pic.jpg" alt="图片">

     <script>
         let img = document.querySelector('img');
        //  img.onclick = function(){
        //      console.log(img.src);
             
        //  }
        console.log(img.src);
        console.log(img.alt);

     </script>

在这里插入图片描述

直接修改属性:点击图片就切换

<img src="pic.jpg" alt="图片">

     <script>
         let img = document.querySelector('img');
            img.onclick = function(){
            console.dir(img.src);
             if(img.src.indexOf('pic.jpg') >= 0){
                 img.src = 'pic1.jpg';
             }else if(img.src.indexOf('pic1.jpg')){
                 img.src = 'pic.jpg';
             }
          }


     </script>

在这里插入图片描述


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

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

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

(1)示例一:切换按钮的文本:假设这是个播放按钮, 在 “播放” - “暂停” 之间切换。

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

在这里插入图片描述

(2)点击计算(这个例子第二篇文章讲过)

  • 使用一个输入框输入初始值(整数). 每次点击按钮, 值 + 1。
     <input type="text" id = "text" value="0">
     <input type="button" id = "btn" value='点击+1'>

     <script>
         let text = document.querySelector('#text');
         let btn = document.querySelector('#btn');

         btn.onclick = function(){
             let num = text.value;
             console.log(num);
             num++;
             text.value = num;
         }
     </script>

在这里插入图片描述

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

(3)全选/取消全选按钮

  • 点击全选按钮, 则选中所有选项
  • 只要某个选项取消, 则自动取消全选按钮的勾选状态
<script>
         //1.获取到元素
         let all = document.querySelector('#all');
         let girls = document.querySelectorAll('.girl');

         //2.给all注册点击事件
         all.onclick = function(){
             for(let i =0;i<girls.length;i++){
                 //all.checked 就是all这个复选框的选中状态
                 girls[i].checked = all.checked;
             }
         }

         //3.针对每个girl注册点击事件,实现对于all的取消操作
         for(let i =0; i < girls.length; i++){
             girls[i].onclick = function(){
                 all.checked = checkGirls(girls);
             }
         }

         function checkGirls(girls){
             //判定是不是所有的girl都被选中了
             for(let i =0;i<girls.length;i++){
                 if(!girls[i].checked){
                     //只要有一个没被选中,就让all是处于未选中状态
                     return '';
                 }
             }
             //遍历了一遍,发现所有都被选中了,就让all也是选中状态
             return 'checked';
         }
     </script>

在这里插入图片描述


4.获取/修改样式属性

CSS 中指定给元素的属性, 都可以通过 JS 来修改

4.1.行内样式操作

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

“行内样式”, 通过 style 直接在标签上指定的样式. 优先级很高.
适用于改的样式少的情况

示例:点击文字则放大字体

     <div style="font-size: 20px; font-weight: 600;">姑苏城外寒山寺,夜半钟声到客船</div>

     <script>
         let div = document.querySelector('div');
         div.onclick = function(){
             //1.先获取到当前字体的大小
             console.log(div.style.fontSize);
             let fontSize = parseInt(div.style.fontSize);
             //2.在当前字体大小的基础上,多增加5px
             fontSize += 5 ;
             div.style.fontSize = fontSize + 'px';

         }
     </script>

在这里插入图片描述

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


4.2.类名样式操作

element.className = [CSS 类名];

修改元素的 CSS 类名. 适用于要修改的样式很多的情况.
由于 class 是 JS 的保留字, 所以名字叫做 className

示例:开启夜间模式

  • 点击页面切换到夜间模式(背景变成黑色)
  • 再次点击恢复日间模式(背景变成白色)
<style>
         .light{
             background-color: #fff;
             color: #000;
         }
         .dark{
             background-color: #000;
             color: #fff;
         }
     </style>

     <div class="light" style="height: 500px;">夜半钟声到客船</div>
     <button>关灯</button>
     <script>
         let div = document.querySelector('div');
         let button = document.querySelector('button');
         button.onclick = function(){
             if(div.className == 'light'){
                 div.className = 'dark';
                 button.innerHTML = '开灯';
             }else if(div.className == 'dark'){
                 div.className = 'light';
                 button.innerHTML = '关灯';
             }
         }
     </script>

在这里插入图片描述


三、操作节点

1.新增节点

分成两个步骤

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

(1) 创建元素节点

使用 createElement 方法来创建一个元素。

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

示例:

    <div class="container">

    </div>
    <script>
        let 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 树中

第一步:使用 appendChild 将节点插入到指定节点的最后一个孩子之后。

element.appendChild(aChild)

    <div class="container">
        
    </div>
    <script>
        let newDiv = document.createElement('div');
        newDiv.id = 'newdiv';
        newDiv.className = 'one';
        newDiv.innerHTML = 'hehe';
        console.log(newDiv);

        let container = document.querySelector('.container');
        container.appendChild(newDiv);
    </script>

在这里插入图片描述

第二步:使用 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 节点的子节点,则该方法会抛出异常
     <div class="container">
        
    </div>

    <button>删除 div</button>

    <script>
        let newDiv = document.createElement('div');
        newDiv.id = 'newdiv';
        newDiv.className = 'one';
        newDiv.innerHTML = 'hehe';
        console.log(newDiv);

        let container = document.querySelector('.container');
        container.appendChild(newDiv);

        let button = document.querySelector('button');
        button.onclick = function(){
            container.removeChild(newDiv);
        }
    </script>

在这里插入图片描述


四、两个示例

1.示例一:猜数字

<style>
        body{
        background: yellowgreen;
    }
    .content{
        width: 500px;
        height: 500px;
        margin: 0 auto;
        background: gold;
    }
    div{
        width: 50%;
        height: 200px;
        background-color: aquamarine;
        display: flex;
        justify-content: center;
    }

    div > span{
        background-color:beige;
        width: 300px;
        height: 200px;
    }
    </style>

    <div>
        <button id="resetBtn">重新开始</button><br>
        <span>要猜的数字</span>
        <input type="text" name="" id="">
        <button id = "guessBtn"></button><br>
        <span>结果:</span>
        <span id="result"></span><br>
        <span>已经猜的次数:</span>
        <span id="guessCount"> 0</span>
    </div>

    <script>
        //1.先把上面需要用到的元素都拿到
        let resetBtn = document.querySelector('#resetBtn');
        let input = document.querySelector('input');
        let guessBtn = document.querySelector('#guessBtn');
        let resultSpan = document.querySelector('#result');
        let guessCountSpan = document.querySelector('#guessCount');

        //2.生成一个1-100的随机整数
        let toGuess = Math.floor(Math.random() * 100) +1;
        console.log(toGuess);
        //3.实现点击 猜 按钮的逻辑
        guessBtn.onclick = function(){
            //(1)读取到input中输入的内容,并转成整数
            if(input.value == ''){
                return;
            }
            let curNum = parseInt(input.value);
            //(2)判定大小关系,并给出提示
            if(curNum < toGuess){
                resultSpan.innerHTML = '低了';
                resultSpan.style.color = 'red';
            }else if(curNum > toGuess){
                resultSpan.innerHTML = '高了';
                resultSpan.style.color = 'red';
            }else{
                resultSpan.innerHTML = '猜对了';
                resultSpan.style.color = 'green';
            }
            //(3)更新猜的次数
            let guessCount = parseInt(guessCountSpan.innerHTML);
            guessCountSpan.innerHTML = guessCount + 1;
        }

        //4.实现reset操作的逻辑,开始新游戏
        resetBtn.onclick = function(){
            //让页面刷新
            //location是和document并列关系的对象
            location.reload();
        }
    </script>

在这里插入图片描述


2.示例二:表白墙

输入后点击提交, 会将信息显示在表格中

    <style>
        *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .container{
            width: 100%;
        }
        h3{
            text-align: center;
            padding: 40px 0;
            font-size: 24px;
        }

        p{
            text-align: center;
            color: #666;
            padding: 10px 0;
        }

        .row{
            width: 400px;
            height: 50px;
            margin: 0 auto;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .row span{
            width: 60px;
            font-size: 20px;
        }
        .row input{
            width: 300px;
            height: 40px;
            line-height: 40px;
            font-size: 20px;
            text-indent: 0.5em;
            /* 去掉轮廓线*/
            outline: none;
        }

        .row #submit{
            width: 300px;
            height: 50px;
            font-size: 20px;
            line-height: 40px;
            margin: 0 auto;
            color: #fff;
            background-color: orange;
            border: none;

            border-radius: 10px;
        }

        .row #submit:active{
            background-color: #555;
        }
    </style>

    <div class="container">
        <h3>表白墙</h3>
        <p>输入后点击提交,会将信息显示在表格中</p>
        <div class="row">
            <span>谁:</span>
            <input type="text" name="" id="">
        </div>
        <div class="row">
            <span>
                对谁:
            </span>
            <input type="text" name="" id="">
        </div>
        <div class="row">
            <span>说啥:</span>
            <input type="text" name="" id="">
        </div>
        <div class="row">
            <button id = "submit">提交</button>
        </div>
    </div>

    <script>
        //当用户点击submit ,就会获取到input中的内容,
        //从而把内容构造成一个div,从而插入到页面末尾
        let submitBtn = document.querySelector('#submit');
        submitBtn.onclick = function(){
            //1.获取到3个input中的内容
            let inputs = document.querySelectorAll('input');
            let from = inputs[0].value;
            let to = inputs[1].value;
            let msg = inputs[2].value;
            if(from == '' || to =='' || msg == ''){
                //用户还没填写完,暂时先不提交数据
                return;
            }
            //2.生成一个新的div,内容就是input里面的内容
            //把这个新的div加载到页面中
            let div = document.createElement('div');
            div.innerHTML = from + '对' + to + '说:' +msg;
            div.className = 'row';
            let container = document.querySelector('.container');
            container.appendChild(div);

            //3.清空之前输入框的内容
            for(let i = 0;i < inputs.length ;i++){
                inputs[i].value = '';
            }
        }
    </script>

在这里插入图片描述


  刚才咱们写的表白墙程序,是通过一些div.row来保存咱们提交的消息.这些div.row是挂在DOM树上,就是在内存中的,容易失去的.。一旦页面刷新/关闭了,此时,之前内存中保存的数据,就没了。为了解决上述的数据容易丢失问题,有以下解决方案:

  1. 可以把提交的数据,保存在浏览器本地。(浏览器提供了localStorage / indexDB这样的机制,能够实现本地存储),本质上,是通过浏览器,把你要存的数据,存到当前电脑的磁盘上。但是这里也有问题:就是只有我在自己的电脑上能看到,别人看不到。

  2. 可以把提交的数据,通过网络通信,传输给服务器.由服务器进行保存。
    1)服务器保存在内存里
    2)服务器保存在文件中
    3)服务器保存在数据库里



完!

评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十叶知秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值