Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React半科普文 #27

Open
chyingp opened this issue Apr 9, 2015 · 0 comments
Open

React半科普文 #27

chyingp opened this issue Apr 9, 2015 · 0 comments

Comments

@chyingp
Copy link
Owner

chyingp commented Apr 9, 2015

什么是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 待填坑

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant