zl程序教程

您现在的位置是:首页 >  后端

当前栏目

[js]dom树-js原型链

JS dom 原型
2023-09-27 14:21:16 时间

这是之前总结的, 发现有很多的毛病,就是重点不突出,重新翻看的时候还是得耗费很长时间去理解这玩意.

js中的继承

js中什么是类

1,类是函数数据类型


2.每个类有一个自带prototype属性
prototype = constractor+__proto__

3,每个类的实例指向类的原型

给人感觉子类继承父类的东西,和父类本身没啥关系, 和父类的财产(原型)有关系.

console.log(document instanceof Document); // true
console.log(window instanceof Window);     // true

object <-- EventTarget <-- 
                            Element(1)
                                HTMLElement <-- HTMLDivElement <-- div
                                                                   odiv = document.getElementById('app');
                            Document(9)
                                    document是Document的一个实例.
                                        - 常用属性
                                        document.head
                                        document.body
                                        document.title
                                        
                                        document.location.href
                                        document.location.host
                                        
                                        
                                        document.location.protocol
                                        document.location.host
                                        
                                        document.location.origin
                                        document.URL             //获取url
                                        
                                        document.location.pathname
                                        document.location.search
                                        
                                        document.cookie
                                        document.documentElement //整个html的引用
                                        
                                        
                                        - 常用方法
                                        document.getElementById
                                        document.getElementsByClassName
                                        document.getElementsByTagName
                                        document.append


window.location.pathname
window.location.search
window.close() //关闭标签
window.open()
参考: http://www.w3school.com.cn/js/js_window.asp
onchange等事件,在哪里?

dir(HTMLDivElement)

DOM 是为了操作文档出现的 API,document 是其的一个对象;
BOM 是为了操作浏览器出现的 API,window 是其的一个对象。
- 继承: 本类的原型指向要继承类的实例

- 模拟系统类
    function myObject() {

    };

    function myEventTarget() {

    };

    myEventTarget.prototype = new myObject;
    myEventTarget.prototype.addListener = function () {

    };

    function myNode() {

    }

    myNode.prototype = new myEventTarget;
    myNode.prototype.createElement = function () {

    };

    var n = new myNode;
    console.dir(n);

js

DOM节点层次图

Dom并非一种编程语言,Dom只是提供了一系列的接口,利用Dom的这些接口可以很方便的读取,修改,删除Html和XML文件中的标签元素和文本内容.在这里我们侧重于讲解Dom对Html文件的操作.
那么Dom是如何读取和管理Html文件的呢?首先你必须要了解html的源码结构

div       > HTMLDivElement > HTMLElement > Element > Node > EventTarget
document -> HTMLDocument   > Document    >           Node > EventTarget

参考: DOM, DOCUMENT, BOM, WINDOW 有什么区别?
https://www.zhihu.com/question/33453164

document.title = 'how to make love';

document.body;
document.getElementById('xxx');

DOM 是为了操作文档出现的 API,document 是其的一个对象;
BOM 是为了操作浏览器出现的 API,window 是其的一个对象。

div       > HTMLDivElement > HTMLElement > Element > Node > EventTarget
document -> HTMLDocument   > Document    >           Node > EventTarget

参考: http://huang-jerryc.com/2016/06/28/JavaScript原型中的哲学思想/

参考: 从原型链看DOM--Node类型
http://www.cnblogs.com/venoral/p/5293575.html

参考:http://www.th7.cn/web/js/201609/188644.shtml

参考:http://www.cnblogs.com/mominger/p/3822775.html

dom操作

回顾dom

参考:
http://www.bijishequ.com/detail/413949?p=11-54-70
http://www.bijishequ.com/detail/421975?p=

这篇很经典
http://www.cnblogs.com/jscode/archive/2012/09/04/2670819.html

这篇图解还没怎么理解
http://developer.51cto.com/art/201009/228137_all.htm

div#div1
    HTMLDivElement
        HTMLElement
            Element
                Node
                    EventTarget
                        Object
                            
div       > HTMLDivElement > HTMLElement > Element > Node > EventTarget
document -> HTMLDocument   > Document    >           Node > EventTarget

oDiv instanceof Node        //true
oDiv instanceof Element     //true
##################################
# 获取元素
##################################
document.
    getElementById       得到类数组 获取选项/长度  遍历
    getElementsByTagName
    getElementsByName(button获取性别,先遍历checkbox,oSex[i].value)
    getElementsByClassName

##################################
# 元素之间的关系
##################################
// 节点: 文字 标签 文字 注释都是节点  回车和空格算一个 text

//                    nodetype    nodename       nodevalue
// 元素节点: 标签        1           大写标签名    null
// 文本节点: text        3           #text        文档内容
// 注释节点:             8           #commnet     注释内容
// document              9           #document     null

console.log(oDiv.nodeType); //获取所有子节点的元素节点,判断nodetype
console.log(oDiv.nodeName);
console.log(oDiv.nodeValue);


console.log(oDiv.children);   //获取元素子节点
console.log(oDiv.parentNode);   //获取父亲节点
console.log(oDiv.previousElementSibling);//获取上一个哥哥节点
console.log(oDiv.nextSibling);           //获取下一个弟弟节点
console.log(oDiv.firstChild); //获取所有子节点中的第一个
console.log(oDiv.lastChild); //获取所有子节点中最后一个

##################################
# 增删改查元素
##################################
var layer = document.createElement("div");
layer.id = "div1";
layer.style.width = "300px";
layer.style.height = "200px";
layer.style.border = "5px solid red";

var btn = document.getElementById('btn');
btn.onclick = function () {
    document.body.appendChild(layer);
};
layer.onclick = function () {
    document.body.removeChild(layer);
};


oDiv.parentNode.removeChild(oDiv);
document.body.insertBefore(oP2, oP);
oDiv.parentNode.removeChild(oDiv);
var clop = oP.cloneNode();      //克隆当前
var clop2 = oP.cloneNode(true); //克隆子子孙孙


js操作的是行内样式.
oDiv.style.width //引用数据类型
    oDiv.style.backgroundColor  //这种ok
    var bgS = oDiv.style;                bgS.backgroundColor //这种ok
    var bg = oDiv.style.backgroundColor; bg = "green" //这种不ok

constructor的事

默认类的prototype = constructor+proto

function Fn() {

};

console.log(Fn.prototype);

重新赋值后prototype = proto,没constructor了

function Fn() {

};
Fn.prototype= {
    getX: function () {
    }
};
console.log(Fn.prototype);

var f = new Fn();
console.log(f.__proto__);

原型链多级继承模拟

<script>
    //    HTMLDivElement > HTMLElement > Element > Node > EventTarget > object
    function myObject() {
    };
    myObject.prototype = {
        hasOwnProperty: function () {
            console.log("myObject");
        }
    };
    function myEventTarget() {
    };
    myEventTarget.prototype = new myObject();
    myEventTarget.prototype.sum = function () {
        console.log('myEventTarget...')
    };

    var f = new myEventTarget;
    console.dir(f);

</script>

/*
 * 操作DOM的属性和方法
 *   [获取元素或者元素集合]
 *    getElementById
 *      ->上下文只能是document(只有document这个实例的原型链上才能找到这个方法,其它实例都找不到)
 *      ->ID重复了获取第一个
 *      ->IE6~7中会把表单元素的name当做id使用
 *    getElementsByTagName
 *      ->获取当前上下文中,所有子子孙孙中标签名叫做XXX的元素
 *    getElementsByClassName
 *      ->IE6~8中不兼容
 *    getElementsByName
 *      ->在IE浏览器中只对表单元素的name起作用
 *      ->上下文也只能是document
 *    querySelector
 *    querySelectorAll
 *      ->不兼容IE6~8
 *      ->没有DOM映射
 *    document.documentElement
 *    document.body
 *    document.head
 *    ...
 *
 *   [描述节点和节点之间关系的属性]
 *          nodeType nodeName  nodeValue
 *     元素节点  1  大写标签名  null
 *     文本节点  3  #text     文本内容
 *     注释节点  8  #comment  注释内容
 *     文档节点  9  #document null
 *
 *   childNodes:所有子节点
 *   children:所有元素子节点(IE6~8中会把注释当做元素节点)
 *   parentNode
 *   previousSibling / previousElementSibling
 *   nextSibling
 *   firstChild
 *   lastChild
 *
 *   [动态操作DOM]
 *     createElement
 *     createDocumentFragment
 *     appendChild
 *     insertBefore
 *     cloneNode(true/false)
 *     removeChild
 *     set/get/removeAttribute
 *
 *   [散]
 *     xxx.style.xxx=xxx  设置行内样式
 *     =>xxx.style.xxx  获取行内样式
 *
 *     xxx.className='xxx'
 *
 *     xxx.onclick=function...
 *
 *     ...
 */

/*
 * JS盒子模型属性
 *   =>在JS中通过相关的属性可以获取(设置)元素的样式信息,这些属性就是盒子模型属性(基本上都是有关于样式的)
 *
 *   client
 *      top
 *      left
 *      width
 *      height
 *
 *   offset
 *      top
 *      left
 *      width
 *      height
 *      parent
 *
 *   scroll
 *      top
 *      left
 *      width
 *      height
 */

//=>clientTop/Left/Width/Height
//1.clientWidth & clientHeight:获取当前元素可视区域的宽高(内容的宽高+左右/上下PADDING)
//=>和内容是否有溢出无关(和是否设置了OVERFLOW:HIDDEN也无关),就是我们自己设定的内容的宽高+PADDING

//=>获取当前页面一屏幕(可视区域)的宽度和高度
// document.documentElement.clientWidth || document.body.clientWidth
// document.documentElement.clientHeight || document.body.clientHeight

//2.clientTop & clientLeft:获取(上/左)边框的宽度

//3.offsetWidth & offsetHeight:在client的基础上加上border(和内容是否溢出也没有关系)

//4、scrollWidth & scrollHeight:真实内容的宽高(不一定是自己设定的值,因为可能会存在内容溢出,有内容溢出的情况下,需要把溢出的内容也算上)+ 左/上PADDING,而且是一个约等于的值 (没有内容溢出和CLIENT一样)
//=>在不同浏览器中,或者是否设置了OVERFLOW:HIDDEN都会对最后的结果产生影响,所以这个值仅仅做参考,属于约等于的值

//=>获取当前页面的真实宽高(包含溢出的部分)
// document.documentElement.scrollWidth || document.body.scrollWidth
// document.documentElement.scrollHeight || document.body.scrollHeight

//=============================
//=>通过JS盒模型属性获取值的特点
//1.获取的都是数字不带单位
//2.获取的都是整数,不会出现小数(一般都会四舍五入,尤其是获取的 偏移量)
//3.获取的结果都是复合样式值(好几个元素的样式组合在一起的值),如果只想获取单一样式值(例如:只想获取PADDING),我们的盒子模型属性就操作不了了(这不能说没有用,真实项目中,有时候我们就是需要获取组合的值来完成一些操作)

//===========[获取元素具体的某个样式值]
//1.[元素].style.xxx 操作获取
//> 只能获取所有写在元素行内上的样式(不写在行内上,不管你写没写都获取不到,真实项目中我们很少会把样式写在行内上)
//=>outer.style.width =>'' (width是写在样式表中的)

//2.获取当前元素所有经过浏览器计算的样式
//> 经过计算的样式:只要当前元素可以在页面中呈现(或者浏览器渲染它了),那么它的样式都是被计算过的
//=>不管当前样式写在哪
//=>不管你是否写了(浏览器会给元素设置一些默认样式)
/*
 * 标准浏览器(IE9+)
 *   window.getComputedStyle([元素],[伪类,一般都写null]) 获取到当前元素所有被浏览器计算过的样式(对象)
 *
 * IE6~8
 *   [元素].currentStyle 获取经过计算的样式
 */

/*
 * getCss:获取当前元素某一个样式属性值
 *
 * @param
 *    curEle[object]:当前要操作的元素
 *    attr[string]:当前要获取的样式属性名
 *
 * @return
 *    获取的样式属性值
 */
let getCss = function getCss(curEle, attr) {
    if ('getComputedStyle' in window) {
        let val = window.getComputedStyle(curEle, null)[attr];
        //=>把获取的结果去除单位(不是所有的值都能去单位的,例如:display\一些复合值都去不掉单位),只有符合 数字+单位 这种模式的结果才能基于PARSE-FLOAT去单位
        let reg = /^-?\d+(\.\d+)?(px|rem|em|pt)?$/i;
        reg.test(val) ? val = parseFloat(val) : null;
        return val;
    }
    //=>throw new SyntaxError:抛出一个错误(语法错误),让浏览器崩溃,不在继续执行JS
    throw new SyntaxError('您的浏览器版本过低,请升级到最新版本,谢谢配合!!');
};
console.log(getCss(outer, 'width'));