08-JS BOM和DOM

  1. BOM是浏览器对象模型,DOM是文档对象模型;
  2. 前者是对浏览器本身进行操作,而后者是对浏览器(可看成容器)内的内容进行操作。
  3. window((location,history,document->DOM,navigater)->BOM),BOM包含有DOM

1.BOM对象

  1. BOM是Browser Object Model的缩写,即浏览器对象模型。
  2. BOM没有相关标准。不同浏览器定义有差别,实现方式不同。
  3. BOM的最根本对象是window。
  • 全局变量

    全局变量存在 window对象之中;

    a = 10;
    delete window.a;
    console.log(a);       //a没有被删除,不会报错
    
  • 伪全局变量

    未经var声明变量的就是伪全局变量;

    a = 10;
    delete window.a;
    console.log(a);   // a此时被删除,报错;
    
  • window

    浏览器端JS的核心对象,每个浏览器独有,有非常大的兼容问题

    window.document

    window.alert

    window.location

    window.navigator

    window.screen

    //文档内部的宽高
    console.log(innerWidth,innerHeight);
    //包含浏览器控制台的高度,自带margin是8px,只包含了左侧的8px
    console.log(outerWidth,outerHeight);
    //显示器屏幕的所有宽高
    console.log(screen.width,screen.height);
    //不包括底下任务栏的宽高
    console.log(screen.availWidth,screen.availHeight);
    
    console.log(screenX,screenY);//窗口位置坐标
    console.log(screenLeft,screenRight);//同上
    
  • location对象

    location对象 区别 历史记录 能否返回
    location.href="http://www.163.com"; 跳转页面,可以获取当前地址 可以
    location.assign("http://wwww.163.com"); 页面跳转,不能获取当前地址 可以
    localtion.repalce("http://wwww.163.com"); 页面跳转 没有 不可以
    location.reload();    //刷新缓存
    location.reload(true);    //底层刷新 Alt + F5
    console.log(location.hostname);   //域名
    console.log(location.pathname); //路径和文件名
    console.log(location.port);   //端口号
    console.log(location.protocol);   //访问协议
    
    //页面跳转,用location.search接收"?"参数后面的内容
    location.href = "aa.html?a=3&b=4";
    console.log(location.search);
    
    location.hash;
    // 浏览器地址栏中的"#"后面内容,路由跳转,超链接的锚点标记,
    //点击之后必须刷新页面才能在控制台出现内容,
    //因为不刷新时页面还没有装载完成;
    
image.png
  • 网页文档的树形结构
image.png
  • 弹出框
confirm("请点击确认");
var res = parseInt(prompt("请输入一个整数"));
  • window.onload()事件

当页面中所有图片 | 内容加载结束才会执行代码

window.onload = function(){
    console.log(img.width);//刚开始获取不到图片的宽和高,页面加载之后才会执行
    console.log(img.height);
}
  • window.onscroll()事件

屏幕滚动时候触发

window.onscroll = function(){
    console.log(1);
}
  • window.onresize()

窗口的大小发生改变时候触发

  • history

当访问历史的时候是不会进行重载的,是将原来的内容直接打开,回退的时候会保留原始页面的部分内容,如文本框里的数据,但是不会保留密码框的数据

history.back();//返回上一层

history.forword();//向前一层

history.go(0);//刷新页面

history.go(1);//向前一个历史

history.go(-1);//向后一个地址

//页面跳转的记录
//要将一个数据与另一个页面共享数据
console.log(history.state);

history.length;//历史记录的数量
  • navigator
//获取当前浏览器的内核和版本信息
console.log(navigator.userAgent);

2.DOM

  1. DOM是Document Object Model的缩写,即文档对象模型。
  2. DOM是W3C的标准。
  3. DOM最根本对象是document(实际上是window.document)
  4. DOM(Document Object model)结构,树形结构。
  5. Object-->EventTarget--->Node--->Element--->HTMLElement--->HTMLDivElement
  • DOM的元素

把标签统称为元素Element;节点也是元素

console.log(document.documentElement); //HTML
console.log(document.head); //head标签
console.log(document.body); //body标签
  • DOM元素的基本操作
document.createElement("div");  //创建一个div元素
document.body.appendChild(div);     //向页面中加入创建的div
document.body.insertBefore(div,box);    //把div插入在box前面
document.getElementById()   // 通过ID号查找元素
document.getElementsByTagName()    //通过标签名称查找元素
document.getElementsByName()     // 通过name属性来查找元素
document.getElementsByClassName()   //通过class属性来查找元素
  • 节点

    image.png
    • nodeName(节点名称)
    1. 元素节点的nodeName是标签名称
    2. 文本节点的nodeName永远是#text
    3. 注释节点的nodeName永远是#comment
    4. nodeName用在两个地方,分辨标签名和获取属性节点名称的时候
    • 判断节点是否为div
    console.log(div.nodeName === "DIV");
    
    • nodeValue
    1. 元素的nodeValue不可用
    2. 注释节点nodeValue包括注释内容
     <div>
        <div>
            <div>0</div>
            <ul>
                <li>1</li>
                <li>2</li>
                <li id="li0">3</li>
                <li>4</li>
                <li>5</li>
            </ul>
        </div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </div>
    
    console.log(document.body.firstChild); //第一个子节点
    console.log(document.body.firstElementChild); //第一个子元素
    console.log(document.body.lastChild); //最后一个子节点
    console.log(document.body.lastElementChild); //最后一个子节点
    console.log(document.body.childNodes); //子节点列表
    console.log(document.body.children); //子元素列表
    //将以上每个li打印出来
    console.log(document.body.firstElementChild.firstElementChild.lastElementChild.Child);
    console.log(document.getElementsByTagName("div"));//获取的是列表项,不是数组
    //需要遍历时,还需要将其转换为数组 ——Array.from();
    
    var li0 = document.querySelector("#li0");
    console.log(li0.parentNode); //父节点
    console.log(li0.parentElement); //父元素
    
    console.log(li0.nextSibling); //下一个兄弟节点
    console.log(li0.previousSibling); //上一个兄弟节点
    
    console.log(li0.nextElementSibling); //下一个兄弟元素(非W3C标准)
    console.log(li0.previousElementSibling); //上一个兄弟元素(非W3C标准)
    
  • 测试节点类型——nodeType

    image.png
  • 获取节点元素

    选择器 选择内容 是否有forEach方法 适用范围
    querySelector 一个元素 所有节点
    getElementById 一个元素NodeList document方法
    getElementsByName 获取列表NodeList document方法
    querySelectorAll 获取列表Nodelist 所有节点方法
    getElementsByClassName 获取列表 HTMLCollection 所有节点方法
    getElementsByTagName 获取列表 HTMLCollection 所有节点方法

    HTMLColllection不能自己遍历,而NodeList可以用forEach方法自己遍历

  • jQuery选择器

    // 根据选择器获取到内容第一个元素
    var div1 = div.querySelector("div"); //标签选择器
    document.querySelector("#div1"); //id选择器
    document.querySelector(".div0"); //class选择器
    document.querySelector("div .div1"); //后代选择器
    document.querySelector("div>.div1"); //子代选择器
    document.querySelector("div~.div1"); //兄弟选择器
    document.querySelector("div+.div1"); //唯一兄弟选择器
    document.querySelector("div,.div1"); //群组选择器
    document.querySelector("[type=input]"); //属性选择器
    
  • 文本节点

    • innerHTML | innerText

      1. 设置 : innerHTML 原样设置 ; innerText 转义后设置内容;
      2. 取值 : innerHTML 原样取值 ; innerText 取出文本,标签不取出;
    • 点击页面,在超链接之前,插入文本
    var a = document.createElement("a");
    a.href = "#";
    a.textContent = "超链接";
    div.appendChild(a);
    
    document.addEventListener("click", clickHandler);
    function clickHandler(e) {
        // div.textContent="你好";//这种方式会覆盖超链接
        // 创建文本节点
        var text = document.createTextNode("你好");
        div.insertBefore(text, a);
        //给父元素里指定的位置插入子元素
        var divs = document.createElement("div");
    }
    
 //根据给入标签名创建标签
document.createTextNode("文本") //根据给入的文本创建文本节点
parent.appendChild(child) //给父元素插入子元素, 追加在尾部
parent.insertBefore(要插入的新元素, 插入在谁的前面)// 给父元素里指定的位置插入子元素
document.createDocumentFragment() //创建文档碎片
  • 插入在父元素的第一个子元素前
function insertFirst(parent, elem) {
    parent.insertBefore(elem, parent.firstChild);
}
  • 插入在当前父元素的后面
function insertNext(prev, elem) {
    prev.parentElement.insertBefore(elem, prev.nextSibling);
}
  • 插入在当前父元素的前面
function insertPrev(target, elem) {
    target.parentElement.insertBefore(elem, target)
}
  • 给当前元素包裹一个父元素
function warp(child, parent) {
    insertPrev(child, parent);
    parent.appendChild(child);
}
  1. 如果需要创建元素,已经多个子元素,先不要将父元素放在页面;
  2. 先把子元素全部放入父元素后,然后再将父元素放在页面中;
  3. 如果没有父元素的时候,则需要创建文档碎片
  • 创建文档碎片
  1. 文档碎片用来解决什么问题 ?批量操作元素的时候 , 我们需要一个容器 ;
  2. 文档碎片是一个和DOM一样的容器结构,它不会在页面中被渲染, 只是简单的作为容器使用。
var elem = document.createDocumentFragment();
//这里如果不使用DocumentFragment,而使用var wrap = document.createDocument("div");也可以,只是在文档中会多增加一个标签。
for (var i = 0; i < 50; i++) {
    var div = document.createElement("div");
    div.innerHTML = "hello world" + i;
    elem.appendChild(div);
}
document.body.appendChild(elem);
  • 删除元素(并非彻底删除)
div.remove();//仅仅是从文档流中删除
div = null; //彻底删除
div.removeChild(a);//删除子元素
parent.removeChild(child);//父元素删除子元素
  • 复制节点
//原元素.cloneNode(是否深复制);
var cloneAll = box.cloneNode(true);
cloneNode => cloneNode()    => 复制节点的皮;
          => cloneNode(true)=> 复制节点的全部内容;
  • innerHTML 和 innerText 区别
  1. innerHTML会原样输出
  2. innerText会解析到浏览器
<ul id="box">xyz
     <li>a</li>
     <li>b</li>
     <li>c</li>
     <li>d</li>
</ul>
console.log(box.innerHTML);//原样输出
//xyz
//<li>a</li>
//<li>b</li>
//<li>c</li>
//<li>d</li>

console.log(box.innerText);//会解析到浏览器执行
//xyz  a  b  c  d 
  • 自定义属性的值
//设置
box.setAttribute("index",99);
//删除
box.removeAttribute();
//获取
box.getAttribute("index");
  • 获取节点
parentNode   //获取父节点
childNodes    //获取所有子节点
children   //获取所有子标签(非W3C标准)

previousSibling   //前一个兄弟节点
nextSibling       // 后一个兄弟节点
previousElementSibling     //前一个兄弟元素(非W3C标准)
nextElementSibling         //后一个兄弟元素(非W3C标准)
  • 根据使用习惯封装通用选择器
function $(selector){
    var firstSelector = selector[0];
    if(firstSelector === "#"){
       return   document.querySelector( selector );
       }
    reutrn document.querySelectorAll( selector );
}
  • 设置元素的样式
 var box = document.getElementById("box");
 box.style.color = "#f99";
 box.style.background = "yellowgreen";
 box.style.cssText = "color: rgb(255, 153, 153); background: orange;";
            
//推荐的元素样式设置 : 
 box.className += " active";
//删掉active;
console.log(box.className.split(" ").join(" "));
//eg:-------------------------------------------------
function removeEle(arr, val) {
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] == val) {
            arr.splice(i, 1);
            break;
        }
    }
    return arr;
}
var arr = box.className.split(" ");
box.className = removeEle(arr, "sss").join(" ");
  • 删除元素

var box = document.getElementById("box");

document.body.removeChild(box); 或者box.parentNode.removeChild(box);

要想删除box,必须要先找到它的父级节点,于是封装了一个函数

function remove( ele ){
     return ele.parentNode.removeChild(ele);
}
  • 封装功能 :

    • getAttribute()

    找到属性节点集合 , 遍历并判定属性名称 nodeName ,如果相同则返回结果;

    function getAttribute(dom, attr_name) {
        var attributes = dom.attributes;
        for (var i = 0; i < attributes.length; i++) {
            if (attributes[i].nodeName === attr_name) {
                return attributes[i].nodeValue;
            }
        }
        return null;
    }
    
    console.log(getAttribute(box, "id"));
    
    • setAttribute()

    难点 : 1. 存在属性直接赋值; 2. 不存在属性,创建属性节点,赋值;

    function setAttribute(ele_node, attr_name, attr_value) {
        var attributes = ele_node.attributes;
        if (attributes[attr_name]) {
            attributes[attr_name].nodeValue = attr_value;
        } else {
            var attr = document.createAttribute(attr_name);
            attr.nodeValue = attr_value;
            ele_node.setAttributeNode(attr);
        }
    }
    setAttribute(box, "index", "hello");
    
    • next()

    找到下一个元素节点;

    function next(ele_node) {
        var next_ele = null;
        while (true) {
            if (ele_node.nextSibling.nodeType === 1) {
                return ele_node.nextSibling;
                break;
            }
            ele_node = ele_node.nextSibling;
        }
        return next_ele;
    }
    console.log(next(box));
    
    • nextAll()

    找到后面所有的节点

    function nextAll(ele_node) {
        var next_eles = [];
        while (ele_node.nextSibling !== null) {
            if (ele_node.nextSibling.nodeType === 1) {
                next_eles.push(ele_node.nextSibling);
            }
            ele_node = ele_node.nextSibling;
        }
        return next_eles;
    }
    
    • nextUntil()

    找后面的节点,直到遇到某一个节点为止

    function nextUntil(ele_node, until) {
        var next_eles = [];
        var until_ele = document.querySelector(until);
        while (ele_node.nextSibling !== null && 
               ele_node.nextSibling !== until_ele) {
            if (ele_node.nextSibling.nodeType === 1) {
                next_eles.push(ele_node.nextSibling);
            }
            ele_node = ele_node.nextSibling;
        }
        return next_eles;
    }
    console.log(nextUntil(box, "#stop"));
    
    • prev()

    找上一个兄弟节点

    function prev(ele_node) {
    var prev_ele = null;
    while (true) {
          if (ele_node.previousSibling.nodeType === 1) {
                prev_node = ele_node.previousSibling;
                break;
          }
          ele_node = ele_node.previousSibling;
    }
    return ele_node.previousSibling;
    }
    
    console.log(prev(box));
    
    • prevAll()

    找元素上面所有的兄弟节点

    function prevAll(ele_node) {
    var prev_eles = [];
    while (ele_node.previousSibling !== null) {
          if (ele_node.previousSibling.nodeType === 1) {
                prev_eles.unshift(ele_node.previousSibling);
    
          }
          ele_node = ele_node.previousSibling;
    }
    return prev_eles;
    }
    console.log(prevAll(box));
    
    • prevUntil()

    找元素上面所有的兄弟节点,直到找到某一个兄弟节点为止

    function prevUntil(ele_node, until) {
    var prev_untils = [];
    while (ele_node.previousSibling !== null && 
           ele_node.previousSibling !== until) {
          if (ele_node.previousSibling.nodeType === 1) {
                prev_untils.unshift(ele_node.previousSibling);
          }
          ele_node = ele_node.previousSibling;
    }
    return prev_untils;
    }
    console.log(prevUntil(box, one));
    
    • parent()

    找到元素的父节点

    function parent(ele_node) {
        var parent_ele = null
        while (true) {
            if (ele_node.parentNode.nodeType === 1) {
                parent_ele = ele_node.parentNode;
                break;
            }
            ele_node = ele_node.parentNode;
        }
        return parent_ele;
    }
    console.log(parent(box));
    
    • parents()

    找寻所有的父节点,直到body

    function parents(ele_node) {
          var parent_eles = [];
          while (ele_node.parentNode !== null) {
          if (ele_node.parentNode.nodeType === 1) {
                parent_eles.unshift(ele_node.parentNode);
          }
          ele_node = ele_node.parentNode;
          }
          return parent_eles;
    }
    console.log(parents(box));
    
    • parentUntil()

    向上找寻父节点,直到找到某一父节点为止

    var test = document.getElementsByTagName("html");
    
    function parentsUntil(ele_node, until) {
    var parent_eles = [];
    while (ele_node.parentNode !== null && ele_node.parentNode !== until) {
          if (ele_node.parentNode.nodeType === 1) {
                parent_eles.unshift(ele_node.parentNode);
          }
          ele_node = ele_node.parentNode;
    }
    return parent_eles;
    }
    console.log(parentsUntil(box, test));
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341