前端学习第二天

DOM对象

DOM (document object model)文档对象模型

html css 组成了我们页面的内容,js是页面行为操作

DOM是打通js和html,css的一个工具,就是通过js来改变html和css

通过 JavaScript,您可以重构整个 HTML 文档。您可以添加、移除、改变或重排页面上的项目。

要改变页面的某个东西,JavaScript 就需要对 HTML 文档中所有元素进行访问的入口。这个入口,连同对 HTML 元素进行添加、移动、改变或移除的方法和属性,都是通过文档对象模型来获得的(DOM)。

在 1998 年,W3C 发布了第一级的 DOM 规范。这个规范允许访问和操作 HTML 页面中的每一个单独的元素。

所有的浏览器都执行了这个标准,因此,DOM 的兼容性问题也几乎难觅踪影了。

DOM 可被 JavaScript 用来读取、改变 HTML、XHTML 以及 XML 文档。


DOM节点

根据 DOM,HTML 文档中的每个成分都是一个节点。

DOM 是这样规定的:

整个文档是一个文档节点
每个 HTML 标签是一个元素节点
包含在 HTML 元素中的文本是文本节点
每一个 HTML 属性是一个属性节点
注释属于注释节点

所以一共四种节点。


通过 DOM,您可访问 HTML 文档中的每个节点。

查找并访问节点,你可通过若干种方法来查找您希望操作的元素:

通过使用 getElementById() 和 getElementsByTagName() 方法

通过使用一个元素节点的 parentNode、firstChild 以及 lastChild 属性

getElementById() 和 getElementsByTagName()
getElementById() 和 getElementsByTagName() 这两种方法,可查找整个 HTML 文档中的任何 HTML 元素。

这两种方法会忽略文档的结构。假如您希望查找文档中所有的 p 元素,getElementsByTagName() 会把它们全部找到,不管 p 元素处于文档中的哪个层次。同时,getElementById() 方法也会返回正确的元素,不论它被隐藏在文档结构中的什么位置。

这两种方法会像您提供任何你所需要的 HTML 元素,不论它们在文档中所处的位置!

getElementById() 可通过指定的 ID 来返回元素:

getElementById() 语法
document.getElementById(“ID”);

getElementsByTagName() 可被用于任何的 HTML 元素:

getElementsByTagName() 语法
document.getElementsByTagName(“标签名称”);
或者:

document.getElementById(‘ID’).getElementsByTagName(“标签名称”);

节点列表(nodeList)
当我们使用节点列表时,通常要把此列表保存在一个变量中,就像这样:

var x=document.getElementsByTagName(“p”);
现在,变量 x 包含着页面中所有p元素的一个列表,并且我们可以通过它们的索引号来访问这些p元素,索引号从 0 开始。

getElementByClassName()

获取node节点下,所有符合条件的元素节点。
参数为:class
返回值: 返回所有符合条件的节点组成的一个数组
可以通过node.length 获取数组长
通过下标的方式获取某个节点 如 node[2]获取第三个节点

在ie浏览器中不支持用class获取,所以我们可以自己封装一个方法,达到兼容的效果

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        function elementByClassName(parent , classStr ) {
            // 第一步找到parent下的所有元素节点,所以用通配符 '*'
            var nodes = parent.getElementsByTagName("*");
            var result = [];
            alert(nodes.length)
            for(var i = 0;i<nodes.length;i++){
                if(nodes[i].className == classStr)
                result.push(nodes[i]);
            }
            return result;
        }

        window.onload = function(){
            var ul1 = document.getElementById("ul1")
            var result =  elementByClassName(ul1,"li1")
            for(var i =0; i<result.length; i++)
                console.log(result[i]);
        }
    </script>
</head>

<body>
    <div>
        <ul id="ul1">
            <li class="li1">11111</li>
            <li class="li1">22222</li>
            <li class="li1">33333</li>
            <li class="li1">44444</li>
            <li class="li1">55555</li>
            <li class="li1">66666</li>
        </ul>
    </div>
</body>

</html>

parentNode、firstChild以及lastChild
这三个属性 parentNode、firstChild 以及 lastChild 可遵循文档的结构,在文档中进行“短距离的旅行”。

请看下面这个 HTML 片段:

JohnDoeAlaska
在上面的HTML代码中,第一个 td 是tr元素的首个子元素(firstChild),而最后一个 td 是 tr 元素的最后一个子元素(lastChild)。

此外,tr 是每个 td元 素的父节点(parentNode)。

对 firstChild 最普遍的用法是访问某个元素的文本:

var x=[a paragraph];
var text=x.firstChild.nodeValue; 

parentNode 属性常被用来改变文档的结构。假设您希望从文档中删除带有 id 为 “maindiv” 的节点:

var x=document.getElementById("maindiv");
x.parentNode.removeChild(x); 

首先,您需要找到带有指定 id 的节点,然后移至其父节点并执行 removeChild() 方法。


根节点

有两种特殊的文档属性可用来访问根节点:

document.documentElement
document.body
第一个属性可返回存在于 XML 以及 HTML 文档中的文档根节点。

第二个属性是对 HTML 页面的特殊扩展,提供了对 标签的直接访问。


元素节点的属性:

  • tagName:获取元素节点的标签名
  • innerHTML:获取节点标签间的内容
  • innerText:获取节点标签间的内容
  • innerHTML设置或获取标签所包含的HTML+文本信息(从标签起始位置到终止位置全部内容,包括HTML标签,但不包括自身)
  • innerText设置或获取标签所包含的文本信息(从标签起始位置到终止位置的内容,去除HTML标签,但不包括自身)

HTML属性:
id,title,style,className
访问这些属性: 通过 元素节点.属性名 或者 元素节点[属性名]
元素节点.style是一个style对象,所以要修改style中某个属性可以通过 元素节点.style.属性 来访问或修改

在style样式中,有一些样式是通过 — 链接的,这时候要把 — 去掉,然后将后续单词的首字母大写
如 TestDiv.style.backgroundColor 访问背景色


获取元素属性时遇到的浏览器兼容的问题:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{
            width: 300px;
            height: 300px;
            background-color: red;

        }
    </style>
    <script>
        window.onload = function(){
            var div1 = document.getElementById("div1");
            /*
            如果我们直接 div1.style.backgroundColor 是无法找到backgroundcolor的,这种操作只能获取行内定义的样式,不能获取到style标签内定义的
            
            这时候可以通过 getComputedStyle(元素节点)[获取样式类型] 的方法获取当前有效样式
            但是这个方法在ie浏览器中不支持,在ie浏览器中获取当前有效样式的方法是: 元素节点.currentStyle[获取样式类型]; 
             */

            // alert(div1.style.backgroundColor);  // 显示为空,因为找不到在外部style中定义的
            // alert(getComputedStyle(div1).backgroundColor);      //可以找到
            // alert(div1.currentStyle);        //ie中的方法

            // 调用封装函数 
            alert(getStyle(div1,"backgroundColor"))

            //这时候可以封装一个兼容的函数
            function getStyle(elem,attr){
                return elem.currentStyle ? elem.currentStyle[attr] : getComputedStyle(elem)[attr];
            }
        }
    </script>
</head>
<body>
    <div id="div1">  </div>
</body>
</html>

通过封装函数对几种获得节点的方法合成:

id -> document.getElementById(id)
tagName -> document.getElementsByTagName(TagName)
Name -> document.getElementsByName(Name)
className -> document.getElementsByClassName(ClassName)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        /*
        封装一个函数,简化几个获取元素节点的方法
        #id    通过id获取元素节点
        .class      通过ClassName获取节点
        tagName       通过tagName获取节点
        name = xxx      通过name获取节点
        */
       function $(vArg){
        // 第一步: 对参数进行区分
       switch(vArg[0]){
           case "#":
               return   document.getElementById(vArg.substring[1]);
               break;
            case ".":
                return elementByClassName(document,vArg.substring(1));
                break;
            default:
                // 对参数前五个字符进行判断
                var str = vArg.substring(0,5)
                if(str == "name="){
                    return document.getElementsByName(vArg.substring(5));
                }else{
                    return document.getElementsByTagName(vArg);
                }
       } 

       }
       function elementByClassName(parent , classStr ) {
            // 第一步找到parent下的所有元素节点,所以用通配符 '*'
            var nodes = parent.getElementsByTagName("*");
            var result = [];
            alert(nodes.length)
            for(var i = 0;i<nodes.length;i++){
                if(nodes[i].className == classStr)
                result.push(nodes[i]);
            }
            return result;
        }

        window.onload = function(){
            var dddd = $("name=dddd")
            alert(dddd)
            var tag = $("div")
            alert(tag)
        }
    </script>
</head>
<body>
    <div name = "dddd"></div>
    <div > </div>
</body>
</html>

getAttribute() 和 setAttribute() 方法方法
getAttribute(attributename) 方法通过名称获取属性的值。提示:如果你想返回属性请使用 getAttributeNode (attributename)方法。

elementNode.getAttribute(attributename)只有一个参数,就是想获取的属性值。
setAttribute(name,value)方法用于修改一个属性的值
elementNode.setAttribute(name,value):增加一个指定名称和值的新属性,或者把一个现有的属性设定为指定的值。name:要设置的属性名。value:要设置的属性值。

当然我们也可以直接通过 elementNode.元素属性名 的方法直接获取元素属性,但这种方式只能获取节点本来具有的属性,而getAttribute()可以获取自己定义的属性。而Attribute的家族还有setAttribute()和removeAttribute(),没错正如你想的英语单词的意思一样set (设置),remove(移除),这两个方法用来设置和移除节点原型中不存在的属性;

代码1:

<div id="case" create="hello"></div>
<div></div>
<script type="text/javascript">
	var t = document.getElementById("case");
	console.log(t.create);		// 用直接获取的方法去获取自定义属性是无法获取的,所以是undefine
</script>

代码2:

<div id="case" create="hello"></div>
<div></div>
<script type="text/javascript">
	var t = document.getElementById("case");
	console.log(t.getAttribute("create"));	//getAttribute可以获取自定义属性,所以是hello
</script>

childNodes 属性

获得 body 元素的子节点集合:document.body.childNodes;

childNodes 属性返回节点的子节点集合,以 NodeList 对象。可以使用 length 属性来确定子节点的数量,然后就能够遍历所有的子节点并提取您需要的信息。

childNodes 属性,标准的,它返回指定元素的子元素集合,包括HTML节点,所有属性,文本。可以通过nodeType来判断是哪种类型的节点,只有当nodeType==1时才是元素节点,2是属性节点,3是文本节点。

节点有三种非常有用的属性,nodeName,nodeValue,nodeType。


删除空白节点的代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        window.onload = function(){
            var div1 = document.getElementById("div1");
            // 这时候我们直接输出div1.childNodes.length,结果是5,因为回车,空格,换行,tab键 都属于一个节点
            console.log(div1.childNodes.length)

            // 这时候我们想办法去除掉空白节点。所以我们必须识别出空白节点
            
            var result = removeSpaceNode(div1.childNodes);
            console.log(result.length)
            for(var i=0; i< result.length; i++)
                console.log(result[i]);

            
            // 或者使用这个函数,直接在原来的节点基础上删除
            function removeSpaceNode2( parent ){    
                var nodes = parent.childNodes;
                // 在删除的时候,必须要倒删,
                for(var i=nodes.length-1; i>=0; i--){       
                    if(nodes[i].nodeType == 3 && /^\s+$/.test(nodes[i].nodeValue)){
                        parent.removeChild(nodes[i]);
                    }
                }
            }
            

            // /^\s+$/.test();  可以使用这个正则表达式来判断是否是空白节点
            // 创建一个函数用来删除空白节点
            function removeSpaceNode( nodes ){
                var result = [];   // 用于存放不是空白节点的节点
                for(var i=0; i<nodes.length; i++){
                    // 判断一下是不是空白节点
                    if(nodes[i].nodeType == 3 && /^\s+$/.test(nodes[i].nodeValue)){
                        continue;   // 空白节点什么都不做
                    }else{
                        result.push(nodes[i]);
                    }
                }
                return result;
            }
        }
    </script>
</head>
<body>
    <div id="div1">
        <em>斜体</em>
        文本内容
        <strong>粗体</strong>
    </div>
</body>
</html>

访问节点

通过节点之间的树形关系,可以定位文档中的每个节点。DOM为Node类型定义如下属性,以方便JavaScript对文档树中每个节点进行遍历。

  • ownerDocument:返回当前节点的根元素(document对象)
  • parentNode:返回当前节点的父节点。所有的节点都仅有一个父节点
  • childNodes:返回当前节点的所有子节点的节点列表
  • firstChild:返回当前节点的首个子节点
  • lastChild:返回当前系欸但的最后一个子节点
  • nextSibling:返回当前节点之后相邻的同级节点
  • previousSibling:返回当前节点之前相邻的同级节点

write() 方法

write() 方法可向文档写入 HTML 表达式或 JavaScript 代码。可列出多个参数(exp1,exp2,exp3,…) ,它们将按顺序被追加到文档中。

语法:document.write(exp1,exp2,exp3,…)

一些说明:说明虽然根据 DOM 标准,该方法只接受单个字符串作为参数。不过根据经验,write() 可接受任何多个参数。还有我们通常按照两种的方式使用 write() 方法:一是在使用该方在文档中输出 HTML,另一种是在调用该方法的的窗口之外的窗口、框架中产生新文档。在第二种情况中,请务必使用 close() 方法来关闭文档。

【注】:在添加内容时,会将原有的页面上的内容覆盖掉

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #div1{
            width: 300px;
            height: 300px;
            background-color: red;
        }
    </style>
    <script>
        window.onload = function(){
            var btn = document.getElementById("btn");
            btn.onclick = function(){
                document.write("<h1>我是标题内容</h1>")
            }
        }
    </script>
</head>
<body>
    <div id="div1"></div>
    <button id="btn"> 按钮 </button>
</body>
</html>

创建节点

createElement()和createTextNode()

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
    </style>
    <script>
        /*
        createElement()
        [格式] document.creatElement(标签名);

        createTextNode(文本内容),创建一个文本节点

        注意创建完标签,使用appendChild把标签插入到相对应的地方
        */
        window.onload = function(){
            var btn = document.getElementById("btn");
            var div = document.getElementById("div1");
            btn.onclick = function(){
                // 创建一个span标签
                var node = document.createElement("span");
                
                // 给span标签赋值
                node.innerText = "这是新建的span标签"

                // 把新创建的标签插入到相对应的节点中
                div.appendChild(node)

                // 当然上面三个步骤太麻烦,我们可以直接封装一个函数来实现创建带文本的节点

                var newnode = createElementWidthTxt("p","我是用封装函数新创建的p")
                div.appendChild(newnode);
            }
        }
        function createElementWidthTxt( tagName, txt){
            var node = document.createElement(tagName);
            var nodeTxt = document.createTextNode(txt);
            node.appendChild(nodeTxt);
            return node;
        }
    </script>
</head>
<body>
    <div id="div1">

    </div>
    <button id="btn"> 按钮 </button>
</body>
</html>

插入节点

insertBefore() 方法在您指定的已有子节点之前插入新的子节点。

提示:如果您希望创建包含文本的新列表项,请记得创建文本节点形式的文本,以便追加到 LI 元素中,然后向列表插入这个 LI。

您也可以使用 insertBefore 方法插入/移动已有元素。

参数:

newnode Node对象。必需。需要插入的节点对象。

existingnode Node object 可选。在其之前插入新节点的子节点。如果未规定,则 insertBefore 方法会在结尾插入 newnode。

但是js没有提供insertAfter方法,所以我们要自己封装一个

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>

        window.onload = function(){
            var node = document.createElement("strong");
            var oldSpan = document.getElementById("oldSpan");
            node.innerHTML = "我是新创建的节点";
            insertAfter(node,oldSpan);
        }

        // 封装一个函数,用于在某个节点之后插入
        function insertAfter(newNode , oldNode){
            // 先判断oldNode是否是最后一个节点,如果是最后一个节点我们直接在最后插入,如果不是最后一个节点我们就要先找到这个oldNode的后一个,在这个后一个节点前插入
            var parent = oldNode.parentNode; // 找到父节点
            if( oldNode == parent.lastNode ){   // 如果是最后一个节点,直接插入最后就行
                parent.appenchild(newNode);
            }else{          
                parent.insertBefore(newNode , oldNode.nextSibling);     // 不是最后一个节点,就在oldNode的后一个节点前插入
            }
        }
    </script>
</head>
<body> 
    <div id="div1">
        <p>p</p>
        <span id="oldSpan">span</span>
        <em>em</em>
    </div>
</body>
</html>

replacechild() 和cloneNode()和removechild()方法

将某个子节点替换为另一个:document.getElementById(“myList”).replaceChild(newnode,oldnode);

replaceChild() 方法可将某个子节点替换为另一个。新节点可以是文本中已存在的,或者是你新创建的

cloneNode() 方法可创建指定的节点的精确拷贝。cloneNode() 方法 拷贝所有属性和值。该方法将复制并返回调用它的节点的副本。如果传递给它的参数是 true,它还将递归复制当前节点的所有子孙节点。否则,它只复制当前节点。

removechild()从子节点列表中删除某个节点;removeChild() 方法可从子节点列表中删除某个节点。如删除成功,此方法可返回被删除的节点,如失败,则返回 NULL。

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        /*
        replaceChild() 节点替换
        cloneNode() 克隆节点
        removeChild() 删除节点
        */

        window.onload = function(){
            var div = document.getElementById("div1");  
            var node = document.createElement("strong");
            var pNode = document.getElementById("p1");


            div.parentNode.replaceChild(node,div);  // 先找到div的父节点,然后利用父节点调用替换节点还书
            
            var cloneNewNode = div.cloneNode();     // 先复制一个节点,然后放入
            node.parentNode.appendChild(cloneNewNode);

            pNode.parentNode.removeChild(pNode)     // 先找到被删除节点的父节点,然后利用该父节点删除这个节点
        }
    </script>
</head>
<body>
    <span> span </span>
    <div id="div1"></div>
    <p id="p1">p</p>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值