JSX学习记录


JSX语法详解

    本文在官方文档的基础上,进行了扩展扩展补充和一些解读。基本涵盖了JSX语法的细枝末节,JSX语法本身并不复杂,也容易掌握。本文供学习参考使用。

一、基础
1、JSX是什么

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

const element =

Hello, world!

;
它是一种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

Hello, {formatName(user)}!

;
  }
  return

Hello, Stranger.

;
}
上面的代码在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 = (
 


    Hello, {formatName(user)}!
 


);

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 = even;
  } else {
    description = odd;
  }
  return
{props.number} is an {description} number
;
}

4、JSX属性值

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

注意这里的”0”是一个字符串字面量。
或者你可以将一个JavaScript表达式嵌在一个大括号中作为属性值:
const element = ;


这里用到的是JavaScript属性访问表达式,上面的代码将编译为:
const element = React.createElement("img", { src: user.avatarUrl });


5、JSX的Children

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


JSX也可以像HTML标签一样包含Children:
const element = (
 


   

Hello!


   

Good to see you here.


 

);

这种写法在生成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的,我们看下面的例子:

代码1
class Test extends React.Component {
    render() {
      return (
       

          Here is a list:
         

               
  • Item 1

  •            
  • Item 2

  •          

       

      )
    }
};
ReactDOM.render(
    ,
    document.getElementById('test')
);

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


但是如果你使用用户定义组件,比如:
class Test extends React.Component {
    render() {
      return (
     
        Here is a list:
       


             
  • Item 1

  •          
  • Item 2

  •        

     

    )
    }
};

class Em extends React.Component {
  render() {
    return (
);
  }
}

ReactDOM.render(
    ,
    document.getElementById('test')
);

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

如果你想得到和代码1一样的结果,需要显示地指定props.children,像下面这样:
class Test extends React.Component {
    render() {
      return (
         
            Here is a list:
           

                 
  • Item 1

  •              
  • Item 2

  •            

         

      )
    }
};

class Em extends React.Component {
  render() {
    return (
{this.props.children}
);
  }
}

ReactDOM.render(
    ,
    document.getElementById('test')
);

得到下面的结果:

6、JSX可自动防范注入攻击

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

const danger = response.potentialDanger;

cosnt ele =

{title}



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

我们将以下代码编译后引入html:
class Test extends React.Component {
    render() {
          let v = "
 


得到结果如下:

注意文本的颜色,此时插入的是一个”,HTML和JSX写法是一样的,就像下面这样:

<script></script>



另外需要注意的是:

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

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

Hello World


Hello World  



  Hello World



  Hello
  World




  Hello World


(2)JSX元素作为children

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

 
 


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


  Here is a list:
 

       
  • Item 1

  •    
  • Item 2

  •  



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


(3)JavaScript表达式

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

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

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

function Item(props) {
  return

  • {props.message}
  • ;
    }

    function TodoList() {
      const todos = ['finish doc', 'submit pr', 'nag dan to review'];
      return (
       

            {todos.map((message) => )}
         

      );
    }

    当然你也可以在一个字符串children中插入一个JavaScript表达式来生成一个“模板”:
    function Hello(props) {
      return
    Hello {props.username}!
    ;
    }


    (4)函数children

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

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

    下面是一个函数children的例子:
    function ListOfTenThings() {
      return (
       
          {(index) =>

    This is item {index} in the list
    }
       
      );
    }

    // 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
    {items}
    ;
    }

    实际上,我们更通常的情况下是将(index) =>
    This is item {index} in the list
    作为一个prop传入子组件。这个例子只是作为一种理解上的扩展。
    (5)有关布尔值、Null以及Undefined

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




    {false}


    {null}


    {true}


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


      {showHeader &&
    }
     


    3、注意事项
    (1)使用JSX时要引入React库

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

    如果你使用了JS打包工具,你可以在文件的头部作如下引用:
    import React from 'react';
    或者你不使用打包工具,也可以直接通过script标签引入React,比如:
    //本地

    //或者BootCDN


    此时React将作为一个全局变量被引入,变量名就是’React’。
    (2)注意引入JSX中用到的自定义组件

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

    import MyComponent from './MyComponent.js'

    ...


     


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

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

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

    下面的代码将产生错误:
    const components = {
      photo: PhotoStory,
      video: VideoStory
    };

    function Story(props) {
      // Wrong! JSX标签名不能使用表达式
      return ;
    }

    如果你需要使用一个表达式来决定元素标签,你应该先将该表达式的值赋给一个大写字母开头的变量:
    const components = {
      photo: PhotoStory,
      video: VideoStory
    };

    function Story(props) {
      // Correct! JSX type can be a capitalized variable.
      const SpecificStory = components[props.storyType];
      return ;
    }


    (5)设置style属性

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

    注:原文地址http://blog.csdn.net/a153375250/article/details/53434299,本人只供本人学习方便特摘过来放于本人博客园中!!