JS高级程序设计——第11章 DOM扩展 11.4 专有扩展

一、文档模式

  1. 文档模式的概念和作用:IE8 引入了一个新的概念叫“文档模式”(document mode)。页面的文档模式决定了可以使用什么功能。换句话说,文档模式决定了你可以使用哪个级别的 CSS,可以在 JavaScript 中使用哪些 API,以及 如何对待文档类型(doctype)

  2. 到了 IE9,总共有以下 4 种文档模式
     IE5:以混杂模式渲染页面(IE5 的默认模式就是混杂模式)。IE8 及更高版本中的新功能都无法使用。

     IE7:以 IE7标准模式渲染页面。IE8 及更高版本中的新功能都无法使用。

     IE8:以 IE8 标准模式渲染页面。IE8 中的新功能都可以使用,因此可以使用 Selectors API、更多CSS2 级选择符和某些 CSS3 功能,还有一些 HTML5 的功能。不过 IE9 中的新功能无法使用。

     IE9:以 IE9 标准模式渲染页面。IE9 中的新功能都可以使用,比如 ECMAScript 5、完整的 CSS3以及更多 HTML5 功能。这个文档模式是最高级的模式。

  3. 要强制浏览器以某种模式渲染页面,可以使用 HTTP 头部信息 X-UA-Compatible,或通过等价的 <meta>标签来设置:

<meta http-equiv="X-UA-Compatible" content="IE=IEVersion">
  • 注意,这里 IE 的版本(IEVersion)有以下一些不同的值,而且这些值并不一定与上述 4 种文档模式对应。

     Edge:始终以最新的文档模式来渲染页面。忽略文档类型声明。对于 IE8,始终保持以 IE8 标准模式渲染页面。对于 IE9,则以 IE9 标准模式渲染页面。
     EmulateIE9:如果有文档类型声明,则以 IE9 标准模式渲染页面,否则将文档模式设置为 IE5。
     EmulateIE8:如果有文档类型声明,则以 IE8 标准模式渲染页面,否则将文档模式设置为 IE5。
     EmulateIE7:如果有文档类型声明,则以 IE7 标准模式渲染页面,否则将文档模式设置为 IE5。
     9强制以 IE9 标准模式渲染页面,忽略文档类型声明。
     8强制以 IE8 标准模式渲染页面,忽略文档类型声明。
     7强制以 IE7 标准模式渲染页面,忽略文档类型声明。
     5强制将文档模式设置为 IE5,忽略文档类型声明。

  • 比如,要想让文档模式像在 IE7 中一样,可以使用下面这行代码:

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"> 

如果不打算考虑文档类型声明,而直接使用 IE7 标准模式,那么可以使用下面这行代码:

<meta http-equiv="X-UA-Compatible" content="IE=7">
  • 没有规定说必须在页面中设置 X-UA-Compatible。默认情况下,浏览器会通过文档类型声明来确 定是使用最佳的可用文档模式,还是使用混杂模式。
  1. document.documentMode 属性:通过 document.documentMode 属性可以知道给定页面使用的是什么文档模式。这个属性是 IE8 中新增的,它会返回使用的文档模式的版本号(在 IE9 中,可能返回的版本号为 5、7、8、9):
 var mode = document.documentMode;

知道页面采用的是什么文档模式,有助于理解页面的行为方式。无论在什么文档模式下,都可以访 问这个属性。

二、children属性

  1. 因此就出现了 children 属性。这个属性是 HTMLCollection 的实例只包含元素中同样还是元素的子节点。除此之外, children 属性与 childNodes 没有什么区别,即在元素只包含元素子节点时,这两个属性的值相同。 下面是访问 children 属性的示例代码:
var childCount = element.children.length;
var firstChild = element.children[0];

IE8 及更早版本的 children 属性中也会包含注释节点,但 IE9 之后的版本则只返回元素节点

三、contains()方法

  1. contains() 方法:在实际开发中,经常需要知道某个节点是不是另一个节点的后代IE 为此率先引入了 contains() 方法,以便不通过在 DOM 文档树中查找即可获得这个信息。
  2. 调用 contains()方法的应该是祖先节点, 也就是搜索开始的节点,这个方法接收一个参数,即要检测的后代节点。如果被检测的节点是后代节点, 该方法返回 true;否则,返回 false。以下是一个例子:
alert(document.documentElement.contains(document.body)); //true

这个例子测试了元素是不是元素的后代,在格式正确的 HTML 页面中,以上代码返 回 true。

  1. compareDocumentPosition():也能够确定节点间的关系。返回一个表示该关系的位掩码( bitmask)。下表列出了这个位掩码的值。
    在这里插入图片描述
  • 模仿 contains()方法,应该关注的是掩码 16。可以对 compareDocumentPosition()的结果执行按位与,以确定参考节点(调用 compareDocumentPosition()方法的当前节点)是否包含给定 的节点(传入的节点)。来看下面的例子:
var result = document.documentElement.compareDocumentPosition(document.body); 
alert(!!(result & 16)); //返回16

执行上面的代码后,result结果会变成 20(表示“居后”的 4 加上表示“被包含”的 16)。对掩码 16 执行按位操作会返回一个非零数值,而两个逻辑非操作符会将该数值转换成布尔值。

  • 使用一些浏览器及能力检测,就可以写出如下所示的一个通用的 contains 函数:函数的第一个参数是参考节点,第二个参数是要检查的节点
function contains(refNode, otherNode){
    if (typeof refNode.contains == "function" &&(!client.engine.webkit || client.engine.webkit >= 522)){
    //首先检测 refNode 中是否存在 contains()方法(能 力检测)。这一部分代码还检查了当前浏览器所用的 WebKit 版本号
         return refNode.contains(otherNode);
    } else if (typeof refNode.compareDocumentPosition == "function"){
         return !!(refNode.compareDocumentPosition(otherNode) & 16);
    } else {
            var node = otherNode.parentNode;
            do {
                if (node === refNode){
                    return true;
                } else {
                    node = node.parentNode;
                }
            } while (node !== null);
            
              return false;
    }
}

首先检测 refNode 中是否存在 contains()方法(能力检测)。这一部分代码还检查了当前浏览器所用的 WebKit 版本号。如果方法存在而且不是 WebKit(!client.engine.webkit),则继续执行代码。否则,如果浏览器是 WebKit 且至少是 Safari 3(WebKit 版本号为 522 或更高),那么也可以继续执行代码。在 WebKit 版本号小于 522 的 Safari 浏览器中, contains()方法不能正常使用。

 接下来检查是否存在 compareDocumentPosition()方法
 而函数的最后一步则是自 otherNode 开始向上遍历 DOM 结构,以递归方式取得 parentNode,并检查其是否与 refNode 相等。在文档树的顶端,parentNode 的值等于 null,于是循环结束。这是针对旧版本 Safari 设计的一个后备策略。

四、插入文本

前面介绍过,IE 原来专有的插入标记的属性 innerHTML 和 outerHTML 已经被 HTML5 纳入规范。 但另外两个插入文本的专有属性则没有这么好的运气。这两个没有被 HTML5 看中的属性innerTextouterText

1、innerText 属性
  1. 通过 innertText 属性可以操作元素中包含的所有文本内容,包括子文档树中的文本
  2. 在通过 innerText 读取值时,它会按照由浅入深的顺序,将子文档树中的所有文本拼接起来。在通过 innerText 写入值时,结果会删除元素的所有子节点,插入包含相应文本值的文本节点
  • 来看下面这 个 HTML 代码示例。
<div id="content">
    <p>This is a <strong>paragraph</strong> with a list following it.</p>
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
	</ul>
 </div>

对于这个例子中的<div>元素而言,其 innerText 属性会返回下列字符串:

 This is a paragraph  with a list following it
 Item 1
 Item 2
 Item 3

由于不同浏览器处理空白符的方式不同,因此输出的文本可能会也可能不会包含原始 HTML 代码 中的缩进

  1. 使用 innerText 属性设置这个<div>元素的内容,则只需一行代码:
div.innerText = "Hello world!";

执行这行代码后,页面的 HTML 代码就会变成如下所示。

<div id="content">Hello world!</div>
  • 设置 innerText 属性的同时,也对文本中存在的 HTML 语法字符(小于号、大于号、引号及和号)进行了编码。再看 一个例子。
div.innerText = "Hello & welcome, <b>\"reader\"!</b>";

运行以上代码之后,会得到如下所示的结果。

  <div id="content">Hello &amp; welcome, &lt;b&gt;&quot;reader&quot;!&lt;/b&gt;</div>
  • 设置 innerText 永远只会生成当前节点的一个子文本节点,而为了确保只生成一个子文本节点, 就必须要对文本进行 HTML 编码。利用这一点,可以通过 innerText 属性过滤掉 HTML 标签。方法是 将 innerText 设置为等于 innerText,这样就可以去掉所有 HTML 标签,比如:
div.innerText = div.innerText;

执行这行代码后,就用原来的文本内容替换了容器元素中的所有内容(包括子节点,因而也就去掉 了 HTML 标签)。

  1. textContent 属性:Firefox 虽然不支持 innerText,但支持作用类似的 textContent 属性。其他支持 textContent 属性的浏览器还有 IE9+、Safari 3+、Opera 10+和 Chrome。为了确保跨浏览器兼容,有必要编写一个类似于下面的函数来检测可以使用哪个属性。
function getInnerText(element){
    return (typeof element.textContent == "string") ?
        element.textContent : element.innerText;
}
function setInnerText(element, text){
    if (typeof element.textContent == "string"){
        element.textContent = text;
    } else {
        element.innerText = text;
    }
}

这两个函数都接收一个元素作为参数,然后检查这个元素是不是有 textContent 属性。如果有, 那么 typeof element.textContent 应该是"string";如果没有,那么这两个函数就会改为使用 innerText。

  • 可以像下面这样调用这两个函数。
setInnerText(div, "Hello world!");
alert(getInnerText(div));    //"Hello world!"

使用这两个函数可以确保在不同的浏览器中使用正确的属性。

2、outerText 属性(尽可能不使用这个属性)
  1. 作用范围扩大到了包含调用它的节点
  • 读取文本值时,outerText 与 innerText 的结果完全一样。但在写模式下,outerText 就完全不 同了:outerText 不只是替换调用它的元素的子节点,而是会替换整个元素(包括子节点)。比如:
div.outerText = "Hello world!";
//这行代码实际上相当于如下两行代码:
var text = document.createTextNode("Hello world!");
div.parentNode.replaceChild(text, div);

本质上,新的文本节点会完全取代调用 outerText 的元素。此后,该元素就从文档中被删除,无法访问。

由于这个属性会导致调用它的元素不存在,因此并不常用。我们也建议读者尽可能不要使用这个属性。

五、滚动

HTML5 在将 scrollIntoView()纳入规范之后,仍然还有其他几个专有方法可以在不同的浏览器中使用。下面列出 的几个方法都是对 HTMLElement 类型的扩展,因此在所有元素中都可以调用。
scrollIntoViewIfNeeded(alignCenter)只在当前元素在视口中不可见的情况下,才滚动浏览器窗口或容器元素,最终让它可见。如果当前元素在视口中可见,这个方法什么也不做。 如果将可选的 alignCenter 参数设置为 true,则表示尽量将元素显示在视口中部(垂直方向)。 Safari 和 Chrome 实现了这个方法。
scrollByLines(lineCount):将元素的内容滚动指定的行高lineCount 值可以是正值, 也可以是负值。Safari 和 Chrome 实现了这个方法。
scrollByPages(pageCount):将元素的内容滚动指定的页面高度,具体高度由元素的高度决定。Safari 和 Chrome 实现了这个方法。

  • 希望大家要注意的是,scrollIntoView()scrollIntoViewIfNeeded()的作用对象是元素的容器,而 scrollByLines()scrollByPages()影响的则是元素自身。下面还是来看几个示例吧。
//将页面主体滚动 5 行 
document.body.scrollByLines(5);
//在当前元素不可见的时候,让它进入浏览器的视口
document.images[0].scrollIntoViewIfNeeded();
//将页面主体往回滚动 1 页 
document.body.scrollByPages(-1);

由于 scrollIntoView()是唯一一个所有浏览器都支持的方法,因此还是这个方法最常用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值