js - dom1

1.DOM 树 : 

文档:一个页面就是一个文档,DOM 中使用 document 表示

元素:页面中的所有标签都是元素,DOM 中使用 element 表示

节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示

2. 获取元素

操作元素的前提是 获取元素

 /* 1 获取元素 */
  // 1.2 使用 getElementsById() 方法可以返回带有指定id的元素对象
  let box = document.getElementById('BOX')
  // console.dir() 是一种在控制台中查看指定 JavaScript 对象的所有属性的方法
  // console.dir(box)

  // 1.2 使用 getElementsByTagName() 方法可以返回指定标签名的对象的集合(伪数组。
  let box2 = document.getElementsByTagName('div')
  console.log(box)
      // 1.2.1 还可以链式调用,获取某个父元素内所有指定标签名的子元素
      console.log(box.getElementsByTagName('div'))
  // 1.3 通过 HTML5 新增的方法获取
      // 1.3.1 document.getElementsByClassName(‘类名’) 根据'类名'返回元素对象集合
      console.log(document.getElementsByClassName('boxSon'), 'getElementsByClassName')
      // 1.3.2 document.querySelector('选择器') 根据选择器匹配'第一次'出现的元素
      console.log(document.querySelector('.boxSon'))
      // 1.3.3 document.querySelector('选择器') 根据选择器匹配出现的元素返回元素'对象集合'
      console.log(document.querySelectorAll('.boxSon'))
      // querySelector 和 querySelectorAll里面的选择器需要加'选择器符号'


  // 1.4 获取body元素
  console.log(document.body, 'body')
  // 1.5 获取html中所有元素
  console.log(document.documentElement, 'html')

3.事件基础

摁遥控器键 电视开机 就是一个事件

3.1 事件三部曲

  1. 事件源:谁 => 遥控器
  2. 事件类型:什么类型的动作 => 摁
  3. 事件处理函数::引发的事 => 电视开机了

3.2 事件绑定

注册事件同上:找事件源绑定想要的事件类型 赋值 处理函数

3.3 常见事件

4. 修改元素

DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内
容 、属性等。以下都是针对元素属性

4.1 修改内容

//改变元素内容

// innerText/innerHTML都可以修改元素内容和查看元素内容
// 1.1 innerText 
    // 修改时,内容如果含有标签则标签按字符串解析,不会被解析成标签元素
   //  查看元素内容,会删除空格回车以及标签元素

// 1.2 innerHTML 
    // 修改时,内容如果含有标签则标签按字符串解析,'会被解析成标签元素'
    // 查看元素内容,保留空格回车以及标签

        两种方式获取元素内容的区别

两种方式设置内容的区别

 

4.2 常用元素的属性操作

1. innerText、innerHTML 改变元素内容
2. src、href
3. id、alt、title

4.3 表单元素的属性操作

type / value / disabled/ checked / selected

// 切换密码框
<body>
  密码框:<input type="password" value="" id="psdInput">
  <button id="lookPsdBtn">看看密码</button>
</body>
<script>
  let psdInput = document.querySelector("#psdInput")
  let lookPsdBtn = document.querySelector("#lookPsdBtn")
  let ok = true
  // 通过ok判断输入框的'type'以及按钮的innerText
  // 按钮的值和输入框的类型相反,当输入框类型切换为密码时按钮提示看看密码
  lookPsdBtn.onclick = () => {
    ok = !ok
    if (ok) {
      lookPsdBtn.innerHTML = '看看密码'
      psdInput.type = 'password'
    } else {
      lookPsdBtn.innerHTML = '不看密码了'
      psdInput.type = ''
    }
  }
</script>
// 全选/反选 
<style>
    * {
      padding: 0;
      margin: 0;
    }

    .wrap {
      width: 300px;
      margin: 100px auto 0;
    }

    table {
      border-collapse: collapse;
      border-spacing: 0;
      border: 1px solid #c0c0c0;
      width: 300px;
    }

    th,
    td {
      border: 1px solid #d0d0d0;
      color: #404060;
      padding: 10px;
    }

    th {
      background-color: #09c;
      font: bold 16px "微软雅黑";
      color: #fff;
    }

    td {
      font: 14px "微软雅黑";
    }

    tbody tr {
      background-color: #f0f0f0;
    }

    tbody tr:hover {
      cursor: pointer;
      background-color: #fafafa;
    }
  </style>

</head>

<body>
  <div class="wrap">
    <table>
      <thead>
        <tr>
          <th>
            <!-- 全选按钮 -->
            <input type="checkbox" id="j_cbAll" value="" />
          </th>
          <th>商品</th>
          <th>价钱</th>
        </tr>
      </thead>
      <tbody id="j_tb">
        <tr>
          <td>
            <input type="checkbox" />
          </td>
          <td>iPhone8</td>
          <td>8000</td>
        </tr>
        <tr>
          <td>
            <input type="checkbox" />
          </td>
          <td>iPad Pro</td>
          <td>5000</td>
        </tr>
        <tr>
          <td>
            <input type="checkbox" />
          </td>
          <td>iPad Air</td>
          <td>2000</td>
        </tr>
        <tr>
          <td>
            <input type="checkbox" />
          </td>
          <td>Apple Watch</td>
          <td>2000</td>
        </tr>

      </tbody>
    </table>
  </div>
  <script>
    let j_cbAll = document.querySelector("#j_cbAll")
    let checks = document.querySelectorAll("#j_tb input")

    // 主按钮控制其他按钮
    j_cbAll.onclick = function () {
      let isChecked = this.checked
      for (let i = 0; i < checks.length; i++) {
        checks[i].checked = isChecked
      }
    }
    // 其他按钮全选后,主按钮激活;其他按钮只要有一个没选上,主按钮失活;
    for (let i = 0; i < checks.length; i++) {
      checks[i].onclick = function () {
        // flag控制主按钮激活
        let flag = true
        // 遍历每个按钮的checked,如果当前按钮checked为false,flag失效且退出遍历
        for (let i = 0; i < checks.length; i++) {
          if (!checks[i].checked) {
            flag = false
            break // 退出for循环 这样可以提高执行效率 因为只要有一个没有选中,剩下的就无需循环判断了
          }
        }
        // 提交主按钮状态
        j_cbAll.checked = flag
      }
    }
  </script>

4.4 样式属性操作

1.element.style

        修改元素行内样式(权重高

        样式属性驼峰命名法 比如 fontSize、 backgroundColor

2.element.className

        修改元素样式类,当修改样式多时采用

<style>
    .box {
      width: 250px;
      height: 250px;
      background-color: pink;
    }

    .uNameInput {
      margin-top: 10px;
    }

    .uNameCheckSuccees {
      color: greenyellow;
    }

    .uNameCheckErro {
      color: rgb(241, 51, 21);
    }

    .paitBoxLi {
      list-style: none;
      background-color: palegoldenrod;
      width: 60px;
      text-align: center;
      margin-top: 1px;
    }

    .AtivePaitBoxLi {
      list-style: none;
      background-color: rgb(220, 96, 79);
      width: 60px;
      text-align: center;
      margin-top: 1px;
    }
  </style>
<body>
  <div class="box"></div>
  <input type="text" class="uNameInput">
  <span class="uNameCheck"></span>
  <div class="paitBox">
    <p>排他思想</p>
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
    </ul>
  </div>
</body>
<script>
  // 1 点击更改盒子大小
    // 通过元素style属性修改其行内样式
  let box = document.querySelector('.box')
  box.onclick = function () {
    this.style.width = '150px'
    this.style.height = '150px'
  }
  // 2 用户如果离开密码框,里面输入个数不是6~16,则提示错误信息,否则提示输入正确信息
    // 为输入框添加失焦事件,视角时判断其value是否符合要求触发相应提示
  let uNameInput = document.querySelector('.uNameInput')
  let uNameCheck = document.querySelector('.uNameCheck')
  uNameInput.onblur = function () {

    if (this.value.length >= 6 && this.value.length <= 16) {
      uNameCheck.innerHTML = '符合命名规则'
      uNameCheck.className = 'uNameCheckSuccees'
    }
    else {
      uNameCheck.innerHTML = '不符合命名规则,请重新填写'
      uNameCheck.className = 'uNameCheckErro'
    }
  }
  // 3. 排他思想 = > 点击哪个li其设置红色高亮显示,其他li为原始色
  // 遍历li集合集体注册点击事件,点击时让所有li class清空,让自身Class为激活状态
  let paitLiList = document.querySelectorAll('.paitBox li')
  console.log(paitLiList)
  for (let i = 0; i < paitLiList.length; i++) {
    paitLiList[i].onclick = function () {
      for (let i = 0; i < paitLiList.length; i++) {
        paitLiList[i].className = 'paitBoxLi'
      }
      this.className = 'AtivePaitBoxLi'
    }
  }

</script>
// 开关灯
<body>
  密码框:<input type="password" value="" id="psdInput">
  <button id="lookPsdBtn">看看密码</button>
</body>
<script>
  let psdInput = document.querySelector("#psdInput")
  let lookPsdBtn = document.querySelector("#lookPsdBtn")
  let ok = true
  // 通过ok判断输入框的'type'以及按钮的innerText
  // 开关灯思想:开灯后,按钮要提示关灯反之亦然。
  // 按钮的值和输入框的类型相反,当输入框类型切换为密码时按钮提示看看密码
  lookPsdBtn.onclick = () => {
    ok = !ok
    if (ok) {
      lookPsdBtn.innerHTML = '看看密码'
      psdInput.type = 'password'
    } else {
      lookPsdBtn.innerHTML = '不看密码了'
      psdInput.type = ''
    }
  }
</script>
// 导航栏切换页面 
 <style>
    * {
      margin: 0;
      padding: 0;
    }

    li {
      list-style-type: none;
    }

    .tab {
      width: 978px;
      margin: 100px auto;
    }

    .tab_list {
      height: 39px;
      border: 1px solid #ccc;
      background-color: #f1f1f1;
    }

    .tab_list li {
      float: left;
      height: 39px;
      line-height: 39px;
      padding: 0 20px;
      text-align: center;
      cursor: pointer;
    }

    .tab_list .current {
      background-color: #c81623;
      color: #fff;
    }

    .item_info {
      padding: 20px 0 0 20px;
    }

    .item {
      display: none;
    }
  </style>
</head>

<body>
  <div class="tab">
    <div class="tab_list">
      <ul>
        <li class="current">商品介绍</li>
        <li>规格与包装</li>
        <li>售后保障</li>
        <li>商品评价(50000)</li>
        <li>手机社区</li>
      </ul>
    </div>
    <div class="tab_con">
      <div class="item" style="display: block;">
        商品介绍模块内容
      </div>
      <div class="item">
        规格与包装模块内容
      </div>
      <div class="item">
        售后保障模块内容
      </div>
      <div class="item">
        商品评价(50000)模块内容
      </div>
      <div class="item">
        手机社区模块内容
      </div>

    </div>
  </div>
  <script>
    // 菜单项和展示域数量一致
    // 通过排他思想设置当前激活的菜单项和显示的菜单区域
    // 菜单区域如何匹配相应菜单项? 每次点击为其菜单项添加'index'属性,这样即可对应匹配相应的展示域
    var tab_list = document.querySelector('.tab_list')
    var lis = tab_list.querySelectorAll('li')
    var items = document.querySelectorAll('.item')

    for (let i = 0; i < lis.length; i++) {
      lis[i].onclick = function () {
        // 菜单项设置匹配展示域的索引
        this.setAttribute("index", i)
        for (let i = 0; i < lis.length; i++) {
          // 排他
          lis[i].className = ''
          items[i].style.display = 'none'
        }
        // 激活自己
        this.className = 'current'
        items[this.getAttribute('index')].style.display = 'block'
      }
    }
  </script>

节点操作

网页所有内容都是节点(标签 内容 属性 注释

HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。

节点属性

  • nodeType  :1  表示元素节点
  • nodeType  :2  表示属性节点
  • nodeType : 3  节点包含文字、空格、换行等

通过节点关系获取节点

<body>
  <div class="father">
    <p>我是爸爸</p>
    <div class="son">
      <p>我是哥哥</p>
    </div>
    <div class="son">
      <p>我是弟弟</p>
    </div>
  </div>
</body>
<script>
  // 1. 查找父节点

  //  子节点.parentNode 返回最近的父节点;没有节点返回Null
  let son = document.querySelector('.son')
  let father = son.parentNode

  // 2.查找子节点
  //父.children
  // 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回 (这个是我们重点掌握的)。
  let children = father.children
  // console.log(children, '子节点集合')
  console.log(father.firstChild, '第一个子节点')
  // 2.1获取第一个/最后一个子元素节点
  // 这两个方法有兼容性问题,IE9 以上才支持。
  /* console.log(father.firstElementChild, '第一个元素子节点')
  console.log(father.lastElementChild, '最后一个元素子节点'); */
  // 处理兼容
  console.log(children[0])
  console.log(children[length - 1])

  // 3. 查找兄弟节点
  // 这两个方法有兼容性问题,IE9 以上才支持。
  let gege = father.children[1]
  // 3.1 获取下一个兄弟元素节点
  let didi = gege.nextElementSibling
  console.log(didi, '弟弟')
  // 3.2 获取上一个兄弟元素节点
  console.log(didi.previousElementSibling, '哥哥')

  // 3.3 寻找下一个兄弟元素节点的兼容性写法
  function nextElementSibling (el) {
    let element = el
    while (element = element.nextSibling) {
      // console.log(element, 'while')
      if (element.nodeType === 1) {
        return element
      }
    }
  }
  console.log(nextElementSibling(gege));
  // ***********************************************


</script>

创建节点

<body>
  <ul>
    <li>01:日本投放和污水</li>
  </ul>
</body>
<script>
  let ul = document.querySelector('ul')
  let ulChildren = ul.children
  console.log(ulChildren[0])
  // ul第一个子元素li
  let fli = ul.firstElementChild
  // 1.创建元素节点 document.createElement('标签名')
  let newLi = document.createElement('li')
  // 2.节点插入内容
  newLi.innerHTML = '日本地震了'
  /*
    3.插入节点 
      3.1 appendChild(插入元素)
      3.1 insertBefore(插入元素, 向谁前插入的节点 )
  */

  ul.appendChild(newLi, '向后插入')
  ul.insertBefore(newLi, ulChildren[0])
</script>

克隆节点

<body>
  <ul>
    <li>
      点我删除我
    </li>
  </ul>
</body>
<script>
  let ul = document.getElementsByTagName('ul')[0]
  let li = ul.children[0]
  li.onclick = function () {
    // 被克隆元素.cloneNode(true):true为深度克隆可以复制克隆源对象的子节点,false为浅克隆只复制科隆源本身
    let newLi = li.cloneNode(true)
    ul.appendChild(newLi)
  }
</script>

删除节点

<body>
  <ul>
    <li>
      点我删除我
    </li>
  </ul>
</body>
<script>
  let ul = document.getElementsByTagName('ul')[0]
  let li = ul.children[0]
  li.onclick = function () {
    // 父节点.removeChild(要删除的节点)
    ul.removeChild(li)
  }
</script>

 节点增删练习 ——评论框

 <style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      padding: 100px;
    }

    textarea {
      width: 200px;
      height: 100px;
      border: 1px solid pink;
      outline: none;
      resize: none;
    }

    ul {
      margin-top: 50px;
    }

    li {
      width: 300px;
      padding: 5px;
      background-color: rgb(245, 209, 243);
      color: red;
      font-size: 14px;
      margin: 15px 0;
    }

    li a {
      float: right;
    }
  </style>
</head>

<body>
  <textarea name="" id=""></textarea>
  <button>发布</button>
  <ul>

  </ul>
  <script>
    var btn = document.querySelector('button')
    var text = document.querySelector('textarea')
    var ul = document.querySelector('ul')

    btn.onclick = function () {
      let textValue = text.value
      if (!textValue) {
        alert('请输入内容')
        return
      }
      let li = document.createElement('li')
      li.innerHTML = textValue + '<button onclick = deleteThis(event)>删除</button>'
      // ul.appendChild(li)
      ul.insertBefore(li, ul.children[0])

    }

    function deleteThis (event) {
      // console.log(event.target)
      let thisFather = event.target.parentNode.parentNode.removeChild(event.target.parentNode)
    }
  </script>
  <!--  <script>
    // 1. 获取元素
    var btn = document.querySelector('button')
    var text = document.querySelector('textarea')
    var ul = document.querySelector('ul')
    // 2. 注册事件
    btn.onclick = function () {
      if (text.value == '') {
        alert('您没有输入内容')
        return false
      } else {
        // console.log(text.value);
        // (1) 创建元素
        var li = document.createElement('li')
        // 先有li 才能赋值
        li.innerHTML = text.value + "<a href='javascript:;'>删除</a>"
        // (2) 添加元素
        // ul.appendChild(li);
        ul.insertBefore(li, ul.children[0])
        // (3) 删除元素 删除的是当前链接的li  它的父亲
        var as = document.querySelectorAll('a')
        for (var i = 0; i < as.length; i++) {
          as[i].onclick = function () {
            // node.removeChild(child); 删除的是 li 当前a所在的li  this.parentNode;
            ul.removeChild(this.parentNode)
          }
        }
      }
    }
  </script> -->
</body>

动态渲染表格练习 

<style>
    table {
      width: 500px;
      margin: 100px auto;
      border-collapse: collapse;
      text-align: center;
    }

    td,
    th {
      border: 1px solid #333;
    }

    thead tr {
      height: 40px;
      background-color: #ccc;
    }
  </style>
</head>

<body>
  <table cellspacing="0">
    <thead>
      <tr>
        <th>姓名</th>
        <th>科目</th>
        <th>成绩</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody>

    </tbody>
  </table>

  <script>
    let table = document.querySelector('table')
    // 1.先去准备好学生的数据
    var datas = [{
      name: '魏璎珞',
      subject: 'JavaScript',
      score: 100
    }, {
      name: '弘历',
      subject: 'JavaScript',
      score: 98
    }, {
      name: '傅恒',
      subject: 'JavaScript',
      score: 99
    }, {
      name: '明玉',
      subject: 'JavaScript',
      score: 88
    }, {
      name: '大猪蹄子',
      subject: 'JavaScript',
      score: 0
    }]
    for (let i in datas) {
      // 1.生成行
      let tr = document.createElement('tr')
      for (let v in datas[i]) {
        // 2.生成列,循环取出每一列的值后加入到行中
        let td = document.createElement('td')
        td.innerHTML = datas[i][v]
        tr.appendChild(td)
      }
      // 2.2添加最后一列操作按钮
      let lastTd = document.createElement('td')
      lastTd.innerHTML = '<button onclick = deleteThis(event)> 删除 </button>'
      // 3.把处理完的行放到表格
      tr.appendChild(lastTd)
      table.appendChild(tr)
    }
    // 删除当前行
    function deleteThis (event) {
      event.target.parentNode.parentNode.parentNode.removeChild(event.target.parentNode.parentNode)
    }
  </script>


</body>

对比三种添加节点方法

 document.write()
 element.innerHTML
 document.createElement()
区别
1. document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
2. innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
3. innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
4. createElement() 创建多个元素效率稍低一点点,但是结构更清晰
总结:不同浏览器下,innerHTML 效率要比 creatElement 高

属性操作

自定义属性 

//为区分是否为元素内置属性,h5提供设置以data-开头的属性
        // 1.
        // this.dataset.index = i
        // 2.
        this.dataset['index'] = i
        // 获取自定义属性需添加data-
        this.getAttribute('data-index')

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值