BOM与DOM

99 阅读9分钟

案例(面试题)

/*
            1. 买卖股票的最佳时机, 给定一个数组, 他的第 I 个元素是一只股票第 I 天的价格, 
                如果你最多只允许完成一次交易 (也就是买入和卖出一只股票一次), 请你设计一个算法来计算你能获取到的最大的利益

            注意: 你不能在购买股票前卖出股票
                示例: 输入 [7, 1, 5, 3, 6, 4,]; 输出: 5

                    解释: 在第 2 天(当天的股票价格等于1)的时候买入, 在第5天的时候卖出(当天股票的价格等于6, 
                            所以你最大的利润为 6 - 1 === 5

                    注意: 利润不能是 7 - 1 === 6, 因为第二天的价格为 1, 第一天的价格为 7, 
                            你是不可能在第二天买入股票然后等到第一天的时候卖出)
*/
方法一
/* for(var i= 0  ){}
          [7, 1, 5, 3, 6, 4,]  天数为 i
    天数   1  2  3  4  5  6
     i     0  1  2  3  4  5
        不能   利润不能是 7 - 1 === 6, 因为第二天的价格为 1, 第一天的价格为 7, 
        你是不可能在第二天买入股票然后等到第一天的时候卖出)
        说明 执行 只能从开始索引到末尾索引 顺序
          i     买入(天数)    卖出(天数) j                             利润 
          0     1              2 i+1   1         1(第2天)-7(第1天)  ===-1
                               3       2            -5                -4
                               4       3            -3                -2
                               5       4            -6                -5
                               6       5            -4                -3 

          1     2              3                  
                               4
                               5
                               6

          2     3              4
                               5 
                               6

          3     4              5
                               6

          4     5              6
        */



        /*
        准备一个容器用于储存最大值
          使用双重for循环
           第一层循环表示 买入的天数
           第二层循环表示 卖出的天数
        使用if循环 变量 求 交换最大利润(最大值) = 卖出-买入
           执行顺序为从开始索引到结束索引
        */
        var max = 0;
        // 准备一个容器用于储存最大值
        // 使用双重for循环
        var arr = [7, 1, 5, 3, 6, 4,];
        for (var i = 0; i < arr.length - 1; i++) {
            // 第一层循环表示 买入的天数
            // console.log(i);
            for (var j = i + 1; j < arr.length; j++) {
                // 第二层循环表示 卖出的天数
                // console.log('买入'+i,'卖出'+j);
                if (arr[j] - arr[i] > max) {
                    // 使用if循环 变量 求 交换最大利润(最大值) = 卖出-买入
                    max = arr[j] - arr[i]
                    //        arr[1]-arr[0] >arr[2]-arr[0]
                    //            2      1      3      1
                }
            }
        }
        console.log(max);

方法二
/**
         *  逻辑:
         *      1. 一个 for 循环, 拿到数组的每一项
         *      2. 第二个 for 循环, 拿到外循环后边的所有数组的每一项
         *      3. 计算后边的数据和前边的数据的最大差值
        */

        var arr = [1000, 7, 1, 5, 3, 6, 4, 100]
        var max = 0
        // 1. 一个 for 循环, 拿到数组的每一项
        for (var k = 0; k < arr.length - 1; k++) {
            // 2. 第二个 for 循环, 拿到外循环后边的所有数组的每一项
            for (var i = k + 1; i < arr.length; i++) {
                if (arr[i] - arr[k] > max) {
                    max = arr[i] - arr[k]
                }
            }
        }

        console.log(max)        

BOM本地存储

  1. storage
    • localStorage
      • 浏览器本地存储持久存储,一旦存储永久存在
      • 只能存储基本数据类型(一般就是字符串),如果其他数据类型存储必须转换为字符串能够跨页面通讯
      • 例如:我在A页面存储,但是在网页面能够获取到,那么就是跨页面通讯
    • sessionStorage
      • 浏览器本地存储,临时存储,关闭浏览器以后,在储内容自动消失
      • 如果要跨页面通讯,必须是从本次页面跳转的才可以打开
      • 增; 删; 清除; 获取; 和 localStorage 一样
    1. 新增一个本地存储
    • window.LocalStorage.setItem(key,vaLue)
    • key 相当于变量名,vaLue 你真正要存储的值
    1. 删除一个本地存储
    • window.localStorage.removeItem(key)
    • 你要删除哪一个本地存储,就把这个key写成哪一个
    1. 清空一个本地存储
    • window.localStorage.clear()
    1. 查询一个本地存储的值 返回值: 查询到: 把这个key对应的value返回出来 没有查询到: 返回一个null
    2. 存储引用数据类型(数组---对象)
错误存储方式:
    错误存储数组
        var arr = [1, 2, 3, 4, 5]
        window.localStorage.setItem('arr', arr)
        var res = window.localStorage.getItem('arr')
        console.log(res)
    错误存储对象
        var obj = {
            name: 'QF001',
            age: 18
        }
        window.localStorage.setItem('obj', obj)
        var res = window.localStorage.getItem('obj')
        console.log(res)
        window.localStorage.setItem('wx', '12345');
        window.localStorage.setItem('qq', '123156');
        window.localStorage.getItem();

JSON

  • 在 JS 中 有一个对象叫做 JSON, 她提供了两个方法
    1. JSON.stringify(传入要转换的数据) 能够将其它类型的数据, 转换为 JSON 格式的字符串
    2. JSON.parse(传入要转换的数据) 能够将 JSON 格式的字符串, 转换为 原本的数据类型
var obj = {
            name: 'QF001',
            age: 18
        }
        var newObj = JSON.stringify(obj)

        var arr = [1, 2, 3, 4, 5]
        var newArr = JSON.stringify(arr)

        // console.log(obj)
        // console.log(newObj)
        // console.log(arr)
        // console.log(newArr)

        window.localStorage.setItem('arr', newArr)
        window.localStorage.setItem('obj', newObj)

        var arr1 = JSON.parse(window.localStorage.getItem('arr'))
        var obj1 = JSON.parse(window.localStorage.getItem('obj'))

        console.log(arr1)
        console.log(obj1)
<h1>我当前页面没有做任何本地存储, 但是我能够获取到其他的本地存储</h1>
    <script>
        // 1. 获取本地存储的内容
        var res1 = window.localStorage.getItem('arr')
        var res2 = window.localStorage.getItem('obj')
        console.log(res1);
        console.log(res2);
        var res3 = window.sessionStorage.getItem('QQ')
        console.log(res3);
    </script>

cookie

注意事项

1. 只能存储字符串,并且有固定的格式 key==value  a==100  qq=888
2. 存储大小有限制   4kb左右
3. 操作  cookie  必须依赖服务器(本地启动文件不能运行cookie)
            目前可以借助vscode 的插件  live server
4. 跟随前后端交互,自动携带
            将来我们前端向后端发送请求的时候, 如果 cookie 内有数据, 那么会自动携带
5. 前后端操作
           前端: JS;  后端: 任何一个后端语言都可以操作cookie 
6. 存储依赖域名
            哪一个域名存储, 哪一个域名能够使用, 不能跨页面通讯
  • cookie 的有效期
    1. 默认是会话级别(浏览器关闭, 自动删除), 我们也可以手动的添加一个过期时间
    2. 我们在设置时间的时候 是按照世界标准时间走的
    3. 但是我们的时间是东八区时间, 所以在处理的时候, 应该先将这个时间往后调整 8 小时

cookie 和 storage 的区别(面试题)

  1. 出现时间: cookie 有js的时候就存在了 storage H5出现以后才出来
  2. 存储大小: cookie 4kb storage 20MB/5MB
  3. 前后端交互 cookie 请求时自动携带 storage 请求时不会自动携带,可以手动携带
  4. 前后端操作 cookie 前端后端都可以操作 storage 只有前端 JS 能操作
  5. 过期时间 cookie 默认会话级别, 但是可以手动设置过期时间 storage 不能手动设置过期时间

localStorage和sessionStorage的区别(面试题)

  1. 过期时间 localStorage: 永久存储 sessionStorage: 临时存储
  2. 跨页面通讯 localStorage: 直接跨页面通讯 sessionStorage: 只能是从当前窗口跳转过去的页面才可以通讯
  3. 共同点 => 只能存储字符串, 不能存储复杂数据类型 => 直接存储其他数据类型, 获取回来的也是字符串类型
cookie代码解析
//    设置一条 cookie
        // document.cookie = 'QQ=12345'
        // document.cookie = 'WX=15619'
        // // 获取cookie
        // console.log(document.cookie);

        //    设置一条过期的cookie
        var timer = new Date()
        document.cookie = 'QQ=12345;expires=' + timer
        console.log(document.cookie);
        // expires  有效期为  

        // 设置一条 30S 后过期的 cookie
        var time1 = new Date();
        // 当前时间的毫秒数 - 8小时的毫秒数 + 指定过期时间的毫秒数   
        // === timer.getTime() - 1000 * 60 * 60 * 8 + 30 * 1000
        time1.setTime(time1.getTime - 8 * 60 * 60 * 1000 + 2 * 1000)
        //    time1.setTime  设置当前毫秒数
        document.cookie = 'QQ=12345;expires=' + time1

        setTimeout(function () {
            console.log(document.cookie)
        }, 4000)
        // 当2秒结束后到4s结束后打印内容

DOM

  • 获取页面的常规元素
    • DOM 文档对象模型 其实就是一些操作HTML节点
    • 获取一个元素(标签/节点/DOM节点)移除一个元数
    • 创建一个元素
    • 给页面中添加一个元素
    • 给元素绑定一下事件(单击事件,双击事件。键盘按下事件....)获取元系的一些属性
    • 获取元系的Css样式
    • 给一个元素添加cSs样式
  • DOM的核心就是document对象
  • document对象是浏览器内置的一个对象,里面存储着专门用来操作元素的各种方法
// 1.打印整个html里面的内容
        console.log(document);
        var htmlEle = document.documentElement
        console.log(htmlEle);
        //2.打印整个head内容
        var headEle = document.head
        console.log(headEle);
        //3.打印整个body标签里面的内容
        var bodyEle = document.body
        console.log(bodyEle);

        // 获取 id 标签内容
        var idEle = document.getElementById('test');
        console.log(idEle);
        // 获取id名为'test'的标签内容

        // console.log(id_box);// 这是一个错误写法,不允许使用
        // 1. 通过元素的 ID 名获取标签
        //   在 JS 中有一个不规范的写法, 这是一种错误写法
        //   一个标签的 ID 名, 在 JS 中, 可以直接当作一个变量使用
        //通过元素的class名获取 class 标签内容
        var classELe = document.getElementsByClassName('box1')
        console.log(classELe); // 打印的是伪数组
        console.log(classELe[1]);//<div class="box1"></div>

注意:

    1. getElelemt    s    ByClassName
    2. 获取到的元素, 放在了一个长得很像数组的数据结构内
       我们可以通过下标去获取到准确的 DOM节点, 也可以通   length 知道获取了多少个元素
       但是数组的一些方法不能使用, 比如 forEach, map....
       我们给这个数组起了个名字叫做 伪数组
        //通过元素标签获取 标签/元素内容  (tag) 
        var tag = document.getElementsByTagName('div');
        console.log(tag);// 打印的是伪数组
        // 没有返回 HTMLCollection []
        //     返回 打印其内容

        // name
        var nameEle = document.getElementsByName('box2');
        console.log(name);//伪数组

        // querySelector
        
        /*   4. 类似 css 选择器的方式获取标签
               获取到的是页面中第一个符合要求的标签
        */
       var new_div_box = document.querySelector('div')
        var new_div_box = document.querySelector('.box1')
        console.log(new_div_box)// 注意这是返回的是标签,不是内容
/*
  *  5. 获取到页面中所有符合要求的 标签
  * 
  *      也是一个伪数组的形式, 但是能使用 forEach
  * 
  *      个人建议, 使用伪数组的时候, 不要使用数组的方法
  *      最好的方式将这个伪书组转换成真实数组
  * 
  *      var arr = [...伪数组]
*/         
        var new_div_box = document.querySelectorAll('div')
        var new_div_box = [...document.querySelectorAll('div')]
        console.log(new_div_box)

操作元素


    
           获取到DOM 节点 之后可以直接操作,节点的属性,并直接渲染的页面
        */
        // 0. 获取元素
        var box0 = document.querySelector('.box1');
        var id_b = document.getElementById('id_box');

        // 1.innerhtml 获取标签内部的结构
        console.log(box0.innerHTML);
        //设置的时候能够解析字符串中的 html 标签
        id_b.innerHTML = '<p>26615159</p>';
        //26615159
        // 2. innerText 获取元素内部的文本 (也就是说获取不到 html 标签)

        // console.log(boxO.innerText)
        console.log(id_b.innerText);//26615159
        // 设置的时候会将字符串的所有内容添加到标签的文本区, 字符串中哪怕是写了标签, 他也不认识
        id_b.innerText = '<p>26615159</p>'
        // <p>26615159</p>

        // 3. 获取元素的某个属性 (包括自定义属性)
        console.log(id_b.getAttribute('a')) //1316
        // getAttribute 获取到当前标签的这个属性对应的值
        console.log(id_b.getAttribute('id'))//id_box
        // getAttribute 获取到当前标签的这个属性对应的值

        // 4. 设置元素的某个属性

        id_b.setAttribute('my_box', 'QF001') // 新加一个属性
        id_b.setAttribute('a', 'QF666')      // 修改原有的属性

        // 5. 删除元素的某一个属性
        boxT.removeAttribute('a')   // 将这个标签的属性a, 删除

获取标签

<body>
    <div class="box box_t" num="100" data-id="QF001" data-xbox="QF002">
        这里展示的是一个商品
    </div>
    <script>
        var bo_x = document.getElementsByClassName('box')[0];
        //获取标签
        /*
          1. H5 自定义属性
              属性名是   data-  后边的内容
              如果一个 H5 自定义属性写为: data-id="QF001"
                    属性名: id
                    属性值: 'QF001'
         
              data-   的作用仅仅表示这是一个 H5的自定义属性
        */

// 1. 增加  节点.dataset.要新增的属性名 = '对应的属性值'
        console.log(bo_x);
        //  在打印的时候 也打印出来 name='张三'
         bo_x.dataset.name = '张三';
         console.log(bo_x); //会增加  name = '张三'

        // // 2. 删除
         delete bo_x.dataset.id
        // // 3.获取
         console.log(bo_x.dataset.xbox);// QF002 // 为字符串

        // /**
        //  *  2. style
        //  *      专门用来给某个元素添加 css 样式
        //  *      添加的样式是行内样式
        // */

         bo_x.style.width = '100px'
         bo_x.style.height = '100px'
         bo_x.style.backgroundColor = 'blue'


        /**
         *  3. className
         *
         *      专门用于操作元素类名; 设置类名的时候, 不管之前有多少个, 直接全部覆盖
         *
         *      classList
         *          也是用于操作元素类名的, 具有一些方法, 如下所示
        */

         bo_x.className = 'new_box'
         console.log(bo_x.className)


        // 新增一个类名
        bo_x.classList.add('new_box')
        console.log(bo_x.classList)

        // 删除一个
         bo_x.classList.remove('new_box')
         console.log(bo_x.classList)
    </script>