Javascript面向对象基础

DOM简介

  • DOM的概念

    • 文档对象模型(Document Object Model,简称DOM),是 W3C 组织推荐的处理可扩展标记语言(html或者xhtml)的标准编程接口。
    • W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。
  • DOM树

    • 文档:一个页面就是一个文档,DOM中使用document表示
    • 节点:网页中的所有内容,在文档树中都是节点(标签、属性、文本、注释等),使用node表示
    • 标签节点:网页中的所有标签,通常称为元素节点,又简称为“元素”,使用element表示

获取元素

  • 根据ID获取
    • 语法:document.getElementById(id)
    • 作用:根据ID获取元素对象
    • 参数:id值,区分大小写的字符串
    • 返回值:元素对象 或 null
    <body>
        <div id="time">2019-9-9</div>
        <script>
            var timer = document.getElementById('time');
            console.log(timer);
            console.log(typeof timer);
            // console.dir 打印我们返回的元素对象 更好的查看里面的属性和方法
            console.dir(timer);
        </script>
    </body>
  • 根据标签名获取元素
    • 语法:document.getElementsByTagName('标签名') 或者 element.getElementsByTagName('标签名')
    • 作用:根据标签名获取元素对象
    • 参数:标签名
    • 返回值:元素对象集合(伪数组,数组元素是元素对象)
<body>
    <ul>
        <li>知否知否,应是等你好久11</li>
        <li>知否知否,应是等你好久22</li>
        <li>知否知否,应是等你好久33</li>
        <li>知否知否,应是等你好久44</li>
        <li>知否知否,应是等你好久55</li>
    </ul>
    <ul id="nav">
        <li>生僻字</li>
        <li>生僻字</li>
        <li>生僻字</li>
        <li>生僻字</li>
        <li>生僻字</li>
    </ul>
    <script>
        // 1.返回的是 获取过来元素对象的集合 以伪数组的形式存储的
        var lis = document.getElementsByTagName('li');
        console.log(lis);
        console.log(lis[0]);
        // 2. 我们想要依次打印里面的元素对象我们可以采取遍历的方式
        for (var i = 0; i < lis.length; i++) {
            console.log(lis[i]);
        }
        // 3. element.getElementsByTagName()  可以得到这个元素里面的某些标签
        var nav = document.getElementById('nav'); // 这个获得nav 元素
        var navLis = nav.getElementsByTagName('li');
        console.log(navLis);
    </script>
</body>
  • H5新增获取元素方式
    • 根据类名返回元素对象集合:document.getElementsByClassName('类名');
    • 根据指定选择器返回第一个元素对象:document.querySelector('选择器');
    • 根据指定选择器返回:document.querySelectorAll('选择器');
    • 注意:querySelector 和 querySelectorAll里面的选择器需要加符号('#nav')
<body>
    <div class="box">盒子1</div>
    <div class="box">盒子2</div>
    <div id="nav">
        <ul>
            <li>首页</li>
            <li>产品</li>
        </ul>
    </div>
    <script>
        // 1. getElementsByClassName 根据类名获得某些元素集合
        var boxs = document.getElementsByClassName('box');
        console.log(boxs);
        // 2. querySelector 返回指定选择器的第一个元素对象  切记 里面的选择器需要加符号 .box  #nav
        var firstBox = document.querySelector('.box');
        console.log(firstBox);
        var nav = document.querySelector('#nav');
        console.log(nav);
        var li = document.querySelector('li');
        console.log(li);
        // 3. querySelectorAll()返回指定选择器的所有元素对象集合
        var allBox = document.querySelectorAll('.box');
        console.log(allBox);
        var lis = document.querySelectorAll('li');
        console.log(lis);
    </script>
</body>
  • 获取特殊元素(body,html)
    • 获取body元素:document.body
    • 获取html元素:document.documentElement

操作元素

  • 改变元素的内容(获取或设置)
    • 从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉:element.innerText
    • 起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行:element.HTML
<body>
    <button>显示当前系统时间</button>
    <div>某个时间</div>
    <p>1123</p>
    <script>
        // 当我们点击了按钮,  div里面的文字会发生变化
        // 1. 获取元素 
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        // 2.注册事件
        btn.onclick = function() {
            // div.innerText = '2019-6-6';
            div.innerHTML = getDate();
        }
        function getDate() {
            var date = new Date();
            // 我们写一个 2019年 5月 1日 星期三
            var year = date.getFullYear();
            var month = date.getMonth() + 1;
            var dates = date.getDate();
            var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
            var day = date.getDay();
            return '今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day];
        }
    </script>
</body>
  • innerTextinnerHTML 的区别
    • 获取内容时的区别:innerText 会去除空格和换行,而 innerHTML 会保留空格和换行
    • 设置内容时的区别:innerText 不会识别html,而 innerHTML 会识别
<body>
    <div></div>
    <p>
        我是文字
        <span>123</span>
    </p>
    <script>
        // innerText 和 innerHTML的区别 
        // 1. innerText 不识别html标签 非标准  去除空格和换行
        var div = document.querySelector('div');
        // div.innerText = '<strong>今天是:</strong> 2019';
        // 2. innerHTML 识别html标签 W3C标准 保留空格和换行的
        div.innerHTML = '<strong>今天是:</strong> 2019';
        // 这两个属性是可读写的  可以获取元素里面的内容
        var p = document.querySelector('p');
        console.log(p.innerText);
        console.log(p.innerHTML);
    </script>
</body>
  • 常用元素的属性操作
    • innerText innerHTML
    • src href
    • id alt title
    • 获取属性的值:元素对象.属性名
    • 设置属性的值:元素对象.属性名 = 值
<body>
    <button id="ldh">刘德华</button>
    <button id="zxy">张学友</button> <br>
    <img src="images/ldh.jpg" alt="" title="刘德华">
    <script>
        // 修改元素属性  src
        // 1. 获取元素
        var ldh = document.getElementById('ldh');
        var zxy = document.getElementById('zxy');
        var img = document.querySelector('img');
        // 2. 注册事件  处理程序
        zxy.onclick = function() {
            img.src = 'images/zxy.jpg';
            img.title = '张学友思密达';
        }
        ldh.onclick = function() {
            img.src = 'images/ldh.jpg';
            img.title = '刘德华';
        }
    </script>
</body>
  • 表单元素的属性操作
    • 利用DOM可以操作如下表单元素的属性:type value checked selected disabled
    • 获取属性的值:元素对象.属性名
    • 设置属性的值:元素对象.属性名 = 值
<body>
    <button>按钮</button>
    <input type="text" value="输入内容">
    <script>
        // 1. 获取元素
        var btn = document.querySelector('button');
        var input = document.querySelector('input');
        // 2. 注册事件 处理程序
        btn.onclick = function() {
            // 表单里面的值 文字内容是通过 value 来修改的
            input.value = '被点击了';
            // 如果想要某个表单被禁用 不能再点击 disabled  我们想要这个按钮 button禁用
            // btn.disabled = true;
            this.disabled = true;
            // this 指向的是事件函数的调用者 btn
        }
    </script>
</body>
  • 样式属性操作
    • 行内样式操作:element.style
      • 元素对象.style.样式属性 = 值;
      • JS里面的样式采取驼峰命名法,比如fontSize、backgroundColor
      • JS修改style样式操作,产生的是行内样式,CSS权重比较高
    • 类名样式操作:element.className
      • 元素对象.className = 值;
      • 如果样式修改较多,可以采取操作类名方式更改元素样式
      • class因为是个保留字,因此使用className来操作元素类名属性
      • className会直接更改元素的类名,会覆盖原先的类名
<body>
    <div></div>
    <script>
        // 1. 获取元素
        var div = document.querySelector('div');
        // 2. 注册事件 处理程序
        div.onclick = function() {
            // div.style里面的属性 采取驼峰命名法 
            this.style.backgroundColor = 'purple';
            this.style.width = '250px';
        }
    </script>
</body>
<body>
    <div class="first">文本</div>
    <script>
        // 1. 使用 element.style 获得修改元素样式  如果样式比较少 或者 功能简单的情况下使用
        var test = document.querySelector('div');
        test.onclick = function() {
            // this.style.backgroundColor = 'purple';
            // this.style.color = '#fff';
            // this.style.fontSize = '25px';
            // this.style.marginTop = '100px';

            // 2. 我们可以通过 修改元素的className更改元素的样式 适合于样式较多或者功能复杂的情况
            // 3. 如果想要保留原先的类名,我们可以这么做 多类名选择器
            // this.className = 'change';
            this.className = 'first change';
        }
    </script>
</body>
  • 获取属性值
    • 获取属性值:element.属性
      • 获取内置属性值(元素本身自带的属性)
    • 获取自定义属性值:element.getAttribute('属性')
      • 主要获得自定义的属性
    <div id="demo" index="1" class="nav"></div>
    <script>
        var div = document.querySelector('div');
        // 1. 获取元素的属性值
        // (1) element.属性
        console.log(div.id);
        //(2) element.getAttribute('属性')  get得到获取 attribute 属性的意思 我们程序员自己添加的属性我们称为自定义属性 index
        console.log(div.getAttribute('id'));
        console.log(div.getAttribute('index'));
	</script>
  • 设置属性值
    • 设置属性值:element.属性 = '值'
    • 设置自定义属性值:element.setAttribute('属性','值')
  div.id = 'test';
  div.className = 'navs';
  
  div.setAttribute('index', 2);
  div.setAttribute('class', 'footer'); 
  // class 特殊  这里面写的就是class 不是className
  • 移出属性
    • element.removeAttribute('属性')
  div.removeAttribute('index');
  • H5自定义属性

    • 自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
    • 自定义属性获取是通过getAttribute(‘属性’) 获取。
    • 但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。
  • 设置H5自定义属性

    • H5规定自定义属性以 data- 开头,作为属性名并且赋值
  <div data-index='1' id='div'></div>
  <script>
    var div = document.getElementById('div');
    div.setAttribute('data-index','2');
  </script>
  • 获取H5自定义属性
    • 兼容性获取:element.getAttribute('data-index');
    • H5新增(IE 11才开始支持):element.dataset.index 或者 element.dataset[index]
    <div getTime="20" data-index="2" data-list-name="andy"></div>
    <script>
        var div = document.querySelector('div');
        // console.log(div.getTime);
        console.log(div.getAttribute('getTime'));
        div.setAttribute('data-time', 20);
        console.log(div.getAttribute('data-index'));
        console.log(div.getAttribute('data-list-name'));
        // h5新增的获取自定义属性的方法 它只能获取data-开头的
        // dataset 是一个集合里面存放了所有以data开头的自定义属性
        console.log(div.dataset);
        console.log(div.dataset.index);
        console.log(div.dataset['index']);
        // 如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法
        console.log(div.dataset.listName);
        console.log(div.dataset['listName']);
    </script>

节点操作

  • 节点概述

    • 网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。
    • HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
    • 一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
      • 元素节点 nodeType 为1
      • 属性节点 nodeType 为2
      • 文本节点 nodeType 为3 (文本节点包含文字、空格、换行等)
    • 我们在实际开发中,节点操作主要操作的是元素节点
  • 节点层级

    • 利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系
  • 父级节点

    • node.parentNode
    • 该属性可返回某节点的父节点,注意是最近的一个父节点
    • 如果指定的节点没有父节点,则返回null
    <div class="demo">
        <div class="box">
            <span class="erweima">×</span>
        </div>
    </div>
    <script>
        // 1. 父节点 parentNode
        var erweima = document.querySelector('.erweima');
        // var box = document.querySelector('.box');
        // 得到的是离元素最近的父级节点(亲爸爸) 如果找不到父节点就返回为 null
        console.log(erweima.parentNode);
    </script>
  • 子节点
    • 所有子节点
      • parentNode.childNodes (标准)
      • 返回包含指定节点的子节点的集合,该集合为即时更新的集合
      • 返回值里包含了所有的子节点,包括元素节点,文本节点等
      • 如果只想要获得里面的元素节点,则需要专门处理,所以我们一般不提倡使用childNodes
    • 子元素节点
      • parentNode.children (非标准)
      • 该属性是一个只读属性,返回所有的子元素节点,它只返回子元素节点,其余节点不返回
      • 虽然children 是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用
    <ul>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <script>
        // DOM 提供的方法(API)获取
        var ul = document.querySelector('ul');
        var lis = ul.querySelectorAll('li');
        // 1. 子节点  childNodes 所有的子节点 包含 元素节点 文本节点等等
        console.log(ul.childNodes);
        console.log(ul.childNodes[0].nodeType);
        console.log(ul.childNodes[1].nodeType);
        // 2. children 获取所有的子元素节点 也是我们实际开发常用的
        console.log(ul.children);
    </script>
  • 第一个子节点

    • parentNode.firstChild
    • 返回第一个子节点,找不到则返回null,同样,也是包含所有的节点
  • 最后一个子节点

    • parentNode.lastChild
    • 返回最后一个子节点,找不到则返回null,同样,也是包含所有的节点
  • 第一个子元素节点(IE 9以上支持)

    • parentNode.firstElementChild
    • 返回第一个子元素节点,找不到则返回null
  • 最后一个子元素节点(IE 9以上支持)

    • parentNode.lastElementChild
    • 返回最后一个子元素节点,找不到则返回null
  • 日常开发

    • 获取第一个子元素节点:parentNode.children[0]
    • 获取最后一个子元素节点:parentNode.children[parentNode.children.length-1]
    <ol>
        <li>我是li1</li>
        <li>我是li2</li>
        <li>我是li3</li>
        <li>我是li4</li>
        <li>我是li5</li>
    </ol>
    <script>
        var ol = document.querySelector('ol');
        // 1. firstChild 第一个子节点 不管是文本节点还是元素节点
        console.log(ol.firstChild);
        console.log(ol.lastChild);
        // 2. firstElementChild 返回第一个子元素节点 ie9才支持
        console.log(ol.firstElementChild);
        console.log(ol.lastElementChild);
        // 3. 实际开发的写法  既没有兼容性问题又返回第一个子元素
        console.log(ol.children[0]);
        console.log(ol.children[ol.children.length - 1]);
    </script>
  • 下一个兄弟节点

    • node.nextSibling
    • 返回当前元素的下一个兄弟节点,找不到则返回null
  • 上一个兄弟节点

    • node.previousSibling
    • 返回当前元素上一个兄弟节点,找不到则返回null
    <div>我是div</div>
    <span>我是span</span>
    <script>
        var div = document.querySelector('div');
        // 1.nextSibling 下一个兄弟节点 包含元素节点或者 文本节点等等
        console.log(div.nextSibling);
        console.log(div.previousSibling);
        // 2. nextElementSibling 得到下一个兄弟元素节点
        console.log(div.nextElementSibling);
        console.log(div.previousElementSibling);
    </script>
  • 下一个兄弟元素节点((IE 9以上支持))

    • node.nextElementSibling
    • 返回当前元素下一个兄弟元素节点,找不到则返回null
  • 上一个兄弟元素节点((IE 9以上支持))

    • node.previousElementSibling
    • 返回当前元素上一个兄弟节点,找不到则返回null
  • 兼容性解决方案(封装一个兼容性函数)

   function getNextElementSibling(element) {
      var el = element;
      while (el = el.nextSibling) {
        if (el.nodeType === 1) {
            return el;
        }
      }
      return null;
    }  
  • 创建节点

    • document.createElement('tagName')
    • 动态创建元素节点
  • 添加节点

    • node.appendChild(child)
      • 此方法将一个节点添加到指定父节点的子节点列表末尾
    • node.insertBefore(child, 指定元素)
      • 此方法将一个节点添加到指定父节点的子节点列表前面
    <ul>
        <li>123</li>
    </ul>
    <script>
        // 1. 创建节点元素节点
        var li = document.createElement('li');
        // 2. 添加节点 node.appendChild(child)  node 父级  child 是子级 后面追加元素
        var ul = document.querySelector('ul');
        ul.appendChild(li);
        // 3. 添加节点 node.insertBefore(child, 指定元素);
        var lili = document.createElement('li');
        ul.insertBefore(lili, ul.children[0]);
        // 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素
    </script>
  • 删除节点
    • node.removeChild()
    • 此方法从 node节点中删除一个子节点,返回删除的节点。
    <button>删除</button>
    <ul>
        <li>熊大</li>
        <li>熊二</li>
        <li>光头强</li>
    </ul>
    <script>
        // 1.获取元素
        var ul = document.querySelector('ul');
        var btn = document.querySelector('button');
        // 2. 删除元素  node.removeChild(child)
        // ul.removeChild(ul.children[0]);
        // 3. 点击按钮依次删除里面的孩子
        btn.onclick = function() {
            if (ul.children.length == 0) {
                this.disabled = true;
            } else {
                ul.removeChild(ul.children[0]);
            }
        }
    </script>
  • 复制(克隆)节点
    • node.cloneNode()
    • 此方法返回调用该方法的节点的一个副本,也称拷贝节点
    • 如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
    • 如果括号参数为true,则是深拷贝,即会克隆复制节点本身以及里面所有的子节点。
    <ul>
        <li>1111</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        // 1. node.cloneNode(); 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
        // 2. node.cloneNode(true); 括号为true 深拷贝 复制标签复制里面的内容
        var lili = ul.children[0].cloneNode(true);
        ul.appendChild(lili);
    </script>

创建元素的三种方式

  • document.write();

    • 直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
  • element.innerHTML

    • 将内容写入某个DOM节点,不会导致页面全部重绘
    • 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
  • createElement()

    • 创建多个元素效率稍低一点点,但是结构更清晰
  • 不同浏览器下,element.innerHTML 效率要比 createElement()

    <script>
        // 三种创建元素方式区别 
        // 1. document.write() 创建元素  如果页面文档流加载完毕,再调用这句话会导致页面重绘
         var btn = document.querySelector('button');
         btn.onclick = function() {
             document.write('<div>123</div>');
         }

        // 2. innerHTML 创建元素
        var inner = document.querySelector('.inner');
         for (var i = 0; i <= 100; i++) {
             inner.innerHTML += '<a href="#">百度</a>'
         }

        var arr = [];
        for (var i = 0; i <= 100; i++) {
            arr.push('<a href="#">百度</a>');
        }
        inner.innerHTML = arr.join('');

        // 3. document.createElement() 创建元素
        var create = document.querySelector('.create');
        for (var i = 0; i <= 100; i++) {
            var a = document.createElement('a');
            create.appendChild(a);
        }
    </script>

innerTHMLcreateElement效率对比

  • innerHTML字符串拼接方式(效率低)
    (function () {
        var d1 = +new Date();
        for (var i = 0; i < 1000; i++) {
            document.body.innerHTML += '<div style="100px; height:2px; border:1px solid blue;"></div>';
        }
        var d2 = +new Date();
        console.log(d2 - d1);
    })();
  • createElement方式(效率一般)
    (function () {
        var d1 = +new Date();
        for (var i = 0; i < 1000; i++) {
            var div = document.createElement('div');
            div.style.width = '100px';
            div.style.height = '2px';
            div.style.border = '1px solid red';
            document.body.appendChild(div);
        }
        var d2 = +new Date();
        console.log(d2 - d1);
    })();
  • innerHTML数组方式(效率高)
    (function () {
        var d1 = +new Date();
        var array = [];
        for (var i = 0; i < 1000; i++) {
            array.push('<div style="100px; height:2px; border:1px solid blue;"></div>');
        }
        document.body.innerHTML = array.join('');
        var d2 = +new Date();
        console.log(d2 - d1);
    })();

DOM的核心总结

  • 概述

    • 对于JavaScript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的DOM编程接口
    • 对于HTML,DOM使得HTML形成了一棵DOM树,包含文档、元素、节点
    • 关于DOM操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。
  • 创建

    • document.write();
    • element.innerHTML 与数组结合,效率最高
    • createElement()
  • 增加

    • node.appendChild(child) 末尾追加
    • node.insertBefore(child, 指定元素) 前置追加
  • 删除

    • node.removeChild() 返回删除节点
  • 修改

    • 修改元素属性:src href title
    • 修改普通元素内容:innerHTML innerText
    • 修改表单元素:value type disabled
    • 修改元素样式:style className
  • 查询

    • DOM提供的API方法:getElementById getElementByTagName
    • H5提供的新方法:querySelector querySelectorAll
    • 利用节点操作获取元素:parentNode children previousElementSibling nextElementSibling
  • 属性操作

    • setAttribute 设置DOM的属性值
    • getAttribute 得到DOM的属性值
    • removeAttribute 移除属性
原文地址:https://www.cnblogs.com/SharkJiao/p/13550081.html