005@关于JSX语法.md

005@关于JSX语法

转(有所更改):React入门:关于JSX语法
可以参考的资料:
React.js学习笔记之JSX解读

JSX=JavaScriptXML。 JSX是React的核心组成部分,它使用XML标记的方式去直接声明界面,界面组件之间可以互相嵌套。

SX可以看作JavaScript的拓展,看起来有点像XML。使用React,可以进行JSX语法到JavaScript的转换。

    //使用JSX
    React.render(
        
content
, document.getElementById('example') ); //不使用JSX React.render( React.createElement('div', null, React.createElement('div', null, React.createElement('div', null, 'content') ) ), document.getElementById('example') );

那么也就是说,我们写一个XML标签,实质上就是在调用React.createElement这个方法,并返回一个ReactElement对象。

    ReactElement createElement(
      string/ReactClass type,
      [object props],
      [children ...]
    )

这个方法的第一个参数可以是一个字符串,表示是一个HTML标准内的元素,或者是一个ReactClass类型的对象,表示我们之前封装好的自定义组件。第二个参数是一个对象,或者说是字典也可以,它保存了这个元素的所有固有属性(即传入后基本不会改变的值)。从第三个参数开始,之后的参数都被认作是元素的子元素。

JSX语法

SX本身就和XML语法类似,可以定义属性以及子元素。唯一特殊的是可以用大括号来加入JavaScript表达式,例如

var HelloMessage = React.createClass({
  render: function() {
    return 
Hello {this.props.name}
; } }); ReactDOM.render(, mountNode);

一、元素名

自定义出的组件标签名,React 的 JSX 里约定分别使用首字母大、小写来区分本地组件的类和 HTML 标签。render渲染时,会把大写的组件名定义为自定义组件,把小写的组件名定义为HTML自带的标签名进行渲染。

var HelloMessage =

JSX的标签与函数名都是使用的驼峰命名。
htmlFor和className

for和class为js的保留字,在书写for与class时需要修改为htmlFor何className,注意都是使用的驼峰命名。
自闭合标签

在 JSX 中, 是合法的,而 就不合法。 所有的标签都必须闭合,可以是自闭和的形式,也可以是常规的闭合。

注意:所有 React component 都可以采用自闭和的形式,包括div等

二、子节点

组件与组件之间就像标签与标签之间可以有嵌套关系,与HTML不同的是可以在子节点中使用求值表达式。目前, 一个 component 的 render,只能返回一个节点。如果你需要返回一堆 div , 那你必须将你的组件用 一个div 或 span 或任何其他的组件包裹。

** 切记,JSX 会被编译成常规的 JS; 因此返回两个函数也就没什么意义了,同样地,千万不要在三元操作符中放入超过一个子节点。**

节点属性:

使用标签的时候指定属性和属性值传入标签内部,使标签内部可以使用属性值。
注意:

如果往原生 HTML 元素里传入 HTML 规范里不存在的属性,React 不会显示它们。如果需要使用自定义属性,要加 data- 前缀。

然而任意属性支持自定义元素

    

三、求值表达式

要使用 JavaScript 表达式作为属性值,只需把这个表达式用一对大括号 ( { } ) 包起来,不要用引号 ( " " )。求值表达式本身与JSX没有多大关系,是JS中的特性。它是会返回值的表达式,与语句有本质上的不同,在编写JSX时,在 { } 中不能使用语句(if语句、for语句等等)。我们不能直接使用语句,但可以把语句包裹在函数求值表达式中运用。建议把函数表达式独立出来,在 { } 调用。

你没法在JSX中使用 if-else 语句,因为 JSX 只是函数调用和对象创建的语法糖。在 { } 中使用,是不合法的JS代码,不过可以采用三元操作表达式

var HelloMessage = React.createClass({
  render: function() {
    return 
Hello {this.props.name ? this.props.name : "World"}
; } }); ReactDOM.render(, document.body);

可以使用比较运算符“ || ”来书写,如果左边的值为真,则直接返回左边的值,否则返回右边的值,与if的效果相同。

var HelloMessage = React.createClass({ 
  render: function() {
      return 
Hello {this.props.name || "World"}
; } }); ReactDOM.render(, document.body);

也可以使用变量来书写

var HelloMessage = React.createClass({
  getName : function() {
      if (this.props.name)
          return this.props.name
      else
          return "world"
  } 
  render: function() {
      var name = this.getName();
      return 
Hello {name}
; } }); ReactDOM.render(, document.body);

其中可以把变量去掉,直接在 { } 中调用函数

  render: function() {
      return 
Hello {this.getName()}
; }

函数表达式

( )有强制运算的作用

var HelloMessage = React.createClass({ 
  render: function() {
      return 
Hello { (function(obj){ if(obj.props.name) return obj.props.name else return "World" }(this)) }
; } }); ReactDOM.render(, document.body);

外括号“ )”放在外面和里面都可以执行。唯一的区别是括号执行完毕拿到的是函数的引用,然后再调用;括号放在外面的时候拿到的事返回值。需传入(this)。

四、注释

JSX 里添加注释很容易;它们只是 JS 表达式而已。你只需要在一个标签的子节点内(非最外层)小心地用 { } 包围要注释的部分。

var content = (
  
);

转化

React JSX将类似XML的语法转化到原生的JavaScript,元素的标签、属性和子元素都会被当作参数传给React.createElement方法:

#JSX
var Nav;
var app = 

JSX转化器

要把带有JSX语法的代码转化为纯Javascript代码,有多种方式,对于内联与HTML中的代码或者是未经过转化的外部文件,在script标签中要加上type="text/jsx",并引入JSXTransformer.js文件即可,不过这种方式并不建议在生产环境使用,建议的方法是在代码上线前就将代码转换好,可以使用npm全局安装react-tools:

npm install -g react-tools

并使用命令行工具转化即可(具体用法可以参考jsx -h):

jsx src/ build/

HTML 标签 vs. React 组件

React.render方法可以渲染HTML结构,也可以渲染React组件。
渲染HTML标签,声明变量采用首字母小写

    var myDivElement = 
; React.render(myDivElement, document.body);

渲染React组件,声明变量采用首字母大写

var MyComponent = React.createClass({/*...*/});
var myElement = ;
React.render(myElement, document.body);

React 的 JSX 使用大写和小写字母来区分本地的组件类和 HTML 标签.

不过需要注意的是class和for这两个属性,JSX语法最终是要被转换为纯Javascript的,所以要和在Javascript DOM中一样,用className和htmlFor。

    //使用JSX
    React.render(
        ,
        document.getElementById('example')
    );
     
    //不使用JSX
    React.render(
        React.createElement('label', {className: 'xxx', htmlFor: 'input'}, 'content'),
        document.getElementById('example')
    );

还有一点是,在创建HTML标准内的元素时,JSX转化器会丢弃那些非标准的属性,如果一定要添加自定义属性,那么需要在这些自定义属性之前添加data-前缀。

命名空间式组件

比如开发组件的时候,一个组件有多个子组件,你希望这些子组件可以作为其父组件的属性,那么可以像这样用:

    var Form = MyFormComponent;
     
    var App = (
      
);

这样你只需将子组件的ReactClass作为其父组件的属性:

    var MyFormComponent = React.createClass({ ... });
     
    MyFormComponent.Row = React.createClass({ ... });
    MyFormComponent.Label = React.createClass({ ... });
    MyFormComponent.Input = React.createClass({ ... });

而创建子元素可以直接交给JSX转化器:

    var App = (
        React.createElement(Form, null,
            React.createElement(Form.Row, null,
                React.createElement(Form.Label, null),
                React.createElement(Form.Input, null)
            )
        )
    );

Javascript表达式

在JSX语法中写Javascript表达式只需要用{}即可,比如下面这个使用三目运算符的例子:

JSX是HTML和JavaScript混写的语法,当遇到<,JSX就当HTML解析,遇到{就当JavaScript解析。

    // Input (JSX):
    var content = {window.isLoggedIn ? 

属性表达式

    React.render(
        
1 ? 'class-a' : 'class-b'}>content
, document.body );

子表达式

    var Nav = React.createClass({
        render: function () {
            return 
nav
} }); React.render(
{2 > 1 ?
, document.body );

不过要注意的是,JSX语法只是语法糖,它的背后是调用ReactElement的构造方法React.createElement的,所以类似这样的写法是不可以的:

    // This JSX:
    
Hello World!
// Is transformed to this JS: React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");

可以从转化后的Javascript代码中看出明显的语法错误,所以要不用三目运算符,要不就这样写:

    if (condition) 
Hello World!
else
Hello World!

传播属性(Spread Attributes)

如果提前就知道了组件的属性的话,写起来很容易。例如component组件有两个动态的属性foo和bar:

var component = ;

而实际上,有些属性可能是后续添加的,我们没办法一开始就确定,我们可能会写出下面不好的代码:

    var component = ;
    component.props.foo = x; // bad
    component.props.bar = y; // also bad

这样写是错误的,因为我们手动直接添加的属性React后续没办法检查到属性类型错误,也就是说,当我们手动添加的属性发生类型错误时,在控制台是看不到错误信息的。

在React的设定中,初始化完props后,props是不可变的。改变props会引起无法想象的后果。

延伸属性

为了解决这个问题,React引入了属性延伸

    var props = {};
    props.foo = x;
    props.bar = y;
    var component = ;
    //或者
    var props = { foo: x, bar: y };
    var component = ;

这样就相当于:

var component = 

当需要拓展我们的属性的时候,定义个一个属性对象,并通过{…props}的方式引入,在JSX中,可以使用...运算符,表示将一个对象的键值对与ReactElement的props属性合并,这个...运算符的实现类似于ES6 Array中的...运算符的特性。,React会帮我们拷贝到组件的props属性中。重要的是—这个过程是由React操控的,不是手动添赋值的属性。

它也可以和普通的XML属性混合使用,需要同名属性,后者将覆盖前者:

    var props = { foo: 'default' };
    var component = ;
    console.log(component.props.foo); // 'override'

JSX 陷阱

style属性

在React中写行内样式时,要这样写,不能采用引号的书写方式

    React.render(
        
xxxxx
, document.body );

HTML转义

比如我们有一些内容是用户输入的富文本,从后台取到数据后展示在页面上,希望展示相应的样式

    var content='content';
     
    React.render(
        
{content}
, document.body );

结果页面直接输出内容了:

content

React默认会进行HTML的转义,避免XSS攻击,如果要不转义,可以这么写:

    var content='content';    
     
    React.render(
        
, document.body );

你可能感兴趣的:(005@关于JSX语法.md)