Web开发day6:补前端JavaScript

目录

一、JavaScript基础知识

二、Javascript基本语法

三、数据类型、强制转换

四、运算符

五、条件判断、循环语句

六、对象、对象字面量

七、函数

八、构造函数

九、数组、call和apply、arguments

十、Date、Math

十一、DOM查询

十二、事件对象

十三、事件冒泡、事件委派、事件绑定

十四、拖拽实现

十五、JSON


进度来源:尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版

网址:尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版_哔哩哔哩_bilibili

一、JavaScript基础知识

JavaScript包含三个部分:

  • ECMAScript:JavaScript标准
  • DOM:文档对象模型,可以操作网页
  • BOM:浏览器对象模型,提供一组对象,可以操作浏览器

二、3个基本语法:alert、console.log、document.write

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <!-- 引入外部js文件,引入外部后,此script标签内部不在生效 -->
    <script type="text/javascript" src="./script.js"></script>

    <!-- JS代码需要编写到script标签中,加不加type="text/javascript"都可 -->
    <script type="text/javascript">
        //单行注释

        /*
         * 控制浏览器弹出一个警告
         * 点击警告的确定后,下面的代码才会执行
         */
        alert("我是内部警告!");

        /*
         * 让计算机在body中写一段内容
         */
        document.write("随便写点什么");

        /*
         * 向控制台输出一个内容
         */
        console.log("控制台");

        /*
         * 输入框,返回值为字符串
         * 想要数字需要强制类型转换
         */
        // let a = prompt('请输入一个值:');
        let a = +prompt('请输入一个值:');

    </script>

</head>
<body>
    <!-- 不推荐使用 -->
    
    <!-- 将js代码编写到标签的onclick属性中 -->
    <button onclick="alert('你点我干嘛~');">点我一下</button>

    <!-- 将js代码编写到超链接的href属性中,点击时不会跳转 -->
    <a href="javascript:alert('不要随便点我');">不要点我</a>
    <a href="javascript:;">点完后不会有反映</a>
</body>
</html>

!!!JavaScript语法严格区分大小写

!!!每句结尾必加英文分号

三、数据类型、强制转换

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        /*
         * 字面量:不可改变的值
         * 变量:可以改变的值
         */

        // 声明变量,并赋值
        let a;
        a = 123;
        let b = 456;
        console.log(a, b);

        /*
         * 标识符:变量名、函数名、属性名等
         * 命名规则:
         *    1.可含有字母、数字、_、$
         *    2.不能以数字开头
         *    3.不能是JS的关键字
         *    4.命名规则一般为驼峰命名法,首字母小写,每个开头字母大写
         *    5.JS由unicode编写,理论上所有utf-8含有的内容都可以用来命名,比如中文
         */

        let a_1_$ = 789;
        console.log(a_1_$)

        /*
         * JS的6种数据类型
         *    String 字符串(\可转义)
         *    Number 数值
         *    Boolean 布尔值
         *    Null 空值
         *    Undefined 未定义
         *    Object 对象
         * 前五种基本数据类型,Object属于引用数据类型
         */

        // \转义符,\n换行,\t一个tab
        let str1 = "hello";
        let str2 = 'hello';
        let str3 = "hey! \"\n\t";
        console.log(str1, str2, str3);

        // typeof 输出变量类型
        // Number.MAX_VALUE最大值,Number.MIN_VALUE正数最小值
        // Infinity表示无穷,NaN表示非数字
        let num1 = 123;
        let num2 = Infinity;
        let num3 = NaN;
        console.log(num1, typeof num1);
        console.log(Number.MAX_VALUE, Number.MIN_VALUE);
        console.log(num2, typeof num2, num3, typeof num3);

        // 布尔true or false
        let bool1 = true;
        console.log(bool1);

        // null表示为空的对象
        let null1 = null;
        console.log(null1, typeof null1);

        // 声明一个变量,但不赋值,就会undefined
        let undefined1;
        console.log(undefined1, typeof undefined1);

        /*
         * 强制类型转换:将一个数据类型转换为其他数据类型
         * 一般都是转换为String和Number或Boolean
         */

        // 1.调用toString方法,注意null和undefined无法转String
        // 2.调用String函数
        let num2str1 = 123;
        num2str1 = num2str1.toString();
        console.log(typeof num2str1);
        let num2str2 = 456;
        num2str2 = String(num2str2);
        console.log(typeof num2str2);

        // 1.调用Number函数,纯数字/空字符串/布尔/null会转,非全数字/undefined会转为NaN
        // 2.调用parseInt函数或parseFloat函数,将变量先转为String再转为数字
        let str2num1 = '123';
        str2num1 = Number(str2num1);
        console.log(typeof str2num1);
        let str2num2 = '456p';
        str2num2 = parseInt(str2num2);
        console.log(typeof str2num2);

        // 非零/非null对象转true,零/空/null/undefined转false
        let other2bool = 123;
        other2bool = Boolean(other2bool);
        console.log(typeof other2bool);
    </script>
</head>
<body>

</body>
</html>

四、运算符

<!DOCTYPE html>
<html lang="en">
<body>

</body>
</html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        /*
         * 加法运算符+:优先级String > Number
         * 除加法运算符外:优先级Number最大
         * 运算自左向右进行
         * 一元运算符:typeof、+(任意数据类型转Number)、-
         * 自增和自减:++、--
         * 逻辑运算符:!、&&、||,布尔值的运算结果为Boolean类型,非布尔计算结果:
         *     与运算:
         *     1. 第一个值为true,返回第二个值
         *     2. 第一个值为false,返回第一个值
         *     或运算:
         *     1. 第一个值为true,返回第一个值
         *     2. 第一个值为false,返回第二个值
         * 相等运算符:==会进行类型转化,转为Number,===不进行类型转换
         */

    </script>
</head>

五、条件判断、循环语句

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        // 代码块{},var无隔离作用,let有隔离作用
        {
            alert('hello');
            console.log('nihao');
            var a = 123;
            let b = 456;
        }
        // a不报错,b报错
        // console.log(a, b);

        // 条件判断if,if中不能使用break和continue
        if(1 == 2){
            console.log(123);
        }else if(1 == 1){
            console.log(456);
        }else{
            console.log(789);
        }

        // 条件分支语句switch,num与case后的值全等比较,均为false执行default
        let num = 2;
        switch(num){
            case 1:{
                console.log(123);
                break;
            }
            case 2:{
                console.log(456);
                break;
            }
            default:{
                console.log(789);
            }
        }

        // 循环语句while
        let n = 1;
        while(n < 50){
            document.write(n++ + '<br />');
        }

        // 循环语句for
        let m = 1;
        for(; m < 10; m++){
            console.log(m);
        }

        // 计时器
        console.time('test');
        console.timeEnd('test');

    </script>
</head>
<body>

</body>
</html>

六、对象、对象字面量

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        /*
         * 对象分类:
         *     1.内建对象,ES标准中定义的,比如Math、String、Boolean
         *     2.宿主对象,由JS运行环境提供的对象,目前主要指由浏览器提供的对象,比如BOM、DOM
         *     3.自定义对象,开发人员自己定义的
         */

        // 创建对象
        let obj1 = new Object();
        console.log(typeof obj1);

        // 添加属性,中括号里可以传变量,属性值可以是任意类型,甚至是对象
        obj1.name = '张三';
        obj1.gender = 'male';
        obj1.age = 18;
        obj1['123'] = 456
        console.log(obj1.age, obj1['123']);
        console.log('age' in obj1, '123' in obj1);

        // 对象是引用数据类型,内存地址一样,改一个都改
        // 基本数据类型保存在栈内存,引用数据类型保存在堆内存(栈内存中保存对象的内存地址)
        let obj2 = obj1;
        obj1.age = 19;
        console.log(obj2.age);

        // 对象字面量创建
        let obj3 = {
            name: '张三',
            age: 28,
            test: {name: '李四'}
        }

        // 枚举对象属性
        for(let n in obj3){
            // n是属性名
            console.log(n, obj3[n]);
        }
    </script>
</head>
<body>

</body>
</html>

七、函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script type="text/javascript">
        // 多行注释shift+alt+a

        /* 
         * 函数:也是一个对象,封装一些功能
         * 以字符串形式传递给构造函数
         * 代码会在调用时执行
         */

        // 以下形式很少用
        let fun1 = new Function('console.log(123);');
        fun1();
        console.log(typeof fun1);

        // 一般以下形式声明函数,fun2(形参1, 形参2){}
        function fun2(){
            console.log(456);
        }
        fun2();

        // 匿名函数声明
        let fun3 = function(){
            console.log(789);
        };
        fun3();

        /* 
         * 参数设置
         * 调用函数时解析器不会检查实参的类型,要注意是否接收到非法参数
         * 调用函数时解析器不会检查实参的数量,多余的没有,少的按undefined
         */

        // 求和函数
        function sum(a, b){
            console.log(a + b);
        }
        sum(1, 2);

        /*
         * 函数的返回值,return返回
         * return不加值/不写return,返回undefined
         * 返回值可以是任意对象
         */
        function sum(a, b){
            return a + b;
        }
        let absums = sum(1, 2);
        console.log('absums:' + absums);

        /* 
         * 立即执行函数
         */

        (function(){
            alert('立即执行');
        })();

        /* 
         * 全局作用域:
         *     1.页面打开时创建,关闭时销毁
         *     2.直接编写在script的js代码都是全局作用域
         *     3.全局作用域中有一个window对象,创建的全局变量都是window的属性,全局函数都是window的方法
         *     4.var变量在所有代码执行前创建,不赋值只声明
         *     5.function 函数名(){}声明的函数在所有代码执行前创建
         * 函数作用域:
         *     1.调用函数时创建,执行完毕后销毁
         *     2.函数作用域可以访问全局变量
         *     3.访问同名变量采取就近原则
         *     4.函数内不使用var声明的变量会被当做全局变量
         */

        // 全局作用域
        var a = 1;
        var b = function(){
            console.log('我是window的方法');
        };
        console.log(window.a);
        console.log(window.b);
        window.b();

        /* 
         * this指针:this指向函数执行的上下文对象
         * this在哪被调用,或者说谁调用this,谁就是this
         */

        // 全局调用,this是window,对象调用,this是对象
        function fun4(){
            console.log(this);
        }
        fun4();
        let obj1 = {
            method: fun4
        };
        obj1.method();

        /* 
         * 工厂方法创建对象
         */

        function createobj(name, age){
            let obj = {
                name: name,
                age: age,
                sayName: function(){
                    console.log(this.name);
                }
            }
            obj.sayName();
            return obj;
        }
        let obj2 = createobj('王五', 18);
        let obj3 = createobj('程六', 19);

    </script>
    <title>Document</title>
</head>
<body>
    
</body>
</html>

八、构造函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript">
        /* 
         * 构造函数:习惯上首字母大写,其他与普通函数一样
         * 构造函数调用使用new
         * 调用构造函数时,立刻创建一个新对象,即使构造函数没有return,创建流程:
         *     1.立即创建一个新对象
         *     2.将新建对象设置为函数中的this
         *     3.运行函数中的代码
         *     4.将新建对象作为返回值返回
         */

        function Person1(name, age){
            this.name = name;
            this.age = age;
            this.sayName = function(){
                alert(this.name);
            };
        }
        let person1 = new Person1('张三', 18);
        console.log(person1);
        person1.sayName();

        // 使用instaneof检查一个对象是否是一个类的实例
        console.log(person1 instanceof Person1, person1 instanceof Object);

        /* 
         * 修改构造函数,将方法在全局作用域定义
         * 但此方法不好
         */
        function fun(){
            alert(this.name);
        }
        function Person2(name, age){
            this.name = name;
            this.age = age;
            this.sayName = fun;
        }
        let person2 = new Person2('李四', 24);
        person2.sayName();

        /* 
         * 每一个函数,解析器都会向函数中添加一个属性prototype
         * prototype指向一个原型对象(原型对象还有一个原型),每个函数的原型函数不一样
         * 普通函数没有,构造函数有用
         * 当以构造函数创建对象时,每个对象都含有一个隐含属性__proto__指向构造函数的原型对象
         * 所以可以将对象共有属性添加到原型对象中
         * 每次先在实例中找,没有的话去原型找
         */

        function Person3(name, age){
            this.name = name;
            this.age = age;
        }
        Person3.prototype.sayName = function(){
            alert(this.name);
        };
        let person3 = new Person3('王五', 29);
        console.log('sayName' in person3);
        person3.sayName();

        // 检查实例对象是否有某个属性/方法,用in的话原型有也是true
        // 原型对象还有一个原型
        console.log(person3.hasOwnProperty('sayName'));  // fasle
        console.log(person3.__proto__.hasOwnProperty('sayName'));  //true
        console.log(person3.__proto__.__proto__.hasOwnProperty('hasOwnProperty'));  //true

        /* 
         * 输出对象,相当于输出对象.toString()方法的返回值
         * 可以重新定义toString方法覆盖原方法,这样打印对象时,就会按照重新定义的方法输出结果
         */

        console.log(person3 == (person3.toString()));  // true
        console.log(person3.__proto__.hasOwnProperty('toString'));  // false
        console.log(person3.__proto__.__proto__.hasOwnProperty('toString'));  // true
        console.log(person3);  // Person3 {name: '王五', age: 29},这样显示纯因为Chrome,实际就是调用toString方法
        console.log(person3.toString());  // [object Object]
        person3.__proto__.__proto__.toString = function(){
            return '我是重新定义的原型的原型的toString方法';
        }
        console.log(person3 == (person3.toString()));  // true
        console.log(person3);  // Person3 {name: '王五', age: 29},这样显示纯因为Chrome,实际就是调用toString方法
        console.log(person3.toString());  // 我是重新定义的toString方法

    </script>
</head>
<body>
    
</body>
</html>

九、数组、call和apply、arguments

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript">
        /* 
         * 数组:数字做索引,数组[索引]=值
         * 读取不存在的元素,会返回undefined
         * 元素可以放任意的数据类型
         */

        let arr1 = new Array();
        arr1[0] = 10;
        arr1[1] = 33;
        console.log(arr1.length);
        arr1.length = 3;

        let arr2 = [1, 2, 3, 4, 5, 6];
        let arr3 = new Array(1, 2, 3);
        let arr4 = new Array(10);  // 创建长度为10的数组

        /* 
         * 四种方法:
         *     1.push(),添加元素到末尾,可同时添加多个,返回值是数组新长度
         *     2.pop(),删除末尾最后一个元素,返回值是删除的元素
         *     3.unshift(),向开头添加一个或多个元素,返回值是数组新长度
         *     4.shift(),删除并返回数组第一个元素
         */

         /* 
          * forEach:遍历数组
          * 需要一个函数作为参数
          * 数组有几个元素,函数执行几次
          * 浏览器会将遍历到的元素以实参形式传递进函数中,有三个参数
          *     1.当前遍历元素的value
          *     2.当前遍历元素的index
          *     3.正在遍历的数组,是一个对象Object
          */

        arr1.forEach(function(value, index, arr){
            console.log(value, index, arr);
        });

        /* 
         * slice:切片,方法同python,不会影响原数组
         * splice:删除指定元素,可删除多个,会影响原数组
         *     1.第一个参数是开始位置
         *     2.第二个参数是删除数量
         *     3.第三个参数是向删除位置前添加的新元素
         */

        /* 
         * concat:连接两个或多个数组,返回新数组,不影响原数组
         * join:数组转字符串,使用括号内的字符拼接,不设置默认使用英文逗号连接,不影响原数组
         * reverse:数组转置,影响原数组
         * sort:数组排序,默认升序,会影响原数组,可自定义排序规则,函数返回大于0的值元素会交换位置
         */

         arr5 = arr1.concat(arr2);
         arr6 = arr1.join(':');
         arr1.reverse();
         arr1.sort(function(a, b){
            // 默认a在b前
            // 此是降序
            return b - a;
         });

         /* 
          * call和apply:
          *     1.都是函数对象的方法,需要通过函数对象来调用
          *     2.函数调用call和apply都会执行函数
          *     3.可以在调用call和apply时传入一个对象作为参数,此参数会成为函数执行的this
          *     4.第二第三及之后的参数是函数的实参,其中call可以直接传,apply需要将实参封装到数组中传
          */

        function fun1(a, b){
            alert(this);
        }
        let obj1 = new Object();
        fun1.call(obj1, 1, 2);
        fun1.apply(obj1, [1, 2]);

        /* 
         * 在调用函数时,浏览器每次都会传递两个隐含参数:
         *     1.函数上下文对象this
         *     2.封装实参的对象arguments,是一个类数组对象,不是数组
         * 其中argument可以通过索引来获取实参,可以获取长度,不定义形参也可以获取
         * arguments.callee可以获取当前执行的函数对象
         */

        function fun2(){
            // console.log(arguments instanceof Array);  // false
            console.log(Array.isArray(arguments));  // false
            console.log(arguments.length);
            console.log(arguments[0]);
            console.log(arguments.callee == fun2);  // true
        }
        fun2(1, 2);

    </script>
</head>
<body>
    
</body>
</html>

十、Date、Math

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="text/javascript">
        /* 
         * Date对象
         */

        // 直接构造函数创建Date对象,封装为当前代码执行时间
        let date1 = new Date();

        // 传入指定参数得到指定时间
        let date2 = new Date('12/03/2016 12:30:10');

        /* 
         * 方法:
         *     1.getDate,获取当前日期对象是几号
         *     2.getDay,获取当前日期对象是周几,周日是0,范围0-6
         *     3.getMonth,获取当前日期对象是几月,范围0-11
         *     4.getFullYear,获取年份
         *     5.getTime,获取当前日期对象的时间戳,从1970年1月1日到当前日期所花毫秒数
         *     6.Date.now(),获取当前代码执行的时间戳
         */

        
        /* 
         * Math对象:不是构造函数,不用创建对象,其中封装了相关的属性和方法
         * 
         */ 
        
        // 常量
        console.log(Math.PI, Math.E);

        // 方法
        console.log(Math.abs(-5));  // 5
        console.log(Math.ceil(1.2));  // 2
        console.log(Math.floor(2.9));  // 2
        console.log(Math.round(1.5));  // 2
        console.log(Math.random());  // [0, 1)随机数
        console.log(Math.round(Math.random()*(y-x)+x));  // [x, y]随机数
        console.log(Math.max(1, 2, 3, 4));  // 最大值,最小值是min
        console.log(Math.pow(2, 3));  // 2的3次方
        console.log(Math.sqrt(2));  // 2的平方
        
    </script>
</head>
<body>
    
</body>
</html>

十一、DOM查询

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

</head>
<body>
    <button id="btn1" onclick="alert('点我干嘛');">我是一个按钮</button>
    <div class="box1">
        <div>我是box1的div</div>
    </div>
    <div id="box2">
        <div>我是box2的div</div>
    </div>
    <a href="https://www.baidu.com/">点我不跳转</a>
    <input type="text" placeholder="请输入年龄">
    <button id="btn2">提交</button>
</body>
<script>
    // 文档节点:代表整个页面,即document
    console.log(document);

    /* 
     * 顺序不能错,比如先声明button再getElementById,浏览器自上而下实行
     * 如果想写上边,可以使用window.onload = function(){JS代码},这样代码会在页面加载后执行
     */
    
    // 通过文档对象获取某个对象,并操作
    // 还有getElementsByTagName(获取的是一个数组)、getElementsByName、还有getElementsByTagName(获取的是一个数组)、getElementsByClassName、
    let btn1 = document.getElementById('btn1');
    btn1.innerHTML = "I'm a button";

    /* 
     * 事件:用户和浏览器之间的交互,比如点按钮、鼠标移动
     * 在事件对应的属性中添加一些js代码,当事件发生时代码执行
     *     1.耦合写法,比如上边的onclick
     *     2.在script标签中写,事件绑定处理函数
     */

    // 绑定单击事件
    btn1.onclick = function(){
        alert('你还点');
    };

    /* 
     * childNodes:所有子节点,包括换行
     * children:所有子元素
     * firstChild:第一个子节点,包括换行
     * firstElementChild:第一个子元素
     * 
     * parentNode:父节点
     * previousSibling:前一个兄弟节点
     * previousElementSibling:前一个兄弟元素
     * nextSibling:后一个兄弟节点
     */

    // 获取body、html
    let body = document.body;
    let html = document.documentElement;

    // 根据CSS选择器查询元素节点,如果满足条件的很多,只返回第一个,返回全部用all,此时返回的是类数组
    let box1div = document.querySelector('.box1 div');
    let box2div = document.querySelectorAll('#box2 div');

    /*
     * 超链接元素的onclick属性的函数返回false会取消超链接的跳转
     * this指代所点击的元素
     * confirm用于弹出确认框
     * 输出框的value可以获得输入的内容
     */
    let a1 = document.getElementsByTagName('a')[0];
    a1.onclick = function(){
        let ifquren = confirm('是否删除?');
        if(ifquren)
            alert(this);
            console.log(this);
        return false;
    }
    
    let btn2 = document.getElementById('btn2');
    btn2.onclick = function(){
        let input1 = document.getElementsByTagName('input')[0];
        console.log(input1.value);
    }

    /* 
     * 通过JS修改元素样式:元素.style.样式名 = '样式值'(只能读内联样式)
     * !!!样式名:带-的不能直接用,把名称改为驼峰命名即可,比如background-color改为backgroundColor
     * 
     * 以下均只读
     * 获取当前正在显示的样式(不局限于内联,但仅IE8支持):元素.currentStyle.样式名 = '样式值'
     * 获取当前正在显示的样式(其他浏览器,IE8不支持):
     *     1.getComputedStyle(元素, 伪元素),伪元素一般都是null
     *     2.返回值是对象,可以 对象.样式名 获取样式值
     */

</script>
</html>

十二、事件对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #areaDiv{
            width: 300px;
            height: 50px;
            border: 1px solid black;
            margin-bottom: 10px;
        }
        #showMsg{
            width: 300px;
            height: 20px;
            border: 1px solid black;
        }
        #box1{
            width: 200px;
            height: 200px;
            border: 1px solid red;
            position: absolute;
        }
    </style>
</head>
<body>
    <div id="areaDiv"></div>
    <div id="showMsg"></div>
    <div id="box1"></div>
</body>
<script>
    
    // 该事件在鼠标在元素内移动时触发
    let areaDiv = document.getElementById('areaDiv');
    let showMsg = document.getElementById('showMsg');
    areaDiv.onmousemove = function(event){
        // 当事件触发时,浏览器每次都会向函数中传递一个事件对象,封装了事件的所有信息
        let x = event.clientX;  // 获取鼠标横坐标
        let y = event.clientY;  // 获取鼠标纵坐标
        showMsg.innerHTML = 'x=' + x + ',y=' + y;
    };

    // div随着鼠标移动
    let box1 = document.getElementById('box1');
    document.onmousemove = function(event){
        let left = event.pageX;
        let top = event.pageY;
        box1.style.left = left + 'px';
        box1.style.top = top + 'px';
    };
</script>
</html>

十三、事件冒泡、事件委派、事件绑定

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box1{
            width: 200px;
            height: 200px;
            background-color: yellowgreen;
        }

        #s1{
            background-color: yellow;
        }
    </style>
</head>
<body>
    <div id="box1">
        我是box1
        <span id="s1">我是span</span>
    </div>

    <button id="btn1">添加超链接</button>
    <ul id="u1">
        <li><a href="javascript:;" class="link">超链接1</a></li>
        <li><a href="javascript:;" class="link">超链接2</a></li>
        <li><a href="javascript:;" class="link">超链接3</a></li>
    </ul>
    <button id="btn2">事件绑定</button>
</body>
<script>

    /*
     * 事件冒泡:事件向上传到,点span触发,div和body也触发
     */

    let s1 = document.getElementById('s1');
    s1.onclick = function(event){
        alert('span触发');
        // 取消冒泡
        event.cancelBubble = true;
    };
    let box1 = document.getElementById('box1');
    box1.onclick = function(){
        alert('div触发');
    };
    // document.body.onclick = function(){
    //     alert('body触发');
    // };

    /*
     * 事件委派:只绑定一次事件,后边新加的事件不需要重新设置(因为for循环会在页面构建时先执行)
     * 可以将事件绑定给其父元素(共同的祖先元素),后代触发时,会冒泡到祖先一样触发
     */

    let btn1 = document.getElementById('btn1');
    let u1 = document.getElementById('u1');
    u1.onclick = function(event){
        // 用target获得触发事件的对象,设置仅点击超链接会alert,点击u1其他地方不触发
        // if(event.target.className == 'link')
        //     alert('u1的触发事件');

        // 使用className判断是有隐患的,万一某个a的class改名了,下面方法更严谨
        if(event.target.tagName == 'A')
            alert('u1的触发事件');
    };
    btn1.onclick = function(){
        let newli = document.createElement('li');
        // 不能用u1.length,因为对象没有length属性,只有String和Array有
        newli.innerHTML = '<a href="javascript:;" class="link">超链接' + (u1.getElementsByTagName('li').length + 1) + '</a>';
        u1.appendChild(newli);
    };

    /*
     * 使用对象.事件 = 函数绑定,只能绑定一个,后会覆盖前
     * 事件绑定:addEventListener,参数为
     *     1.事件的字符串,不要on,只click
     *     2.回调函数,当事件触发时该函数会被调用
     *     3.是否在捕获阶段触发事件,一般为false,会true时触发顺序和冒泡相反
     */

    // 同时绑定多个,先后执行
    let btn2 = document.getElementById('btn2');
    btn2.addEventListener('click', function(){
        alert(1);
    }, false);
    btn2.addEventListener('click', function(){
        alert(2);
    }, false);

</script>
</html>

十四、拖拽实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box1{
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        }
    </style>
</head>
<body>
    <div id="box1"></div>
</body>
<script>
    /*
     * 拖拽:
     *     1.鼠标按下,开始拖拽
     *     2.鼠标移动,元素跟着移动
     *     3.鼠标松开,停止拖拽
     */

    let box1 = document.getElementById('box1');
    box1.onmousedown = function(event){
        let l = event.clientX;
        let t = event.clientY;
        let left_diff = l - box1.offsetLeft;
        let top_diff = t - box1.offsetTop;
        document.onmousemove = function(event){
            let left = event.clientX;
            let top = event.clientY;
            box1.style.left = left - left_diff + 'px';
            box1.style.top = top - top_diff + 'px';
        };
        document.onmouseup = function(){
            document.onmousemove = false;
            // 取消自己,不然点击空白松开还会触发alert
            document.onmouseup = false;
            alert(1);
        };
    };

</script>
</html>

十五、JSON

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
<script>
    /*
     * JSON:特殊格式的字符串,属性名必须双引号
     * JSON分类:JSON对象(用{})、JSON数组(用[])
     * JSON中允许的值:字符串、数值、布尔、null、普通对象(Object)、数组
     * 
     */
    
    // JSON举例
    let json1 = '{"name": "孙悟空", "age": 18, "gender": "男"}';
    let json2 = '[1, 3, 5, "你好"]';
    let json3 = '{"arr": [1, 2, 3]}';

    // JSON转js对象
    let obj1 = JSON.parse(json1);
    console.log(obj1);

    // js对象转JSON
    let json4 = JSON.stringify(obj1);
    console.log(json4);
</script>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我选择四娃

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

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

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

打赏作者

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

抵扣说明:

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

余额充值