React入门笔记(一):简介和JSX

React入门笔记(一):简介和JSX
React入门笔记(二):组件和AJAX
React入门笔记(三):表单、事件、Ref属性
React中的Diff算法——Christopher Chedeau(原文翻译)

一、简介

React是一个用于构建用户界面的JavaScript库,可以认为是MVC中的V(视图),由于React的代码逻辑简单,越来越多的人开始使用。
React的优点如下:

  • 声明式设计:采用声明范式,可以轻松描述应用。
  • 高效:通过对DOM的模拟,最大限度地减少与DOM的交互。
  • 灵活:可以与已知的库或框架很好地结合使用。
  • JSX:JSX是JavaScript语法的扩展,React并不一定使用JSX,但是建议使用。
  • 组件:通过React构建组件,使代码复用性更高。
  • 单向相应的数据流:实现了单向响应的数据流,从而减少重复代码,所以比传统数据绑定更简单。

React库以及一些常用的依赖库:

  • react.js:必需的核心代码
  • react-dom.js:dom渲染
  • react-dom-fiber.js:虚拟调用栈,用于任务调度
  • react-dom-server.js:dom服务端渲染
  • react-with-addons.js:扩展功能
  • browser.js:Babel转换器的核心代码,用于将ES6代码转为ES5代码,也是jsx的编译依赖库,在react 0.14后被使用
  • jsxtransformer.js:jsx的编译依赖库,用于React 0.14之前

二、JSX

JSX是一个看起来很像XML的JavaScript语法扩展,其优点是:

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

JSX看起来类似HTML,元素的自定义属性需要使用data-前缀,以下是一个简单示例。ReactDOM.render是React的最基本方法,用于将模板转为HTML语言,并插入指定的DOM节点。

// ===== DEMO 01 
// id为'example'的元素作为这一小段html片段的container
// 代码中嵌套多个HTML标签,需要使用一个标签元素包裹它,
// 所以此处最外层的div是必须的!!
ReactDOM.render(
    <div>
        <h1>Hello</h1>
        <h2>world!</h2>
        <p data-myattribute="attr-name">
        React is easy to learn!</p>
    </div>
    ,
    document.getELementById('example');
);

JSX位置

JSX语法与JavaScript语法并不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel"

  1. JSX可以像普通JavaScript代码一样直接写到html文件中,用<script type="text/babel"></script>包裹代码片。

  2. React JSX代码可以放在一个独立文件上,比如创建一个helloworld.js文件,代码如DEMO 01,然后在HTML文件中引入该JS文件:

    // ===== DEMO 02
    <body>
        <div id="example"></div>
        <script type="text/babel" src="helloworld.js"></script>
    </body>

开启花括号大法

JSX允许HTML和JavaScript的混写,JSX的基本语法规则,就是遇到HTML标签(以<开头)就用HTML规则解析,遇到代码块(以{开头),就用JavaScript规则解析。所以在html代码中插入一些JavaScript代码块时,就通通用花括号括起来,以下详细介绍:

  1. JavaScript表达式
    在JSX中使用JavaScript表达式可以直接写在花括号{}中,但是在JSX中不能使用if else表达式,但可以使用conditional(三元运算) 表达式来替代,如{i==1?'True':'False'}

  2. 样式
    React推荐使用内联样式,可以使用camelCase语法来设置内联样式(这样是否会很占用名字空间?)。React会在指定元素数字后自动添加px,以下为一个简单示例:

    // ===== DEMO 03
    var myStyle = {
        fontSize: 100,
        color: 'FF0000'
    };
    ReactDOM.render(
        <h1 style={myStyle}>Hello world!</h1>,
        document.getElementById('example')
    );
  3. 注释
    标签内注释要写在花括号中,举栗子如下:

    // ===== DEMO 04
    ReactDOM.render(
        /*标签外注释……*/
        <div>
        <h1>Hello world!</h1>
        {/*标签内注释……*/}
        </div>,
        document.getElementById('example')
    );
  4. 数组
    JSX允许在模板中插入数组,数组会自动展开所有内容,相当于数组中的所有元素拼接在一起,举栗子如下:

    // ==== DEMO 05
    var arr = [
        <h1>Hello</h1>,
        <h2>world!</h2>,
    ];
    ReactDOM.render(
        <div>{arr}</div>,
        document.getELementById('example')
    );
    // Hello
    // world!

React元素 vs React组件

  1. React元素(React element)
    React中最小基本单位,可以用JSX语法简单的创建一个React元素:

    const element = <div className="element">React element</div>

    React元素不是真实的DOM元素而只是js的普通对象(plain objects),所以也无法直接调用DOM原生API,只有这个元素被渲染完成后,才能通过选择器获取对应的DOM元素。按照React有限状态机的设计思想,应当用状态和属性来表述组件,要尽量避免DOM操作,即便要进行DOM操作,也应当使用React提供的接口refgetDOMNode()。除了使用JSX语法,我们还可以使用React.creatElement()React.cloneElement()来构建React元素,这两个函数的参数如下所示。

    // ==== DEMO 06
    React.createElement(
        type,    // 标签名,如`div`,`span`,React组件等
        [props], // 传入属性
        [...children] // 该参数及之后都是组件的子组件
    )
    React.cloneElement(
        element, // React元素,新添加的元素会并入原有属性
        [props],
        [...children]
    )
  2. React组件(React component)
    有三种构建组件的方法。React.createClass()ES6 class和无状态函数。

    • React.createClass():最早、兼容性最好的方法。在0.14版本前官方指定的组件写法。
    • ES6 class:目前官方推荐的使用方法,使用了ES6标准语法来构建,实际仍然是调用了React.createClass()来实现,ES6 class的生命周期和自动绑定方式与React.createClass()略有不同。
    • 无状态函数:使用函数构建的无状态组件,传入propscontext两个参数,没有state,除了render(),没有其他生命周期方法。

      // ==== DEMO 07
      // React.createClass()
      var Greeting = React.createClass({
          render: function(){
              return <h1>Hello {this.props.name}</h1>;
          }
      });
      // ES6 class
      class Greeting extends React.Component{
          render(){
              return <h1>Hello {this.props.name}</h1>;
          }
      }
      // 无状态函数
      function Greeting(props){
          return <h1>Hello {this.props.name}</h1>;
      }

      React.createClass()ES6 class构建的组件的数据结构是类,无状态组件数据结构是函数,但是在React被视为是一样的。

  3. 元素与组件的区别
    组件由元素构成,元素数据结构是普通对象,而组件数据结构是类或纯函数。
    元素就是一个用于描述出现在页面中的 DOM 节点或者 React 组件的纯对象。元素可以在自己的属性中包含其它元素。创建一个元素的成本很低,一旦元素被创建之后,就不再发生变化。元素并不是一个真正的实例,而是一种用来告诉 React 你希望哪些东西显示在页面中的方式。 一个描述组件的元素也属于元素的范畴,就像一个描述 DOM 节点的元素一样,它们可以互相嵌套混搭使用。
    React 组件可以用好几种方式声明,可以是一个包含 render() 方法的类,也可以是一个简单的函数,不管怎么样,它都是以属性作为输入,返回元素树作为输出。函数式组件没有实例,类组件才有。
    除此之外,还有几点区别要注意:

    • this.props.childrenthis.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示==组件的所有子节点==。在JSX中,被元素嵌套的元素会以属性children的方式传入该元素的组件。当仅嵌套一个元素时,children是一个React元素,当嵌套多个元素时,children是一个React元素的数组(可以使用React.Children.map来遍历)。可以直接把children写入JSX中,但如果需要传入新属性,就要用到React.cloneElement()来构建新的元素。

      // map方法对于嵌套一个元素,多个元素或者没有嵌套都适用
      render() {
          var child = this.props.children
          return (
          {/*代码中嵌套多个HTML标签,需要使用一个标签元素包裹它,
          所以此处最外层的div是必须的!!*/}
              <div>
                  {React.Children.map(this.props.children, function(child){
                      return child;
                  })}
              </div>
          );
      }
      // 仅仅适用于只嵌套一个React元素
      render() {
          var child = this.props.children
          return <div>{ React.cloneElement(child, {tip: 'right way'}) }</div>
      }

      这里需要注意,this.props.children的值有三种可能:如果当前组件没有子节点,它就是undefined;如果有一个子节点,数据类型是object;如果有多个子节点,数据类型就是array。所以,处理 this.props.children 的时候要小心。React提供一个工具方法React.Children来处理this.props.children。我们可以用React.Children.map来遍历子节点,而不用担心this.props.children的数据类型是undefined还是object

    • 用户组件:有时组件可以让用户以属性的方式传入自定义的组件,来提升组件的灵活性。这个属性传入的就应该是React元素,而非React组件。使用React元素可以让用户传入自定义组件的同时,为组件添加属性。同样,可以使用React.cloneElement()为自定义组件添加更多属性,或替换子元素。

      <MyComponent tick={
          <UserComponent tip="OK"/>
      }/>
    • 在JSX中的渲染
      React可以渲染React元素或React组件。要渲染HTML标签,只需要在JSX里使用小写字母开头的标签名。

      var myDivELement = <div className="foo" />;
      ReactDOM.render(myDivElement, document.getELementById('example'));

      要渲染React组件,只需创建一个大写字母开头的本地变量。

      var MyComponent = React.createClass({/*...*/});
      var myElement = <MyComponent someProperty={true} />;
      ReactDOM.render(myElement, document.getElementById('example'));

      React的JSX使用大小写的约定来区分本地组件的类和HTML标签。

三、感想与注意点

  1. 由于JSX就是JavaScript,一些标识符像class和for不建议作为XML属性名。作为替代,React DOM使用className和htmlFor来做对应的属性。
  2. React通过元素来描述组件的DOM节点或者子组件,从而达到切分组件的目的,降低组件的复杂度,并且使得组件更加易于解耦。组件实际上是元素树的封装,这也是React能够进行局部渲染的前提。

四、参考

[1] React教程
[2] React元素和组件的区别
[3] React 组件、元素以及实例
[4] React 入门实例教程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值