HTML、JavaScript、CSS、DOM、JSX关系

JSX是随着Facebook提出react而衍生出的概念;

在Facebook之前,HTML、JavaScript、CSS、DOM之间的关系和作用为:

HTML

HTML只能定义静态的文档,浏览器解释来展现;只写html浏览器也能解释展现一个网页;标签里可带有各类属性,最基本的就是classid。class属性的作用是引用css样式;id的作用是配合javascript使用(获得dom元素),具有唯一性。当然根据标签的不同,还有其他的属性。

CSS

CSS:层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。 它制定了HTML可以支持的各种样式,负责对HTML的展示。 有了CSS的支持,可以使得html更好的展示,一般存放在.css文件里。

多个css样式可集中在单个html标签里,出现这种情况时,一般按优先权划分

(1)浏览器默认设置 (最低)
(2)外部样式表
(3)内部样式表(写在html的<head>标签内部)
(4)内联样式(写在html的标签里,即style属性)(最高)

JavaScript

JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。
JavaScript引擎是单线程运行的,浏览器无论在什么时候都只且只有一个线程在运行JavaScript程序. JavaScript引擎用单线程运行也是有意义的,单线程不必理会线程同步这些复杂的问题,问题得到简化.
JavaScript是如何为HTML写出的网页提供动态的功能呢?这就引出了DOM的概念:

DOM

DOM:W3C定义,一个与系统平台和编程语言无关的接口(API),程序和脚本可以通过这个接口动态地对文档的内容、结构和样式进行访问和修改。它提供了对文档(HTML)的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来。DOM是web页面的完全的面向对象表述,它能够使用如 JavaScript等脚本语言进行修改。

每一个网页元素(一个HTML标签)对应着一个对象。DOM将HTML的文档结构映射为一个树状的对象模型,其中每一个元素(标签)对应着树上的一个节点对象。

DOM中attribute和property的区别:
attribute是一个特性节点,每个DOM元素都有一个对应的attributes属性来存放所有的attribute节点,attributes是一个类数组的容器,说得准确点就是NameNodeMap,总之就是一个类似数组但又和数组不太一样的容器。attributes的每个数字索引以名值对(name=”value”)的形式存放了一个attribute节点。

*获得属性:getAttribute 删除属性:removeAttribute *

property就是一个属性,如果把DOM元素看成是一个普通的Object对象,那么property就是一个以名值对(name=”value”)的形式存放在Object中的属性。要添加和删除property也简单多了,和普通的对象没啥分别:

elem.gameid = 880; // 添加
console.log( elem.gameid ) // 获取
delete elem.gameid // 删除

attribute和property容易混淆的原因是:DOM元素一些默认常见的attribute(如id,class等)节点都有与之对应的property属性,不管使用哪种方法都可以访问和修改。自定义的attribute节点,或者自定义property,两者就没有关系了。

最后为了更好的区分attribute和property,基本可以总结为attribute节点都是在HTML代码中可见的,而property只是一个普通的名值对属性。

// gameid和id都是attribute节点
// id同时又可以通过property来访问和修改
<div gameid="880"   id="box">hello</div>
// areaid仅仅是property
elem.areaid = 900;

DOM属于浏览器实现,浏览器完成HTML文档解析的工作;不是JavaScript语言规范里的内容。

他们之间的关系比喻为:
html是主体,css用来装饰html元素;浏览器将HTML文档解析为树状的DOM模型;javascript通过操作DOM元素简介操作HTML元素(标签);

利用HTML、JavaScript、CSS实现的代码示例:

<html>
  <head>

  <style type="text/css">
    body {background-color: yellow}
    h1 {background-color: #00ff00}
    h2 {background-color: transparent}
    p {background-color: rgb(250,0,255)}
    p.no2 {background-color: gray; padding: 20px;}
 </style>

 </head>

<body>
<h1>这是标题 1</h1>
<h2>这是标题 2</h2>

<script type="text/javascript">
  document.write("<h1>Hello World!</h1>")
</script>

<p>这是段落</p>
<p class="no2">这个段落设置了内边距。</p>
</body>
</html>

代码解释:
其中的<style>标签是CSS设置,放在了<head>标签里(参照CSS优先级),<script>包裹的是JavaScript代码,生成了一个新的<h1>标签,,<script>标签放在了<body>标签里(位置不限于此),我们看到JavaScript用到DOM提供的接口document.write()方法来生成新的标签;

通过上边的实例,我们可以看出HTML、JavaScript、CSS、DOM的关系了。

JSX

2013年5月,Facebook开源了React:

React 独有的 JSX 语法,HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写。

<!DOCTYPE html>
<html>
  <head>
    <script src="../build/react.js"></script>
    <script src="../build/JSXTransformer.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script type="text/jsx">
    {
      var names = ['Alice', 'Emily', 'Kate'];
      names.map(function (name) {
      return <div>Hello, {name}!</div>
       })
    }
  </div>,
    </script>
  </body>
</html>
  • JSX跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/jsx"
  • React 提供两个库: react.js 和 JSXTransformer.js ,它们必须首先加载。其中,JSXTransformer.js 的作用是将 JSX 语法转为 JavaScript 语法。这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。
  • JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用** HTML** 规则解析;遇到代码块(以 { 开头),就用** JavaScript** 规则解析;

总之,JSX是Facebook提出的新语法,提供了JSXTransformer.js去将JSX转换为正常的JavaScript;

将第一实例改为React重写:


<html>
  <head>
    <script src="../build/react.js"></script>
    <script src="../build/JSXTransformer.js"></script>
  <style type="text/css">
    body {background-color: yellow}
    h1 {background-color: #00ff00}
    h2 {background-color: transparent}
    p {background-color: rgb(250,0,255)}
    p.no2 {background-color: gray; padding: 20px;}
 </style>

 </head>

<body>
<h1>这是标题 1</h1>
<h2>这是标题 2</h2>

<script type="text/javascript">
  document.write("<h1>Hello World!</h1>")
</script>
{
      return <div>Hello, world!</div>
}
<p>这是段落</p>
<p class="no2">这个段落设置了内边距。</p>
</body>
</html>

[浏览器 线程机制]

浏览器的内核是多线程的,它们在内核制控下相互配合以保持同步,一个浏览器至少实现三个常驻线程:javascript引擎线程,GUI渲染线程,浏览器事件触发线程。
javascript引擎是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行JS程序。
GUI渲染线程负责渲染浏览器界面,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。但需要注意 GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理

浏览器事件循环

在JavaScript中为了不阻塞UI的渲染,很多JavaScript任务都是异步的,它们包括键盘、鼠标I/O输入输出事件、窗口大小的resize事件、定时器(setTimeout、setInterval)事件、Ajax请求网络I/O回调等。当这些异步任务发生的时候,它们将会被放入浏览器的事件任务队列中去。在浏览器内部中存在一个消息循环池,也叫Event Loop(事件循环),JavaScript引擎在运行时后单线程的处理这些事件任务。例如用户在网页中点击了button事件,则它们会被放入在这个事件循环池中,需要等到JavaScript运行时执行线程空闲时候才会按照队列先进先出的原则被一一执行。对于setTimeout这类定时任务也是一样的,只有当定时时刻达到的时候,它们才会被放入浏览器的事件队列中等待被执行;由于此时的JavaScript主线程也许并不空闲,所以它将并不会被JavaScript引擎所立即执行,因为在JavaScript语言设计中setTimeout这类定时任务的执行时间并不是精确的。在前端开发中经常会发现setTimeout(func, 0)很有用,因为这并不是立即执行,而是将当前执行回调函数放入浏览器的事件队列中,等待当前其他任务的完成,然后在执行它;所以setTimeout(func, 0)具有改变当前代码执行顺序的作用,让浏览器有机会完成UI界面渲染等任务后在执行这段回调函数。当然对于老式浏览器这里具有16ms的差距,HTML5规定为4ms,以及关于动画操作中的requestAnimationFrame,

推荐阅读更多精彩内容