2.ReactJS基础(虚拟DOM,JSX语法)

2019/01/17 17:20
阅读数 87

将脚手架(create-react-app)创建的todolist项目精简为hello world示例

即,删除自动生成的样式文件、logo.svt、App.test.js、serviceWorker.js等文件,并精简App.js和index.js里的代码,结果如下:

npm run start 后,浏览器界面仅显示纯文本 Hello world !

 

一,虚拟DOM

首先,看一段html片段

<div id="container">
    <p>这里是p标签里的文本节点</p>
    <ul>
        <li class="item">这里是li标签里的文本节点</li>
        <li class="item">这里是li标签里的文本节点</li>
        <li class="item">这里是li标签里的文本节点</li>
    </ul>
</div>

上面的html片段会最终生成为DOM对象,并由浏览器渲染到页面上。

而虚拟DOM,就是用一个JS对象模拟上面的DOM元素和结构:

['div', { id: 'container' }, [
    ['p', {}, '这里是p标签里的文本节点'],
    ['ul', {},[
        ['li', { class: 'item' }, '这里是li标签里的文本节点'],
        ['li', { class: 'item' }, '这里是li标签里的文本节点'],
        ['li', { class: 'item' }, '这里是li标签里的文本节点']
      ]
]
 ] ]

 这里用伪代码进行了模拟。虚拟DOM和真实DOM都是js对象。

 为何引入虚拟DOM?因为操作真实DOM耗性能。而DOM操作影响性能,最主要的原因就是因为它导致了浏览器的重绘(repaint)和重排(reflow)。   

 浏览器渲染原理简单描述:浏览器下载到html文档后,会解析文档的结构来构建DOM树;解析css文件,产生css规则树;然后根据DOM树和css规则树构建出渲染   树;最后渲染到浏览器界面上。

 每一次的DOM操作(element.style.borderColor = '#f00';),都会触发页面的重绘或重排。

 但是如果换成操作虚拟DOM,假设操作ul下的li标签,添加1000个li标签并设置内容颜色,对于上面模拟的对象来说完全是在内存中完成,性能损耗几乎不计。

 操作完虚拟DOM后,再映射为真实DOM,交给浏览器渲染,这样性能损耗就只是替换映射这个环节以及渲染一次的过程了。

 以上只是对虚拟DOM的简单描述,总之,虚拟DOM的目的是将所有操作累加起来,统一计算(Diff算法)出所有的变化后,统一更新一次DOM。

二、ReactJS中的JSX语法

JSX全称 JavaScript XML

其实就是对js语法进行了扩展,可以在js代码中写xml标签

作用:用来创建虚拟DOM对象。

import React, { Component } from 'react';

class App extends Component {
  render() {
    return (
      <div>
        Hello world !
      </div>
    );
  }
}

export default App;

例如,App.js中,App组件(react中,继承了Component的类,就是一个组件)中的render方法就是返回了一个虚拟DOM对象。return(<div>Hello world !</div>)中的div并不是虚拟DOM对象,它只是JSX语法,React会最终将其生成一个虚拟DOM对象。

将App.js中的代码做如下修改:

import React, { Component } from 'react';

class App extends Component {
  render() {
    return (
      <div>
        <Test1/>
        <Test2/>
        Hello world !
      </div>
    );
  }
}

class Test1 extends Component {
  render() {
    return (
      <div>
        Test1
      </div>
    );
  }
}
class Test2 extends Component {
  render() {
    return (
      <div>
        Test2
      </div>
    );
  }
}

export default App;

此时浏览器显示结果为:

在App组件中包含了两个子组件Test1和Test2,

可以简单地理解为App组件生成的虚拟DOM是由多个‘子虚拟DOM’组成,最后会将这个大的虚拟DOM映射成真实DOM,由浏览器渲染到页面上。(挂载到id=root的节点上)

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部