JavaSciipt之DOM(四):元素节点的创造、删除、复制等操作

操作DOM节点,节点,可以利用节点层级关系(父子)来获取元素。节点有3个属性,分别是节点类型、节点名、节点值。元素节点类型值是1;属性节点类型值是2;文本节点类型值(文字、空格、换行)类型是3;实际开发中,节点操作主要是操作元素节点。节点的层级可以看作是父子兄的关系,白龙网指出。

1、节点类型

(1)父节点 .parentNode
<body>
  <div class="box">
    <span>子节点</span>
  </div>
<script>
  var span = document.querySelector('span');
  //返回的是最近的父节点,如果没有父节点,则返回结果为空
  console.log(span.parentNode);
</script>
</body>
(2)子节点 childNodes  children
<body>
  <ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
<script>
var ul = document.querySelector('ul');
//1.childNodes,标准,返回值得是一个集合,包含元素节点、文本节点等内容,如果要使用该方法,需要判断元素的类型值1来筛选出元素
console.log(ul.childNodes);
for (i = 0; i < ul.childNodes.length; i++) {
  if (ul.childNodes[i].nodeType == 1) {
    console.log(ul.childNodes[i]);
  }
}
//2.children,非标准,返回值是元素节点,常用
console.log(ul.children);
</script>
</body>
(3)首尾元素
获取首尾元素,有3种方法,各有特点,区别对待,区别使用。
<body>
  <ul>
    <li>子元素太多了1</li>
    <li>子元素太多了1</li>
    <li>子元素太多了1</li>
    <li>子元素太多了1</li>
    <li>子元素太多了1</li>
  </ul>
<script>
var ul = document.querySelector('ul');
//1.firstChild lastChild 获取的元素节点、文本节点
console.log(ul.firstChild);
console.log(ul.lastChild);
//2.firstElementChild lastElementChild 可以获取第一个与最后一个元素,但是要求IE9以上浏览器才能支持,即,存在兼容性问题
console.log(ul.firstElementChild);
console.log(ul.lastElementChild);
//3.实际开发中,一般会用这种方法来获取第一个、最后一个子元素
console.log(ul.children[0]);
console.log(ul.children[ul.children.length -1]);
</script>
</body>
案例1:新浪下拉菜单 鼠标经过下拉出现,鼠标离开,下拉显示
<body>
  <style>
    * {
      padding: 0;
      margin: 0;
    }
    ul {
      list-style: none;
    }
    .nav > li {
      float: left;
    }
    .nav li ul {
      display: none;
    }
  </style>
  <ul class="nav">
    <li>
      <a href="#">白龙网</a>
      <ul>
        <li>前端技术</li>
        <li>后端开发</li>
        <li>SEO服务</li>
        <li>小程序</li>
      </ul>
    </li>
    <li>
      <a href="#">白龙网</a>
      <ul>
        <li>前端技术</li>
        <li>后端开发</li>
        <li>SEO服务</li>
        <li>小程序</li>
      </ul>
    </li>
    <li>
      <a href="#">白龙网</a>
      <ul>
        <li>前端技术</li>
        <li>后端开发</li>
        <li>SEO服务</li>
        <li>小程序</li>
      </ul>
    </li>
    <li>
      <a href="#">白龙网</a>
      <ul>
        <li>前端技术</li>
        <li>后端开发</li>
        <li>SEO服务</li>
        <li>小程序</li>
      </ul>
    </li>
  </ul>
<script>
  var ul = document.querySelector('.nav');
  var lis = ul.children;
  console.log(ul.children);
  for (i = 0; i < lis.length; i++) {
    lis[i].onmouseover = function() {
      this.children[1].style.display = 'block';
    }
    lis[i].onmouseout = function() {
      this.children[1].style.display = 'none';
    }
  }
</script>
</body>
(4)兄弟节点 nextSibling previousSibling nextElementSibling previousElementSibling
<body>
  <div>白龙网</div>
  <span>从建站到SEO的在线服务平台</span>
  <p>最后一个段落</p>
<script>
  var divs = document.querySelector('div');
  //1.获取上一个/下一个兄弟节点,包括元素、文本,没有则返回空;如果只想获取元素,不想出现文本,使用nodeType判断即可
  if (divs.nextSibling.nodeType === 1) {
    console.log(divs.nextSibling);
  }
  console.log(divs.previousSibling);
  //2.获取下一个、上一个元素节点,没有则返回空,存在兼容性问题
  console.log(divs.nextElementSibling);
  console.log(divs.previousElementSibling);
</script>
</body>

2、创建节点

自定义节点,需要两步才能完成,首先要创建节点,然后要添加节点。节点可以添加到后面,也可以添加到前面。
<body>
  <ul>
    <li>原有节点</li>
  </ul>
<script>
  //1.创建元素
  var li = document.createElement('li');
  var ul = document.querySelector('ul');
  //2.添加元素,因为是从后面添加的元素,所以也叫追加元素
  ul.appendChild(li);
  var div = document.createElement('div');
  //如果想要在已有子元素前面添加元素,则使用insertBefore(添加的元素,添加的元素位置)
  ul.insertBefore(div,ul.children[0]);
</script>
</body>
案例1:简单的发布留言案例
<body>
  <textarea name="" id="" cols="30" rows="10"></textarea>
  <button>发布</button>
  <ul>1</ul>
<script>
 //获取元素
  var btn = document.querySelector('button');
  var text = document.querySelector('textarea');
  var ul = document.querySelector('ul');
 //添加事件
 btn.onclick = function() {
  //创建节点
  var li = document.createElement('li');
  if (text.value == '') {
    alert('请输入内容:');
    return false;
  } else {
    //输入内容显示到新建的LI中,实际上就是把文本域的值赋值给LI
    li.innerHTML = text.value;
  }
  //添加节点
  // ul.appendChild(li);
  ul.insertBefore(li,ul.children[0]);
 }
</script>
</body>

3、删除节点

删除节点,一定是删除父元素的子节点。
<body>
  <button>删除</button>
  <ul>
    <li>白龙网</li>
    <li>drupal开发</li>
    <li>SEO优化</li>
  </ul>
<script>
 var ul = document.querySelector('ul');
 var btn = document.querySelector('button');
 btn.onclick = function() {
  if (ul.children.length == 0) {
    //子节点删除完毕,按钮显示灰色状态,即:不可再删
    btn.disabled = true;
  } else {
    //删除子节点:element.removeChild(child)
    ul.removeChild(ul.children[0]);
  }
 }
</script>
</body>
案例1:简单版在线留言内容的删除
<body>
  <textarea name="" id="" cols="30" rows="10"></textarea>
  <button>发布</button>
  <ul></ul>
<script>
 //获取元素
  var btn = document.querySelector('button');
  var text = document.querySelector('textarea');
  var ul = document.querySelector('ul');
 //添加事件
 btn.onclick = function() {
  //创建节点
  var li = document.createElement('li');
  if (text.value == '') {
    alert('请输入内容:');
    return false;
  } else {
    //输入内容显示到新建的LI中,实际上就是把文本域的值赋值给LI,需要注意的是,此处要阻止a链接进行跳转,可以使用javascript:;或者javascript:void(0);另外,引自,又给出了一种添加节点的方法,即:加号拼接一个节点出现,或者用createElement()创建一个节点也可以
    li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";
    //添加节点
    ul.insertBefore(li,ul.children[0]);
    //删除节点
    var as = document.querySelectorAll('a');
    for (i = 0 ; i < as.length; i++) {
      //删除节点的时候,是删除所有链接节点的父亲,ul的儿子,即li,因此需要对数组as[i]添加事件,使用removeChild()删除每个li即可
      as[i].onclick = function() {
        ul.removeChild(this.parentNode);
      }
    }
  }
 }
</script>
</body>

4、复制节点 .cloneNode() 

复制节点,也是克隆节点,使用方法类似于创建节点,要先复制再追加,复制才能成功。
<body>
<ul>
  <li>白龙网</li>
  <li>SEO教程</li>
  <li>drupal</li>
</ul>
<script>
 var ul = document.querySelector('ul');
 //1.复制节点,如果.cloneNode()为空,或者false,称为浅拷贝,则只复制节点,不复制标签里面的内容;如果.cloneNode()为true,则既复制节点,又复制标签里面的内容;
 var lili = ul.children[0].cloneNode();
 var lili2 = ul.children[0].cloneNode(true);
 //2.添加节点
 ul.appendChild(lili);
 ul.appendChild(lili2);
</script>
</body>
案例1:动态生成表格,并删除对应的行
用JS操作表格,添加行与单元格,并从数组中获取数据,这个案例类似于网站后台删除文章的功能。
<body>
    <table border="1" cellspacing="0">
      <thead>
        <th>姓名</th>
        <th>科目</th>
        <th>成绩</th>
        <th>操作</th>
      </thead>
      <tbody>
      </tbody>
    </table>
<script>
  //准备数据
 var datas = [
 {
  name: '周润发',
  subject: 'Javascript',
  score: '99'
 },
 {
  name: '张学友',
  subject: 'Javascript',
  score: '90'
 },
 {
  name: '刘德华',
  subject: 'Javascript',
  score: '80'
 },
 {
  name: '刘德华',
  subject: 'Javascript',
  score: '80'
 },
 {
  name: '刘德华',
  subject: 'Javascript',
  score: '80'
 }
 ];
 //2.创建行
 var tbody = document.querySelector('tbody');
 for (i = 0 ; i < datas.length; i++)  {
  var tr = document.createElement('tr');
  tbody.append(tr);
  //3.创建单元格
  for (k in datas[i]) {
    var td = document.createElement('td');
    //4.填充数据:拿到对象的数据,并赋值给单元格
    td.innerHTML = datas[i][k];
    tr.appendChild(td);
  }
  //添加删除单元格并给单元格添加数据
  var td = document.createElement('td');
  td.innerHTML = '<a href="javascript:;">删除</a>';
  tr.appendChild(td);
 }
 //5.删除操作
 var as = document.querySelectorAll('a');//获取所有a标签
 for (i = 0; i < as.length; i++) {
  as[i].onclick = function() {//每个a标签都要点击故而循环
    tbody.removeChild(this.parentNode.parentNode)//删除的是行,该行是tbody的儿子,是a标签的爸爸(td)的爸爸(tr)
  }
 }
</script>
</body>

5、创建元素的三种方法

(1)document.write()
<body>
<button>点击</button>
<p>白龙网</p>
<script>
  var btn = document.querySelector('button');
  btn.onclick = function() {
    //直接把内容写入页面的内容流,文档流执行完毕后,会导致页面全部重绘
  document.write('<div>drupal</div>');
 }
</script>
</body>
(2)innerHTML
<body>
  <div class="top"></div>
  <div class="bottom"></div>
  <script>
    var div = document.querySelector('.top');
    div.innerHTML = '<a href= "">白龙网</a>';
  </script>
</body>
 
<body>
  <div></div>
  <script>
    for (i = 0; i <= 100; i++) {
      var div = document.querySelector('div');
      //用加号连字符,把循环添加的a标签连接到一起
      div.innerHTML += '<a href= "/">白龙网</a>' + '<br />';
    }
  </script>
</body>
(3)appendChild('')
<body>
  <div></div>
  <script>
    var a = document.createElement('a');
    var div = document.querySelector('div');
    div.appendChild(a);
  </script>
</body>
for (i = 0; i <= 1000; i++) {
    var a = document.createElement('a');
    var div = document.querySelector('div');
    div.appendChild(a);
}
innerHTML与appendChild()创建单个元素他们之间没有太大的区别;但是创建多个元素时,创建效率就有明显的区别了。
使用innertHTML创建元素,不采用拼接字符串,采用数组的形式,该方法比createElement()方法快,但是结构相对复杂些,例如,把字符串放入数据,再把数组转化为字符串等操作。
使用createElement虽然时间慢了些,但是结构消清晰,获取元素,创建元素,追加元素,一步到位,结构更加清晰。