js---dom相关操作

253 阅读5分钟
  • 元素节点增删查
  • 元素属性操作Api
  • 元素常见位置属性
  • 元素身上的事件

元素节点增删查

获取节点自身
1.document.getElementById("test")
根据元素id返回元素,如果不存在该元素,则返回null
2.document.getElementsByTagName("div") , 返回数组
返回指定 标签名 的节点数组, 没有找到返回空数组
3.document.getElementsByClassName("test"), 返回数组
返回指定 类名 的节点数组,没有找到返回空数组
4.document.querySelector()
返回匹配指定的CSS选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null
5.document.querySelectorAll(), 返回数组
返回指定 CSS选择器 的元素节点数组,没有找到返回空数组
获取关系节点
1.获取子元素
<body>
  <div class="test">
    333
    <p>test3----1</p>
    <p>test3----2</p>
    <p>test3----3</p>
  </div>
</body>
<script>
  let dos = document.getElementsByClassName("test")[0];
  // firstChild  childNodes  lastChild 会包含文本(空文本等); 
  // 而firstElementChild  children  lastElementChild 返回非纯文本的标签元素
  let firstChild = dos.firstChild; // "  333   "
  let firstElementChild = dos.firstElementChild; // <p>test3----1</p>
  let childNodes = dos.childNodes; // NodeList [text, p, text, p, text, p, text]
  let children = dos.children; // HTMLCollection [p,p,p]
  console.log(firstChild, firstElementChild, childNodes, children)

  let lastChild =  dos.lastChild
  let  lastElementChild = dos.lastElementChild
</script>
2.获取父元素
 元素.parentElement   元素.parentNode
3.获取兄弟元素
// previousElementSibling  nextElementSibling 前后兄弟标签元素
// nextSibling previousSibling 前后兄弟节点包含纯文本

增加

创建、插入节点
1.createElement
document.createElement("input"); 
2.insertBefore
// 在指定子节点前插入一个节点
parentNode.insertBefore(newNode, refNode);

3.appendChild
// 就是将指定的节点添加到调用该方法的节点的子元素的末尾
parent.appendChild(child);

删除

1.removeChild
// 移除某个指定的子节点
element.removeChild(child);

2.remove
// 移除某个节点本身以及其子节点
element.remove();

元素属性操作Api

1.修改设置属性
// setAttribute(属性名,属性值)  元素.属性 = 属性值
let pp = document.getElementById("pp");
pp.setAttribute("t1","t1")
pp.t2 = "t222"
2.读取属性
<body>
  <input id="inp">
</body>
<script>
  let input = document.getElementById("inp");

  // 自定义属性 读取应和操作是同一套,否则读取不到
  input.setAttribute("t1","t11")
  console.log(input.getAttribute("t1")) //t11
  console.log(input.t1) //undefined

  input.t2= 't2'
  console.log(input.getAttribute("t2")) //null
  console.log(input.t2)//t2

  // 固有页面显示属性 读取应和操作可以随便,建议最好同一套操作
  input.setAttribute("title","t11")
  console.log(input.getAttribute("title")) //t11
  console.log(input.title) //t11

  input.type= 'text'
  console.log(input.getAttribute("type")) //text
  console.log(input.type)//text
</script>
3.移除属性
元素.removeAttribute(属性名)

元素常见位置属性

1.布尔属性
checked ( 默认选中 , 一般用于checkbox)
selected ( 默认选中 ,一般用于option)
readOnly(O必须大写) (不能修改数据 , 但不影响数据传输 , 后端仍然可以获得该数据)
disabled (提交后后端不会获得该数据)
multiple ( 多选 , 按住ctrl和shift可以多选)可以让下拉菜单变成列表菜单
hidden ( 隐藏 );Html5新增属性

手机号:<input type="hidden">
<input type="checkbox" checked="checked">北京
<input type="checkbox" >上海
<select name="" id="">
  <option value="0" disabled>请选择</option>
  <option value="1" >北京</option>
  <option value="2" selected>上海</option>
</select>
2.字符串属性
id:表示元素的唯一标识;一个页面上不能出现相同id值的两个元素
title:可见元素在鼠标掠过时出现的提示信息
href:一般用于a和link这两个元素,表示超链接
src:用于image、script、object等等,表示数据的来源
name:一般用于表单元素,表示控件的名字
value:一般用于表单元素,是控件要传到后端的值
class:定义在元素上引用的样式类名
style :可以定义某个元素的样式 
nodeName: 节点名称,大写字符串
className:类名称
<body>
<button id="btn"  onclick="f()" class="btn active">我是parent并列的另外一个button</button>
<script type="text/javascript">
   let btn = document.getElementById("btn");
   console.log(btn.nodeName) //BUTTON
   console.log(btn.className) // "btn active"
</script>
</body>
3. data属性 (IE8及以下不兼容)
如果是多个-分隔 的,字符串,用驼峰来获取如data-xxx-yyy,则dataset.xxxYyy
对于设置私有属性,可以使用新增属性:"data-xxxx"。js中用dataset来获取此类属性的集合。 
如果data-后面是一个单词,比如:data-one,那么使用:Ele.dataset.one来获取属性值; 
如果data-后面不是一个单词,比如:data-one-two,那么使用:Ele.dataset.oneTwo(驼峰形式)来获取属性值 
<body>
<ul>
  <li data-id="1">1111</li>
  <li data-id="2">2222</li>
</ul>
</body>
<script>
 let dom = document.getElementsByTagName("li")[1];
 console.log(dom.dataset.id);
</script>
4. classList属性(IE11以下不支持。)
这个属性中有add、remove、contains、toggle等方法。
 box1.classList //返回类名数组
 box1.classList.add("box-box")  // 添加类名
 box1.classList.remove("box2") // 移除某个类名
 console.log( box1.classList.contains("box2"), box1.classList.contains("box1")) //是否含有类名
5. 位置属性
// style.width  .style.xxx 等都是获取元素的行内样式,若行内样式没有显示添加,则返回空字符串, 读写都是字符串格式。
// offsetWidth offsetHeight  盒子的最终宽度 = padding + content-width (不包含border), 返回数值整型,只可以读,不可以设置
// offsetTop offsetLeft 返回的是该盒子上边(左边)距离直接父元素的上边(左边)边界距离,注意是直接父元素。返回数值整型,只可以读,不可以设置
<style>
    * {
        padding: 0;
        margin: 0;
    }
    .box {
        background-color: pink;
        position: absolute;
        top: 30px;
        left: 50%;
        transform: translate(-50%);
        width: 300px;
        padding: 50px 20px;
        box-sizing: border-box;
        border-left: 600px solid #ccc;
    }
</style>

<body>
<div class="box">
    <div id="box-child">box3-child</div>
</div>
<p style="margin-top:1000px;">Still there?</p>
</body>
<script>
    let box = document.getElementsByClassName("box")[0];
    let boxChild = document.getElementById("box-child");
    console.log('box.style.width', box.style.width) // ""
    console.log('box.offsetWidth', box.offsetWidth) // 300  盒子的最终宽度 = padding + content-width (不包含border)
    console.log('box.offsetTop', box.offsetTop) // 30   该盒子上边距离直接父元素(body)的上边边界距离(不含border)
    console.log('box.style.top', box.style.top) // ""
    console.log('box.scrollTop', box.scrollTop) // 0
    console.log('box.offsetLeft', box.offsetLeft) // 720 该盒子左边距离直接父元素(body)的左边边界距离(不含border)
    console.log('boxChild.offsetTop', boxChild.offsetTop) // 50 该盒子上边距离直接父元素(<div class="box" >)的上边边界距离
    console.log('boxChild.offsetLeft', boxChild.offsetLeft) // 20 该盒子左边距离直接父元素(<div class="box" >)的左边边界距离
    document.onscroll = () => {
        console.log('scroll');
        console.log('document', window.scrollY, box.offsetTop) //浏览器纵向滚动条距离
    }
</script>

元素身上的事件

1. 绑定方式
// 1.行内式  on+事件类型 = " 执行函数() "
<div id="btn" onclick="clickone()"></div> 
<script>
    function clickone() {console.log("clickone",this);} // this指向window
</script>
// 2.js代码中绑定
document.getElementById("btn").onclick = function(){  console.log(this) } //this指向当前绑定dom事件对象,若是子元素触发该事件,this依然是当前btn对应的dom对象
// 3.监听方式
 document.getElementById("btn").addeventlistener("click",clickone);  //this指向当前绑定dom事件对象,若是子元素触发该事件,this依然是当前btn对应的dom对象
2.on绑定和addeventlistener绑定区别
// on绑定的事件若绑定同一类型的事件,譬如都是click事件,js代码后面的会覆盖前面的
document.getElementById("btn").onclick = function () {
        console.log("btn11", this)
    }
document.getElementById("btn").onclick = function () {
      console.log("btn22", this)
  }
  // 控制台只会输出  btn22
  
 //addEventListener可以同时绑定多个同类型事件。
document.getElementById("btn").addEventListener('click',function(){console.log(123)});
document.getElementById("btn").addEventListener('click',function(){console.log(456)});
// 控制台会输出123,456. 说明addEventListener可以同时绑定多个事件。
3.addeventlistener的第3个参数
<style>
    * {
        padding: 0;
        margin: 0;
    }

    #parent {
        background-color: pink;
    }

    #child {
        position: absolute;
        top: 50px;
        width: 100px;
        height: 30px;
        background-color: purple;
    }

    #btn {
        position: absolute;
        right: 0;
        top: 0;
    }

</style>
<body>

<div id="parent">
    <p>parent-----parent</p>
    <p id="child">child</p>
</div>
<button id="btn">我是parent并列的另外一个button</button>
<script type="text/javascript">

    let parent = document.getElementById('parent');
    let child = document.getElementById('child');
    let btn = document.getElementById('btn');
    // 父元素addEventListener第3个参数
    // 没写或者值为false,都表示若点击子元素,先触发子元素的事件,然后再触发父元素的事件。即冒泡顺序执行;
    // 值为 true, 若点击子元素,先触发父元素同类型的事件,再触发子元素的事件。即捕获顺序执行;
    parent.addEventListener('click', function () {
        console.log("parent")
    });
    // 虽然child定位出去了,但是点击子元素依然会触发父元素同类型事件
    child.addEventListener('click', function () {
        console.log("child")
        setTimeout(()=>{
            console.log('time out')
        },3000)
    })
    // 虽然页面显示btn元素在parent元素内部,但是点击btn,依然不会触发parent元素。
    btn.addEventListener('click', function () {
        console.log("btn")
    })
</script>
</body>
4.事件执行的另外一种方式 btn.事件类型()
<body>
<button id="btn"  onclick="f()">我是parent并列的另外一个button</button>
<script type="text/javascript">
    function f(){
        console.log('fff',this)  // this都指向window
    }
    let btn = document.getElementById("btn")
    btn.click() // 自执行
</script>
</body>
5.处于性能考虑,建议动态内容上绑定事件时采用事件代理模式
// 可以大量节省内存占用,减少事件注册。比如ul上代理所有li的click事件就很不错
6.node.contains(e.target) 判断一个节点是否是他的子节点以及自身,返回值为布尔值
// 场景: 点击盒子之外区域关闭某个盒子
<body>
<div id="box">
    <p>我是一个p</p>
    <button>我是一个button</button>
</div>
<script type="text/javascript">
let node = document.getElementById("box");
window.addEventListener("click", function (e) {
    if (node.contains(e.target)) {
        console.log("点击的是box盒子")
        return
    }
    console.log("点击的是box盒子之外的区域")
})
</script>
</body>