day44 js

孤街醉人 提交于 2019-12-05 07:42:27
day44 js
 
内容回顾
    1.DOM
        三步走 1.获取事件源 2.绑定事件 3.事件驱动
        DOM操作: 对节点的操作
            1.对标签属性的操作
                getAttribute()
                setAttribute()
                .src
                .alt
                .id
                .className
            2.对标签样式属性的操作
                objDiv.style.cssStyle
            3.对值的操作
                双闭合标签
                    innerText: 只设置文本
                    innerHTML: 即设置了文本, 又渲染了标签 
                单闭合标签
                    input:value
            4.对DOM的创建 销毁操作(和上面三种不同的是, 这些都是方法(即函数): 都是动态创建的)
                创建: document.creatElement('')
                追加: 父.appendChild(子)
                      父.insertBefore('要插入的新节点','参考的节点')     #插入的是参考节点的兄弟节点
                销毁: 父.removeChild(子)
            5.对DOM的获取的三种方式
                document.getElementById()
                document.getElementsByClassName()
                document.getElementsByTagName()
    2.什么是动态页面和静态页面?
        动态: 有数据交互的, 有数据驱动的叫动态页面    
 
                
 
今日内容
 
库和框架的区别:
    库: 小而精, 实现了js的一部分功能, 主要是DOM的操作
    框架: 大而全
 
路由的跳转:
<body>
    <a href="#/home">首页</a>
    <a href="#/course">课程</a>
    <div class="app"></div>
    <script>
        //路由的跳转, 通过A标签, 给url加锚点实现, 原来的标题栏不变, 只是下面的页面渲染在变
        //如何获取url里面的锚点(#/home), 通过BOM对象获取,浏览器对象模型
        window.onhashchange = function () {             
            switch(window.location.hash){               //window可以省略, hash可以获取url中的'#/home'
                case '#/home':
                    document.getElementsByClassName('app')[0].innerHTML = '<h2>我是首页</h2>';
                    break;
                case '#/course':
                    document.getElementsByClassName('app')[0].innerHTML = '<h2>我是课程</h2>';
                    break;
                default:
                    break;
            }
        }
    </script>
</body>
 
一.选项卡案例(tab栏选项卡)
 
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        #tab{
            width: 480px;   /*父盒子的高度不设置,直接让子盒子撑起来*/
            margin: 20px auto;
            border: 1px solid red;
        }
        ul{
            width: 100%;
            overflow: hidden;
            list-style-type: none;
        }
        ul li{
            float: left;
            width: 160px;
            height: 60px;
            text-align: center;
            line-height: 60px;
            
        }
        ul li a{
            text-decoration: none;
            color: #000;
        }
        li.active{
            
        }
        p{
            display: none;
            height: 200px;
            text-align: center;
            line-height: 200px;
            
        }
        p.active{
            display: block;
        }
    </style>
</head>
<body>
    <div id="tab">
        <ul>
            <li class="active">
                <a href="#">首页</a>
            </li>
            <li>
                <a href="#">新闻</a>
            </li>
            <li>
                <a href="#">图片</a>
            </li>
        </ul>
        <p class="active">首页内容</p>
        <p>新闻内容</p>
        <p>图片内容</p>
    </div>
    <script>
        //先做标题栏效果, 在做内容区效果
        //标题栏效果
        var objlis = document.getElementsByTagName('li');
        var objps = document.getElementsByTagName('p');
        for (var i=0; i<objlis.length; i++) {
            objlis[i].index = i;                //排除变量提升带来的影响; 把i保存起来
            objlis[i].onclick = function () {
 
 
                for (var j=0; j<objlis.length; j++){        //利用排他思想, 做标题部分的切换
                    objlis[j].className = '';
                    objps[j].className = '';
                }
                this.className = 'active';              //这里的this用objlis[i]行不行? 不行, 因为js的变量提升, 这个的i不是局部的,而是全局的
                console.log(i);                         //i 的结果是for完事后i的结果, 是 3
                objps[this.index].className = 'active';
            }
        }
    </script>
 
    变量的提升: 如何解决: 用不变的'对象.属性'来保存变量的值(上面的例子使用的就是此方法)
<script>
        //js中的变量提升
        console.log(a);     //打印的是;undefined , 而不是报错, 是因为js会把所有var的变量提升到文档的开头; 比如这里是将 var a; 放到了开头, 下面相当于直接赋值 a = 2.
        var a = 2;
        console.log(a);
        //js中的变量提升, 会带来一个问题: 作用域的问题, 会把局部的变量作用域搞成全局的.
        console.log(a);     //打印undefined(假设上面的a = 2不存在, 结果是undefined)
        {
            var a = 6;       //由于js的变量提升: 这句实际是两句: 第一句是在文档的最开头声明变量 var a; 第二句是在这里赋值变量 a = 6;
            console.log(a);     //打印6
        }
        console.log(a);         //打印6
    </script>
</body>
</html>
    
    变量的提升: 使用es6的let解决选项卡的问题: 而且var都可以用let替换, 不会有任何问题
<script>
    //用let声明变量, 不会存在变量提升, 属于局部
    console.log(a);         //直接报错,
    {
        let a = 3;
        console.log(a);
    }
    console.log(a);         //直接报错
</script>
   
     let解决变量提升
<script>
    var objlis = document.getElementsByTagName('li');
    var objps = document.getElementsByTagName('p');
    for (let i=0; i<objlis.length; i++) {
        objlis[i].onclick = function () {
            for (var j=0; j<objlis.length; j++){       
                objlis[j].className = '';
                objps[j].className = '';
            }
            objlis[i].className = 'active';    //这里原来的this 也就可以使用不会变量提升的: 局部的: let声明的变量i 了.         
            objps[i].className = 'active';     //这里原来的this 也就可以使用不会变量提升的: 局部的: let声明的变量i 了.
        }
    }
</script>
 
    自定义标签: 系统的东西都是可以自定义的
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        abc{
            width: 100px;
            height: 100px;
            
            display: block;
        }
    </style>
</head>
<body>
    <div id="box">
        <p class="child1">bajie</p>
    </div>
    <script>
        var objDiv = document.getElementById('box');
        var objP = document.createElement('abc');
        objDiv.appendChild(objP);
    </script>
</body>
</html>
 
    父.insertBefore('要插入的新节点','参考的节点')     #插入的是参考节点的兄弟节点
<body>
    <div id="box">
        <p class="child1">bajie</p>
    </div>
    <script>
        var objDiv = document.getElementById('box');
        var objP1 = document.getElementsByClassName('child1')[0];
        var objP2 = document.createElement('p');
        objDiv.insertBefore(objP2,objP1);      //插入到参考元素之前, 没有After
        objP2.innerText = 'wukong';
    </script>
</body>
 
二.定时器
    两种定时器: 
        一次性定时器: 可以做异步
        循环周期定时器: 可以做倒计时, 可以做动画:比如每一秒改动值, 
            js跟python一样都有垃圾回收机制    
            但是定时器对象, 垃圾回收收不回
        开定时器: 一次性定时器 
            var timer = setTimeout(fn, 1000)    #一秒之后调用fn函数
        开定时器: 循环定时器
            (interval 间隔)
            setInterval(fn, 1000)    #每一秒执行一次fn
        清定时器:
            clearTimeout(timer)    #开启定时器时,返回的定时器对象
            clearInterval(timer)
    一次性定时器:
<body>
    <button id="start">开启定时器</button>
    <button id="clear">清除定时器</button>
    <script>
        //一次性计时器主要是来做异步的
        var timer;                                  //全局变量,还是要在最外面写, 不要指望变量提升给你做这个事,
        document.getElementById('start').onclick = function () {
            //一次性定时器: 未来数据交互的时候, 如果数据阻塞了, 可以考虑加一个定时器来处理
            timer = setTimeout(function () {
                console.log(111)
            },3000);
            console.log(222);
            // clearTimeout(timer);    //此时的console.log(111)不会被执行
        };
        document.getElementById('clear').onclick = function () {        //清除的实际, 如果在开始计时后的3秒内按清理, 是可以阻止 111 的打印的
            clearTimeout(timer);
        }
    </script>
</body>
        
    循环定时器
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        #box{
            width: 100px;
            height: 100px;
            
        }
    </style>
</head>
<body>
    <button id="start">开启定时器</button>
    <button id="clear">清除定时器</button>
    <div id="box"></div>
    <script>
        var timer = null;
        var count = 0;
        document.getElementById('start').onclick = function () {
            var objDiv = document.getElementById('box');
            clearInterval(timer);                           //清除之前的定时器, 防止多次按钮的时候, 产生加速效果
            timer = setInterval(function () {
                count += 10;
                objDiv.style.marginLeft = count + 'px';
            },200)
        }
    </script>
</body>
</html>
 
 
三.js中的面向对象
    1.创建对象的几种常用方式
        使用Object()或对象字面量创建对象
 
<script>
    //使用Object(): 内置的构造函数来创建对象
    var person = new Object();
    person.name = 'bajie';
    person.age = 18;
    person.fav = function () {
        alert(person.name);
    }
    person.fav();
</script>
 
<script>
    //字面量方式创建对象: 推荐这种方式创建对象
    var person = {
        name: 'bajie',
        age: 18,
        fav: function () {
            alert(this.name);
        }
    };
    person.fav();
    //这两种方式创建非常简单, 但是有个问题, 当创建多个类似的对象时, 代码会重复多次, 如何解决? 使用"工厂模式"
</script>
 
        工厂模式创建对象: 把重复创建对象的过程写进函数中
 
<script>
    function createPerson() {
        var person = {
            name: 'bajie',
            age: 18,
            fav: function () {
                alert(this.name);
            }
        };
        return person;
    }
    var p1 = createPerson();
    var p2 = createPerson();
 
 
    console.log(p1 === p2);     //不是一个内存地址
    console.log(p1.age);
    //有个问题, 我们现在虽然可以源源不断地创建对象了, 但是我们不能一眼就看出来 p1, 和p2是属于哪个对象类型:
    console.log(p1 instanceof Object);  //instanceof 可以检测出p1是属于object类型,但是不能检测出是属于person
                                        //如何解决: 我们可以使用自定义的构造函数的方法来创建对象
</script>
 
        自定义的 构造函数模式创建对象
            在进行自定义构造函数创建对象之前, 我们首先了解一下构造函数和普通函数的区别
                1.实际上并不存在创建构造函数的特殊语法 ? 其与普通函数唯一的区别在于调用方法
                    对于任意函数, 只要使用new操作符调用, 那么它就是构造函数;
                    不使用new操作符调用, 那么它就是普通函数
                2.按照惯例, 我们约定构造函数以大写字母开头, 这样是为了有利于区分二者.
                    例如 new Array(); new Object();
<body>
    <script>
        //自定义构造函数
        function Person(name, age) {            //相当于python中的Class Person
            this.name = name;
            this.age = age;
            this.fav = function () {
                alert(this.name);
            };
        }
        var p1 = new Person('八戒', 18);        //相当于python中的实例化
        console.log(p1);                        //和原生的有一点不同: 原生的方法都在 __proto__里, 而自定义的方法直接在对象里
        p1.fav();
 
 
        function Fruit(name, age) {                //相当于python中的Class Person
            this.name = name;
            this.age = age;
            this.fav = function () {
                alert(this.name);
            };
        }
        var f1 = new Fruit('wukong', 100);
        console.log(p1 instanceof Object);
        console.log(f1 instanceof Object);
        console.log(p1 instanceof Person);
        console.log(f1 instanceof Fruit);          //四个打印的结果都是true, 而且能区分对象是属于哪个类了
                                                   //现在有个问题: 上面的Person和Fruit对象中有同样的方法, 当我们进行调用的时候, 无疑是内存的消耗
                                                   //如何解决: 原型模式创建对象
    </script>
</body>
 
        原型模式创建对象: 把几个对象相同的方法放到他们的父类中: 如 Person.prototype 就是Person的父类
<script>
    //(constructor 构造器)
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.showName = function () {   //原型: prototype
        console.log(this);                      //this 是谁? 是Person
    };
    var p1 = new Person('datang', 100);
    p1.showName();
    console.log(p1);                            //此时对象的方法就在__proto__里面了, 和原生的构造函数一样了
</script>
 
 
四.BOM
    BOM: 浏览器对象模型, 操作浏览器部分功能的api, 比如让浏览器自动滚动
    BOM: 我们需要记的不多, 因为浏览器都给我们做好了, 比如刷新按钮,前进后退, 标题栏上面的叉,滚动, 地址栏上的信息
    BOM是包含DOM的.
        BOM    window   history历史信息
                        location本地对象
                        screen屏幕
    1.弹出系统对话框
        alert()    不同浏览器外观不一样
        confirm()  兼容不好
        prompt()   不推荐
    2.打开窗口,关闭窗口
<script>
    //需求: 3秒后, 打开百度网页
    setTimeout(function () {
        // window.open('http://www.baidu.com/','_blank');  //(blank 空白的)模式不写默认就是在新窗口打开
        window.open('http://www.baidu.com/','_self');   //在自己当前窗口打开百度网址
    },3000);
</script>
    
    3.location对象
        window.location对象中有很多方法和属性
        属性:
            hash: url中'#asdf'这一堆
            host:主机(主机名+端口号)
            hostname: 主机名
            href:url完成地址                     : https://www.baidu.com:80/home/a.jpg?srt=info&asd
            origin:原始地址                      : https://www.baidu.com:80
            pathname:路径地址(也叫路由地址)        : /home/a.jpg
            search:                            : ?srt=info&asd
            port:端口
            protocol:协议, https: 是把用户名密码打包在传输, s = ssl
        方法:
            reload(): 就是网页上的刷新
            toString()
<script>
    window.location.href = 'http://www.baidu.com';  //也可以进行网页的跳转 , 是在当前窗口打开
</script>
    
    4.(navigator 领航员)
        userAgent: 用户代理,用的什么浏览器
 
    5.history
        history.go(-1): 上一页
        history.go(0): 刷新
        window.location.reload():刷新    //这三个都是全局刷新, 尽量少用. 局部刷新比较好(必用ajax)
 
 
 
 
 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!