chyingp/blog

React半科普文

Opened this issue · 0 comments

什么是React

以下是官方定义,反正我是没看懂。google了下,大家都称之“前端UI开发框架”,勉强这么叫着吧。可以看下这篇文章对react的介绍,本文更多的是覆盖react的入门实践。

A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES

本文提到的例子可以在这里找到:github链接

getting started

getting-started.html里的例子比较简单,首先引入 react.jsJSXTransformer.js,然后通过 React.render() 方法即可。语法细节什么的可以先不管。

需要注意的点是,最后一段script标签,上面声明了 type="text/jsx",也就是说并不是通常的直接解析执行的脚本,JSXTransformer.js 会对其进行预编译后再执行。

<!DOCTYPE html>
<html>
<head>
    <title>getting started</title>
    <script src="build/react.js"></script>
    <script src="build/JSXTransformer.js"></script>
</head>
<body>

    <div id="example"></div>
    <script type="text/jsx">
      React.render(
        <h1>Hello, world!</h1>,
        document.getElementById('example')
      );
    </script>
</body>
</html>

好了,看下效果吧。

Alt text

文件分离

根据以往养成的好习惯,直觉的感觉到,这里应该将组件的定义跟 html 页面分离,不然以后页面肯定就乱糟糟了。示例请查看 separate-file.html

修改后的html文件,瞬间清爽很多。同样需要注意 type="text/jsx"

<!DOCTYPE html>
<html>
<head>
    <title>demo</title>
    <script src="build/react.js"></script>
    <script src="build/JSXTransformer.js"></script>
</head>
<body>

    <div id="example"></div>

    <script type="text/jsx" src="js/helloworld.js"></script>
</body>
</html>

处理后的 helloworld.js,其实内容一点变化都没有

React.render(
  <h1>Hello, world!</h1>,
  document.getElementById('example')
);

好了,查看效果。双击 separate-file.html,这时看到页面是空白的,同时控制台还有错误信息。

Alt text

肿么办呢?相信有经验的兄弟知道咋整了。这里偷个懒,直接用fis起个本地服务器。在2015.04.09-react/ 根路径下运行

fis server start
fis release

然后访问 http://127.0.0.1:8080/separate-file.html。well done

Alt text

Server端编译

之前提到,JSXTransformer.js 会对标志 type="text/jsx" 的script 进行预编译后再执行,那么在浏览器端很可能就会遇到性能问题(没验证过)。React 的开发团队当然也考虑到这个问题了,于是也提供了server端的编译工具。

请查看 server-build-without-transform.html 。这里我们已经把 JSXTransformer.js 的依赖去掉。相对应的,我们需要在server端做一定的编译工作。

<!DOCTYPE html>
<html>
<head>
    <title>demo</title>
    <script src="build/react.js"></script>
    <!-- <script src="build/JSXTransformer.js"></script> -->
</head>
<body>

    <div id="example"></div>

    <script src="js-build/helloworld.js"></script>
</body>
</html>

挺简单的,安装 react-tools,然后运行相应命令即可

npm install -g react-tools

jsx --watch js/ js-build/

可以看到,js/helloworld.js 已经被编译成 js-build/helloworld.js。我们看下编译后的文件
Alt text

编译后的文件。可以看到,都是浏览器可以理解的语法。你也可以一开始就这样编写,不过保证你会抓狂。

React.render(
  React.createElement("h1", null, "Hello, world!"),
  document.getElementById('example')
);

定义一个组件

下面定义一个极简的_组件_ 来做说明,示例代码可以查看 define-a-component.html。从代码可以看到:

  1. 通过 React.createClass() 来定义一个组件,该方法需要定义 render 方法来返回组件对应的 dom 结构
  2. 通过 React.render() 来调用组件。该方法传入两个参数,分别是 对应的组件,父级节点。
<!DOCTYPE html>
<html>
<head>
    <title>getting started</title>
    <script src="build/react.js"></script>
    <script src="build/JSXTransformer.js"></script>
</head>
<body>

    <div id="example"></div>
    <script type="text/jsx">
      var HelloComponent = React.createClass({
            render: function(){
                return (
                    <div>
                        <h1>Hello World</h1>
                        <p>I am Hello World Component</p>
                    </div>                  
                );
            }
        });

      React.render(
        <HelloComponent />,
        document.getElementById('example')
      );
    </script>
</body>
</html>

示例效果如下:
Alt text

刚接触React组件定义的同学,可能会踩中下面的坑。比如把前面的组件定义改成。区别在于去掉了组件最外层的包裹节点 <div>

      var HelloComponent = React.createClass({
            render: function(){
                return (
                        <h1>Hello World</h1>
                        <p>I am Hello World Component</p>
                );
            }
        });

再次访问 http://127.0.0.1:8080/define-a-component.html 会有如下错误提示。错误信息比较明确了,不再赘述,乖乖加上包裹节点就好了

Alt text

使用property

在定义一个组件时,我们通常会暴露一定的配置项,提高组件的可复用性。这里简单示范下如何实现,具体代码可查看 using-properties.html

关键代码如下,还是比较直观的。使用组件时,就跟使用浏览器内置的组件那样给属性赋值。在组件定义的内部代码实现中,通过 this.props.xx 来取到对应的值即可。

    <script type="text/jsx">    

        var HelloComponent = React.createClass({
            render: function(){
                return (
                    <div>
                        <h1>Title is: {this.props.title}</h1>
                        <p>Content is: {this.props.content}</p>
                    </div>                  
                );
            }
        });

        React.render(
            <HelloComponent title="hello" content="world" />,
            document.getElementById('example')
        );

    </script>

组件嵌套

推荐看下 Thinking in React 这篇文章。要实现文中提到的 搭积木式的开发模式,组件的嵌套使用是必不可少的。下面示范下,具体代码查看 compose-components.html

<!DOCTYPE html>
<html>
<head>
    <title>demo</title>
    <script src="build/react.js"></script>
    <script src="build/JSXTransformer.js"></script>
</head>
<body>

    <div id="example"></div>

    <script type="text/jsx">

        var Title = React.createClass({
            render: function(){
                return (
                    <h1>This is Title</h1>
                );
            }
        });

        var Content = React.createClass({
            render: function(){
                return (
                    <p>This is Content</p>
                );
            }
        });

        // Article组件包含了 Title、Content 组件
        var Article = React.createClass({
            render: function() {
                return (
                    <div class="article">
                        <Title />
                        <Content />
                    </div>
                );              
            }
        });

        React.render(
          <Article />,
          document.getElementById('example')
        );
    </script>
</body>
</html>

组件更新

在React的体系中,组件的UI会随着组件状态的变化(state)进行更新。从围观的代码层面来说,是 setState() 方法被调用时,组件的UI会刷新。简单例子可以参考 update-if-state-chagne.html。例子可能不是很恰当,就表达那么个意思。

其中有两个方法简单介绍下:

  1. getInitialState:返回组件的初始状态。
  2. componentDidMount:当组件渲染完成后调用的方法。

ps:React的组件更新机制是最大的亮点之一。看似全量刷新,实际内部是基于Virtual DOM机制的局部刷新,开发者无需再编写大量的重复代码来更新局部的dom节点。

Virtual DOM以及局部刷新实现机制,这里就不展开了,可参考 http://calendar.perfplanet.com/2013/diff/

<!DOCTYPE html>
<html>
<head>
    <title>demo</title>
    <script src="build/react.js"></script>
    <script src="build/JSXTransformer.js"></script>
</head>
<body>

    <div id="example"></div>
    <script type="text/jsx">        

        var HelloComponent = React.createClass({
            getInitialState: function(){
                return {
                    title: 'title1',
                    content: 'content1'
                };
            },
            componentDidMount: function(){
                var that = this;
                setTimeout(function(){
                    that.setState({
                        title:'title2', 
                        content:'content2'
                    });
                }, 2000);
            },
            render: function(){
                return (
                    <div>
                        <h1>Title is: {this.state.title}</h1>
                        <p>Content is: {this.state.content}</p>
                    </div>                  
                );
            }
        });


        React.render(
            <HelloComponent />,
            document.getElementById('example')
        );

    </script>
</body>
</html>

访问 Alt text ,刚打开时,展示如下

Alt text

2000ms后,界面刷新。

Alt text

Virtual DOM

已经有人写过了,这里直接附上参考链接:http://calendar.perfplanet.com/2013/diff/

react native

TODO 待填坑