React JSX 开发笔记

Posted ArchieCMS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React JSX 开发笔记相关的知识,希望对你有一定的参考价值。

1、JSX是什么

优点:

  • JSX 执行更快,因为它在编译为 javascript 代码后进行了优化。

  • 它是类型安全的,在编译过程中就能发现错误。

  • 使用 JSX 编写模板更加简单快速。

JSX是一种像下面这样的语法:

const element = <h1>Hello, world!</h1>;

它是一种JavaScript语法扩展,在React中可以方便地用来描述UI。本质上,JSX为我们提供了创建React元素方法(React.createElement(component, props, ...children))的语法糖(syntactic sugar)。上面的代码实质上等价于:

var element = React.createElement(
"h1",  null,  "Hello, world!");

2、JSX代表JS对象

JSX本身也是一个表达式,在编译后,JSX表达式会变成普通的JavaScript对象。

你可以在if语句或for循环中使用JSX,你可以将它赋值给变量,你可以将它作为参数接收,你也可以在函数中返回JSX。

例如下面的代码:

function getGreeting(user) {    if (user) {   
       return <h1>Hello, {formatName(user)}!</h1>;    }  
   return <h1>Hello, Stranger.</h1>;
}

上面的代码在if语句中使用JSX,并将JSX作为函数返回值。实际上,这些JSX经过编译后都会变成JavaScript对象。

经过babel会变成下面的js代码:

function test(user) {
    if (user) {        
       return React.createElement(            
           "h1",            
           null,            
           "Hello, ",            formatStr(user),            
           "!"        );    }    
   return React.createElement(        
       "h1",        
       null,        
       "Hello, Stranger."    ); }

3、在JSX中使用JavaScript表达式

在JSX中插入JavaScript表达式十分简单,直接在JSX中将JS表达式用大括号括起来即可。例如:

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}
const user = {  firstName: 'Harper',  lastName: 'Perez'};const element = (  
   <h1> Hello, {formatName(user)}!  </h1>); ReactDOM.render(      element,      document.getElementById('root') );

上面的代码中用到了函数调用表达式fromatName(user)。

在JavaScript中,表达式就是一个短语,Javascript解释器会将其计算出一个结果,常量就是最简单的一类表达式。常用的表达式有:

  • 变量名;

  • 函数定义表达式;

  • 属性访问表达式;

  • 函数调用表达式;

  • 算数表达式;

  • 关系表达式;

  • 逻辑表达式;

需要注意的是,if语句以及for循环不是JavaScript表达式,不能直接作为表达式写在{}中,但可以先将其赋值给一个变量(变量是一个JavaScript表达式):

function NumberDescriber(props) {
  let description; 
  if (props.number % 2 == 0) {    description = <strong>even</strong>;  } else {    description = <i>odd</i>;  }  
  return <div>{props.number} is an {description} number</div>;}

4、JSX属性值

你可以使用引号将字符串字面量指定为属性值:

const element = <div tabIndex="0"></div>;

注意这里的”0”是一个字符串字面量。

或者你可以将一个JavaScript表达式嵌在一个大括号中作为属性值:

const element = <img src={user.avatarUrl}></img>;

这里用到的是JavaScript属性访问表达式,上面的代码将编译为:

const element = React.createElement(
"img", { src: user.avatarUrl });

5、JSX的Children

首先JSX可以是一个不包含Children的empty tag。如:

const element = <img src={user.avatarUrl} />;

JSX也可以像html标签一样包含Children

const element = (  <div>    <h1>Hello!</h1>    <h2>Good to see you here.</h2>  </div>);

这种写法在生成React元素的时候给我们带来了很大的便利,而且能够更加直观地描述UI。不然我们需要像下面这样创建和上面代码等价的React元素:

const element = React.createElement(  "div",  null,
  React.createElement(    
   "h1",    
   null,    
   "Hello!"  ),  React.createElement(    
   "h2",    
   null,    
   "Good to see you here."  ) );

tip: React DOM结点使用骆驼拼写法给属性命名

例如:class在JSX中应写作className,tabindex应写作tabIndex。

另外关于JSX的children需要注意的是:

React自定义组件的chilren是不会像固有的HTML标签的子元素那样自动render的,我们看下面的例子:

代码1class Test extends React.Component {
    render() {      return (  <div>
   Here is a list:          
         <ul>            <li>Item 1</li>            <li>Item 2</li>          </ul>        </div>      )    } }; ReactDOM.render(    <Test />,    document.getElementById('test') );

以上代码定义的组件中都是build-in组件,类似div、p、ul、li等。它们中的子元素会直接render出来,像下面这样:

但是如果你使用用户定义组件,比如:

class Test extends React.Component {
    render() {      return (      <Em>        Here is a list:        <ul>          <li>Item 1</li>          <li>Item 2</li>        </ul>      </Em>    )    } }; class Em extends React.Component {  render() {    return (<div></div>);  } } ReactDOM.render(    <Test />,    document.getElementById('test') );

并不能得到跟上面代码1一样的结果,我们得到的只是一个空的div标签:

如果你想得到和代码1一样的结果,需要显示地指定props.children,像下面这样:

class Test extends React.Component {
    render() {      return (          <Em>            Here is a list:            <ul>              <li>Item 1</li>              <li>Item 2</li>            </ul>          </Em>      )    } }; class Em extends React.Component {  render() {    return (<div>{this.props.children}</div>);  } } ReactDOM.render(    <Test />,    document.getElementById('test') );

得到下面的结果:6、JSX可自动防范注入攻击

在JSX中嵌入接收到的内容是安全的,比如:

const danger = response.potentialDanger;

cosnt ele = <h1>{title}</h1>

在默认情况下,React DOM会将所有嵌入JSX的值进行编码。这样可以有效避免xss攻击。

我们将以下代码编译后引入html:

class Test extends React.Component {
    render() {          
   let v = "<script><\/script>";          
   return (          
         <div>            <h1>{v}</h1>          </div>        )    } }; ReactDOM.render(    <Test />,    document.getElementById('test') );

得到结果是:

可以看到通过JSX插入的文本自动进行了HTML转义,所以这里插入的是一段文本,而不是<script>标签。这有点类似于Js中的document.createTextNode("...")(实际上我们可以利用document.createTextNode进行HTML转义)。

作为对比,换作使用DOM元素的innerHTML属性:

<!DOCTYPE html><html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <div id="test"></div>
    <script type="text/javascript">      document.getElementById("test").innerHTML
      ="<h1><script><\/script><\/h1>";    
   </script>  </body></html>

得到结果如下:


意文本的颜色,此时插入的是一个<script>标签。

如果你很清楚自己在做什么,希望直接将字符串不经转义编码直接插入到HTML文档流,可以使用dangerouslySetInnerHTML属性,这是一个React版的innerHTML,该属性接收一个key为__html的对象,修改代码如下:

      class Test extends React.Component {
            render() {              
             let v = {                __html: "<script><\/script>"              };              
             return (              
             <div>                <h1 dangerouslySetInnerHTML={v}/>              </div>              )          }      };

这次我们插入了<script>标签:


、进阶

1、JSX中的props

指定JSX中的props有以下几种方式:

(1)使用JavaScript表达式

任何有效的JavaScript表达式都可以作为prop的值,使用的时候将该表达式放在一对大括号中即可:

<MyComponent foo={1 + 2 + 3 + 4} />
<YourComponent clickTodo={(id) =>
this.props.handleClick(id)} />

(2)使用字符串字面量

字符串字面量可以作为prop值,下面的代码是等价的:

<MyComponent message="hello world" />
<MyComponent message={'hello world'} />

(3)使用扩展运算符

如果你想将一个prop对象传入JSX,你可以使用扩展运算符...直接将整个prop对象传入。下面的2个组件是等价的:

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;}
function App2() {  const props = {firstName: 'Ben', lastName: 'Hector'};
 return <Greeting {...props} />;}

扩展运算符是一个es6特性。是一种传递属性的十分便利的方式。但请注意不要滥用该运算符,注意不要将一大堆毫不相关的prop一股脑全部传入下面的组件中。

2、JSX中的Children

React组件中有一个特殊的prop–props.children。它指代了JSX表达式中开闭标签中包含的内容。

下面讨论的是几种指定JSX的children的方法:

(1)使用字符串字面量

你可以直接在JSX的开闭标签中写入字符串字面量,组件得到的props.children就是该字符串值。

以下面的代码为例:

<MyComponent>Hello world!</MyComponent>

MyComponent的props.chilren将获得”Hello World!”字符串。通过该方式传入的字符串是未经HTML转义的。实际上你只需要像在HTML标签中写入文本那样就可以了。例如你想在一对<p>标签中写入文本”<script></script>”,HTML和JSX写法是一样的,就像下面这样:

<p>&#60;script&#62;&#60;/script&#62;</p>

另外需要注意的是:

JXS会自动删除一行中开头和结尾处的空白符;JSX会自动删除空行;JSX会删除紧邻标签的换行;JSX会删除字符串中的换行;字符串中的换行会被转换成一个空格

举例来说,下面的JSX代码都是等价的:

<div>Hello World</div><div> Hello World   </div><div>
  Hello World</div><div>
  Hello
  World</div><div>

  Hello World</div>

(2)JSX元素作为children

我们同样可以使用JSX元素作为JSX的children,由此生成嵌套组件:

<MyContainer>  
<MyFirstComponent /><MySecondComponent />
</MyContainer>

我们也可以混合使用字符串字面量和JSX作为children:

<El>
  Here is a list:  
 <ul>    <li>Item 1</li>    <li>Item 2</li>  </ul>
</El>

El的props.children将得到一个数组:

可以看到数组的第一个元素就是字符串“Here is a list:”,第二个元素是一个对象(JSX代表JavaScript对象)。

(3)JavaScript表达式

和prop一样,你也可以将任何有效的JavaScript表达式作为children传入,将它放在{}中就可以了。像下面这样:

<MyComponent>{'foo'}</MyComponent>

这里传入了一个常量表达式。

下面使用一个函数调用表达式来生成一个list作为children:

function Item(props) {
  return <li>{props.message}</li>;}
function TodoList() {  const todos = [
           'finish doc',
           'submit pr',
           'nag dan to review'];  
return (    
      <ul>          {todos.map((message) =>
           <Item key={message} message={message} />)}  
      </ul>  ); }

当然你也可以在一个字符串children中插入一个JavaScript表达式来生成一个“模板”:

function Hello(props) {
  return <div>Hello {props.username}!</div>;}

(4)函数children

首先说明,这不是一种常见的用法。

实际上,传入自定义组件的children并没有严格的限制,只要在React需要render的时候能将它们转换成可以render的东西就行了。

下面是一个函数children的例子:

function ListOfTenThings() {
  return (    
   <Repeat numTimes={10}>      {(index) => <div key={index}>
   This is item {index} in the list</div>}  
   </Repeat>  ); } // Calls the children callback numTimes to
//produce a repeated component
function Repeat(props) {  let items = [];  for (let i = 0; i < props.numTimes; i++) {
   items.push(props.children(i));  }  
   return <div>
{items}</div>;
}

实际上,我们更通常的情况下是将(index) => <div key={index}>This is item {index} in the list</div>作为一个prop传入子组件。这个例子只是作为一种理解上的扩展。

(5)有关布尔值、Null以及Undefined

布尔值,Null以及Undefined可以作为有效的children,但他们不会被render,下面的JSX表达式都会render一个空的div标签:

<div />
<div></div><div>{false}</div><div>{null}</div><div>{true}</div>

关于此有一个有趣的应用,在条件render中,下面的<Header />只有在show为true时才会render:

<div>
  {showHeader && <Header />}  <Content />
</div>

3、注意事项

(1)使用JSX时要引入React库

前面已经解释过了,JSX是React.createElement方法的语法糖,因此在使用JSX的作用域中必须引入React库。

如果你使用了JS打包工具,你可以在文件的头部作如下引用:

import React from 'react';

或者你不使用打包工具,也可以直接通过script标签引入React,比如:

//本地
<script src="./react.js"></script>
//或者BootCDN
<script src="http://cdn.bootcss.com/react/15.4.0/react.js">
</script>

此时React将作为一个全局变量被引入,变量名就是’React’。

(2)注意引入JSX中用到的自定义组件

JSX中用到的组件可能并不会在JavaScript中直接引用到,但自定义组件本质上就是一个JS对象,你在JSX中使用的时候,需要首先将该组件引入到当前作用域:

import MyComponent from './MyComponent.js'...
<Outer>  <MyComponent /></Outer>

(3)自定义组件首字母一定要大写

JSX中小写字母开头的element代表HTML固有组件如div,span,p,ul等。用户自定义组件首字母一定要大写如<Header><Picker>

(4)元素标签名不能使用表达式

下面的代码将产生错误:

const components = {
  photo: PhotoStory,
  video: VideoStory
};function Story(props) {
  // Wrong! JSX标签名不能使用表达式
  return <components[props.storyType] story={props.story} />;}

如果你需要使用一个表达式来决定元素标签,你应该先将该表达式的值赋给一个大写字母开头的变量:

const components = {
  photo: PhotoStory,
  video: VideoStory
};function Story(props) {
  // Correct! JSX type can be a capitalized variable.
  const SpecificStory = components[props.storyType]; 
 return <SpecificStory story={props.story} />;}

(5)设置style属性


在设置标签style属性的时候,要注意,我们是将一个描述style的对象以JavaScipt表达式的形式传入。因此应该有2层大括号:

<div style={{color:'red', margin:'10px auto'}}></div>

                                                               



以上是关于React JSX 开发笔记的主要内容,如果未能解决你的问题,请参考以下文章

React 学习笔记总结

React 学习笔记总结

react 学习笔记

初学React:JSX语法

React Native学习笔记

react学习笔记