JavaScript - day11

21 阅读3分钟

一、BOM的常用对象

1.1 history对象

保存了当前窗口的历史纪录(过去的url)
  • 前进:history.go(1);
  • 后退:history.go(-1);
  • 刷新:history.go(0);
<script>
    // 前进
    history.go(1)
    // 后退
    history.go(-1)
    // 刷新
    history.go(0)
</script>

1.2 location对象

保存了当前窗口的正在打开的url(现在的url)
  • 一个url的组成部分:
    1. 协议:*https(加密)/*http(未加密)/ftp(传输文件)/ws(直播)... 前两个都属于叫做请求-响应模型
    2. 主机号|IP地址|域名:域名是需要花钱购买的,主机号|IP地址是免费,127.0.0.1才真的是叫做主机号,只能自己访问自己
    3. 端口号:https默认端口为443,http默认端口为80,只有默认端口可以省略不写
    4. 文件的相对路径|路由:百度加密了
    5. 查询字符串|请求消息:前端传输到后端的东西
  • 获取url的5个部分的内容,可以输入location对象查看:
    1. 协议:location.protocal;
    2. 域名:location.hostname;
    3. 端口:location.port;
    4. 路由:location.pathname;
    5. 请求消息:location.search;
<script> 
    console.log(location);//href:"http://127.0.0.1:5500/%E4%BD%9C%E4%B8%9A/%E6%9D%A8%E7%8E%89%E5%8D%8E%20-%20%E7%AC%AC%E4%B8%89%E5%91%A8%E4%BD%9C%E4%B8%9A/day11/02-location%E5%AF%B9%E8%B1%A1.html"
    // 协议
    console.log(location.protocol);//http:
    // 域名
    console.log(location.hostname);//127.0.0.1
    // 端口号
    console.log(location.port);//5500
    // 路由 console.log(location.pathname);///%E4%BD%9C%E4%B8%9A/%E6%9D%A8%E7%8E%89%E5%8D%8E%20-%20%E7%AC%AC%E4%B8%89%E5%91%A8%E4%BD%9C%E4%B8%9A/day11/02-location%E5%AF%B9%E8%B1%A1.html
    // 请求消息
    console.log(location.search);// 
</script>
  • 跳转:location="新url" - 替换当前窗口,可以后退
  • 跳转后,禁止后退:location.replace("新url") - 替换当前窗口,禁止后退
  • 刷新:location.reload();

二、DOM

2.1 查找元素

var elem=document.querySelector("任意css选择器的");
  • 缺陷:只能找到单个元素,如果匹配到了多个,也只会返回第一个,没找到null
var elems=document.querySelectorAll("任意css选择器的");
  • 优点
    1. 找到了是一个集合,没找到是一个空集合
    2. 复杂查找时,非常简单
    3. 返回的是一个静态集合NodeList
<ul>
    <li></li>
    <li></li>
    <li></li>
</ul>
<ul>
    <li></li>
    <li></li>
    <li></li>
</ul>
<script>
    var li1 = document.querySelector('li')
    console.log(li1)//找到的是第一个ul里面的第一个li
    // 要想找到第二个ul里面的所有li
    var lis = document.querySelectorAll('ul')[1].querySelectorAll('li')
    console.log(lis);
</script>

2.2 document.getXXX 和 document.queryXXX的区别

  1. 后者更适合复杂查找
  2. 前者返回的是一个动态集合:每一次DOM发生变化,他都会悄悄的再次查找,让页面和数据保持一致,但是效率也就低下了 - 不支持forEach
  3. 后者返回的是一个静态集合:每一次DOM发生变化,他不会悄悄的再次查找,让页面和数据没有保持一致,但是效率也就高了 - 支持使用forEach

2.3 操作样式表

  1. 获取你想要操作的样式表
var sheet=document.styleSheets[i];
  1. 获取此样式表种所有的样式规则
var rules=sheet.cssRules;
  1. 数出你想要操作的那个规则的
var rule=rules[i];
  1. 操作
console.log(rule.style.css属性名)
rule.style.css属性名="css属性值";

2.4 DOM分类:

  • 核心DOM:即可以操作HTML又可以操作XML,但是语法相对比较繁琐
  • HTML DOM:只可以操作HTML
  • XML DOM:只可以操作XML

2.5 操作属性

  • 获取属性值
    1. 核心DOM:elem.getAttribute("属性名");
    2. HTML DOM:elem.属性名;
  • 设置属性值:
    1. 核心DOM:elem.setAttribute("属性名","属性值");
    2. HTML DOM:elem.属性名="属性值";
  • 删除属性:设置属性值为空字符串,确实某些属性可以算是删除,但是只是删除了属性值,属性名还在,而有的属性哪怕只有一个属性名,也会具有作用(比如:href、disabled、readonly)
    1. 核心DOM:elem.removeAttribute("属性名");
    2. HTML DOM:elem.属性名=""; - 属性节点删不干净
  • 判断有没有:只能判断有没有,不能判断是什么,推荐用elem.getAttribute("属性名");去获取到值,自己再写比较运算
    1. 核心DOM:elem.hasAttribute("属性名");
    2. HTML DOM:elem.属性名!="";

2.6 元素上树的三种方式:

  1. 父元素.appendChild(elem);//在父元素末尾处追加一个子元素elem
  2. 父元素.insertBefore(elem,已有子元素);//在父元素追加一个子元素elem,但是放在已有子元素的前面
  3. 父元素.replaceChild(elem,已有子元素);//在父元素追加一个子元素elem,但是会替换掉已有子元素

2.7 删除元素:

elem.remove();

三、let

let 变量名=值;

作用

  1. 解决了声明提前
  2. 带来了块级作用域,一个{}就是一个块,此变量只能在那个{}里面使用
  3. 如果用let去当作下标绑定事件,那么他会记录着你当前元素的下标,不再需要自定义下标了 - 其实forEach的那个形参i就是let创建的

四、类数组转为普通数组:接住=Array.from(类数组对象);

五、案例

<div id="menu"></div>
<span>>></span>
<div id="content"></div>
<script>
    // 开关门效果
    var span = document.querySelector('span')
    span.onclick = function(){
        span.innerText = span.innerText == '>>'?'<<':'>>'
        content.style.display = span.innerText == '>>'?'block':'none'
    }
</script>
<ul>
    <li></li>
    <li></li>
    <li></li>
</ul>
<section>
    <div class="active"></div>
    <div></div>
    <div></div>
</section>
<script>
    // 选项卡
    var lis = document.querySelectorAll('li')
    var divs = document.querySelectorAll('div')
    lis.forEach((li,i)=>{
        li.onclick = function(){
            divs.forEach(div=>div.className = '')
            divs[i].className = 'active'
        }
    })
</script>
<ul id="ul">
    <li>name1</li>
    <li>name2</li>
    <li>name3</li>
    <li>name4</li>
    <li>name5</li>
    <li>name6</li>
    <li>name7</li>
    <li>name8</li>
    <li>name9</li>
    <li>name10</li>
</ul>
<script>
    // 摇号功能
    // 拿到所有的li
    var lis = document.querySelectorAll('li')
    // 创建一个新数组用来装排序的数
    var num = []
    // 死循环 - 当num的长度和lis的长度一致时退出循环
    while(num.length < lis.length) {
        // 创建随机数
        var r = parseInt(Math.random()*(lis.length))
        // 如果num中没有这个数则向num中加入这个数
        if(num.indexOf(r) == -1) {
            num.push(r)
        }
    }
    // 给li设置自定义属性
    lis.forEach((li,i)=>li.setAttribute('nn',num[i]))
    // 把类数组变为数组
    lis = Array.from(lis)
    // 对数组进行排序
    lis.sort((a,b)=>a.getAttribute('nn') - b.getAttribute('nn'))
    // 上树
    lis.forEach(li=>ul.appendChild(li))
</script>
<select id="lsel" size="5" multiple>
            <option>Argentina</option>
            <option>Brazil</option>
            <option>Canada</option>
            <option>Chile</option>
            <option>China</option>
            <option>Cuba</option>
            <option>Denmark</option>
            <option>Egypt</option>
            <option>France</option>
            <option>Greece</option>
            <option>Spain</option>
    </select>
    <div>
            <button id="btn1">>></button>
            <button id="btn2">></button>
            <button id="btn3"><</button>
            <button id="btn4"><<</button>
    </div>
    <select id="rsel" size="5" multiple>
    </select>
<script>
    // 国家的移动
    // 设置左右空数组
    var larr = [];
    var rarr = [];
    // 拿到每一个国家并且放在左数组中
    larr = lsel.innerHTML.trim().slice(8,-9).split('</option>\n\t\t<option>');
    // 拿到所有的button
    var btns = document.querySelectorAll('button');
    // 遍历btns
    btns.forEach(btn=>{
        // 点击事件
        btn.onclick = function(){
            // 判断按钮
            switch(this.innerText){
                case '>>':
                    // 把左数组的内容全部拼接到右数组
                    rarr = rarr.concat(larr);
                    // 左数组设置为空
                    larr = [];
                    break;
                case '<<':
                    larr = larr.concat(rarr);
                    rarr = [];
                    break;
                case '>':
                    // 拿到sel1里面的option
                    var op1 = lsel.children;
                    // 倒着循环
                    for(var i = op1.length - 1; i >= 0; i--) {
                        // 判断option是否被选中
                        if(op1[i].selected) {
                            // 如果这个被选中就把这个option给删除了并且拼接到右数组
                            rarr = rarr.concat(larr.splice(i,1));
                        }
                    }
                    break
                default :
                    var op2 = rsel.children;
                    for(var i = op2.length - 1; i >= 0; i--) {
                        if(op2[i].selected) {
                            larr = larr.concat(rarr.splice(i,1));
                        }
                    }
            }
            // 数组按照字符串pk排序
            larr.sort();
            rarr.sort();
            // 判断左数组的长度是否为0
            if(larr.length == 0) {
                // 为0则设置左边select内容为空
                lsel.innerHTML = '';
            } else {
                lsel.innerHTML = '<option>' + larr.join('</option><option>') + '</option>';
            }
            // 右
            if(rarr.length == 0) {
                rsel.innerHTML = '';
            } else {
                rsel.innerHTML = '<option>' + rarr.join('</option><option>') + '</option>';
            }
        }
    })
</script>