玩转Reactjs第二篇-渲染和JSX

一、前言

前一章我们搭建了Reactjs的标准工程,本章节我们基于标准工程的demo应用,了解react的 渲染和JSX语法。

二、渲染

1、在标准工程的public/index.html下

<div id="root"></div>

该div是我们整个应用的根节点,所有的DOM节点都挂载在该节点下,可以看成web容器。

2、再看src/index.js代码

//1、引入相关包
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

//2、将app定义节点挂载到root节点下
ReactDOM.render(<App />, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

(1)、引入相关的组件和包,其中"react","react-dom"是react的基本包,App是应用节点组件。

(2)、ReactDOM.render将App定义的节点挂载到root节点下,root下的所有节点都在React的作用域中。可以类比Vue的入口方法new Vue()。

3、继续看src/App.js

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

定义App方法然后导出,App方法返回一段类似html的代码段,该代码段最终渲染成如下dom节点

我们看相似度达到99%,DOM结构以及标签相同,但是也有不同的地方

(1)class属性名,在代码段中为className,

(2)img的src的为引用的表达式。

这就是我们接下来要隆重介绍的JSX。

三、什么是JSX

     熟悉Vue的同学知道(后面我们会经常与vue比较,理解两者的异同点),UI和JS是分开的,UI采用的Template模式,对于使用原生态前端的同学更容易掌握。在Reactjs中,一般采用将UI嵌套在js表达式中,即JSX(Javascript XML),虽然从形式上看类似HTML,但是实质上是javascript表达式,是javascript的一种扩展形式。有以下特点:

1、引用表达式

既然JSX是js表达式,那当然可以引用表达式了,比如demo中的img的src的属性值就是使用了表达式,需要注意的是表达式放置在{}中。

可以使用对象表达式,如下面的user

...
const user = {
  firstName: 'ma',
  lastName: 'jack'
};

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          hello,{user.firstName},
          Edit <code>src/App.js</code> and save to reload.
        </p>
        ...
      </header>
    </div>
  );
}

export default App;

也可以使用函数表达式,如下面的formatName

...
const user = {
  firstName: 'ma',
  lastName: 'jack'
};

function formatName(user){
  return user.lastName+" "+user.firstName;
}
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          hello,{formatName(user)},
          Edit <code>src/App.js</code> and save to reload.
        </p>
        ....
      </header>
    </div>
  );
}

还可以支持三元表达式,但不支持if else,for的条件表达式。

<div>
      <h1>{i == 1 ? 'True!' : 'False'}</h1>
</div>

2、样式

(1)采用className标签设置样式,如demo中,在App.css中定义样式,将文件导入到App.js中,使用className属性调用

(2)内联样式,如下面的style

...
const style={
  fontSize: 100, 
  color: '#FF0000'
}
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p style ={style}>
          Edit <code>src/App.js</code> and save to reload.
        </p>
       ...
      </header>
    </div>
  );
}

这里样式属性的key值需要使用驼峰命名方式,而不是css的短连接模式。本质上,JSX的内联样式使用的字面量对象,而不是字符串,也可以这样写:

<p style ={{fontSize: 100,  color: '#FF0000'}}>

实际上,除了样式,Reactjs在JSX中实现了一套完整的DOM表达方式,所有的特性和属性都是采用小驼峰命名方式。

四、为什么要用JSX

   如果初学JSX,特别之前使用html,js原生态写前端的同学,非常不习惯将UI与JS糅合在一起的写法。那么为什么Reactjs推荐使用,按照官方说法,总结起来:

  • JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。
  • 它是类型安全的,在编译过程中就能发现错误。
  • 使用 JSX 编写模板更加简单快速。

第三点,有点王婆卖瓜,自卖自夸的意思,只能说仁者见仁,智者见智。我们重点看下前两点。

1、JSX执行更快

我们先来看下JSX的编译过程,官网上给了一个如下的例子。

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

Babel会把 JSX 转译成一个名为 React.createElement() 函数调用

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

createElement实际上创建一个如下的树型结构,称之为"React元素"

// 注意:这是简化过的结构
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

   了解Vue的同学应该很快知道,这就是Vue中所说的Vnode(VUE源码学习第九篇--编译(generate)),他们的原理都是相似的,通过这种React元素,最终构建VDOM,以保持随时更新。

VUE源码学习第七篇--编译(parse),我们梳理了vue的编译过程:

通过正则匹配对Template进行解析,最终生成render表达式,这个过程是非常耗时的,而JSX本来就是JS,无需这一步,大大提高了编译效率。

2、安全性

     这里主要是说的是XSS(Cross Site Script,跨站脚本攻击),它指的是恶意攻击者往Web页面里插入恶意脚本代码,而程序对于用户输入内容未过滤,当用户浏览该页之时,嵌入其中Web里面的脚本代码会被执行,从而达到恶意攻击用户的特殊目的。

   比如以下面一段

const username = "jack ma";
....
<h1>{username}</h1>

username可以是从某个地方获取的(如input),这里为了简化,直接写死来演示。

有人故意篡改了内容

const username = "<img οnerrοr='alert(\"hi!\")' src='invalid-image' />";

当我们运行应用,此时页面正常显示了这段文字,并没有弹出"hi"。

这是应该Reactjs将所有的内容在渲染之前都被转换成了字符串,这样就有效的防止了XSS。

有同学说,我就是希望转义成html,打印hi,怎么办,可以使用dangerouslySetInnerHTML(类似原生的innerHtml)。

const username =  "<img οnerrοr='alert(\"hi!\")' src='invalid-image' />'}";
...
<h1 ><div dangerouslySetInnerHTML = {{"__html":username}} /></h1>

五、总结

本章节点主要阐述了渲染以及JSX,重点对JSX的语法,以及使用JSX的优势进行了详细介绍。

JSX虽然形式上类似html语法,但实际上是javascript的表达式,是javascript的扩展形式。

JSX的优点在于编译快,安全性高,以及编写速度快。

发布了33 篇原创文章 · 获赞 95 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/tcy83/article/details/104235889