翻译--https://github.com/ruanyf/react-demos/blob/master/README.md

此文章为阮一峰大神写的关于react的DEMOreact的DEMO, 建议看英文版
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
此项目是一个针对reactJS 简单DEMO的集合.
有道是大繁若简, 在没有样式的前提下, DEMO被写出来; 同样, 你会发现, 在跟随这些DEMO学习react的过程中, 基本上没有什么难点.

如何使用

首先用git把项目拷贝到你的磁盘上

$ git clone git@github.com:ruanyf/react-demos.git

接下来就可以运行你的demo啦

HTML Template

<!DOCTYPE html>
<html>
  <head>
    <script src="../build/react.js"></script>
    <script src="../build/react-dom.js"></script>
    <script src="../build/browser.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script type="text/babel">

      // ** Our code goes here! **

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

Demo01: Render JSX

demo / source

React中的模板语法是继承自 JSX. 在JSX语法中, 将HTML标签直接写到JS代码中, 这是被允许的. ReactDOM.render() 是一个可以将JSX语法转化为HTML标签的方法, 并且在特定的DOM节点中渲染出来.

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

需要注意的是: 你必须要用 <script type="text/babel"> 来指明你写的是JSX语法的代码, 除此之外你还要引入 browser.min.js, 它是Babel的 browser version , 能够在浏览器中真正地呈现这种转化.
在v0.14以前, React用 JSTransform.js 来转换 <script type="text/jsx"> 语法. 不过, 它早已经被摈弃了 (更多信息).

Demo02: Use JavaScript in JSX

demo / source

你也可以在JSX使用原生JavaScript. JSX是把三角括号 (<) 作为HTML语法的开始符, 并且把花括号 ({) 当做JS语法的开始符.

var names = ['Alice', 'Emily', 'Kate'];

ReactDOM.render(
  <div>
  {
    names.map(function (name) {
      return <div>Hello, {name}!</div>
    })
  }
  </div>,
  document.getElementById('example')
);

Demo03: Use array in JSX

demo / source

如果有一个JS变量是数组, JSX语法会遍历截取该数组中的所有成员.

var arr = [
  <h1>Hello world!</h1>,
  <h2>React is awesome</h2>,
];
ReactDOM.render(
  <div>{arr}</div>,
  document.getElementById('example')
);

Demo04: Define a component

demo / source

React.createClass() 创建一个组件类, 这个组件类执行一个渲染方法, 这个渲染方法是返回这个类的实例化组件. 获取一个实例化对象, 不需要使用 new , 仅仅把它当做一个普通的HTML标签即可.

var HelloMessage = React.createClass({
  render: function() {
    return <h1>Hello {this.props.name}</h1>;
  }
});

ReactDOM.render(
  <HelloMessage name="John" />,
  document.getElementById('example')
);

组件也会有属性, 并且可以通过 this.props.[attribute] 来获取到这些属性, 就像 <HelloMessage name="John" />this.props.name 是 John.

请记住: 组件名字的首字母必须大写, 否则React就会抛出错误. 例如: HelloMessage 是可以作为一个组建的名字, 但是 helloMessage 不行. 除此之外, 一个React组件只能有一个直属子节点(据我猜想, 应该是JSX语法只能解析到第一个HTML标签的结束符, 自此终止).

// wrong
var HelloMessage = React.createClass({
  render: function() {
    return <h1>
      Hello {this.props.name}
    </h1><p>
      some text
    </p>;
  }
});

// correct
var HelloMessage = React.createClass({
  render: function() {
    return <div>
      <h1>Hello {this.props.name}</h1>
      <p>some text</p>
    </div>;
  }
});

Demo05: this.props.children

demo / source

React 使用 this.props.children 方法来获取组件的孩子节点.

var NotesList = React.createClass({
  render: function() {
    return (
      <ol>
      {
        React.Children.map(this.props.children, function (child) {
          return <li>{child}</li>;
        })
      }
      </ol>
    );
  }
});

ReactDOM.render(
  <NotesList>
    <span>hello</span>
    <span>world</span>
  </NotesList>,
  document.getElementById('example')
);

注意下, this.props.children 的值有三种可能结果.

  1. 如果组件没有孩子节点, 该值为undefined;
  2. 如果只有一个孩子节点, 该值为object;
  3. 如果有多个孩子节点, array.

所以在操作这个方法时, 一定要小心.

React 也给了我们一个万用方法 React.Children , 用来处理 this.props.children 方法奇怪的数据结构. 你可以用 React.Children.map 来迭代 this.props.children 而不用担心他的数据类型到底是undefined 还是 object. 查看官方文档 获取更多与React.Children相关的提示.

Demo06: PropTypes

demo / source

在React中, 组件有许多被叫做”props”的属性, 这些属性可以是任何类型.

有时候你需要使用一种方式来校验这些”props”. 此外, 你也并不想要用户在你的组件随意输入一些值.

React 就有一种专门针对于此的解决方案, 它就是”PropTypes”.

var MyTitle = React.createClass({
  propTypes: {
    title: React.PropTypes.string.isRequired,
  },

  render: function() {
     return <h1> {this.props.title} </h1>;
   }
});

组件MyTitle上有一个叫title的props. PropTypes 告诉 React 该组件的title是必填的, 并且它的值必须是一个string类型的.

如果我们尝试把title的值给成数值类型的, 如下:

var data = 123;

ReactDOM.render(
  <MyTitle title={data} />,
  document.getElementById('example')
);

那么, 这个props无法通过校验, 并且console面板会给你一个错误提示.

Warning: Failed propType: Invalid prop `title` of type `number` supplied to `MyTitle`, expected `string`.

看看 官方文档 寻求更多关于PropTypes的解释.

P.S. 如果你想给props一个默认值, 请使用getDefaultProps()这个方法.

var MyTitle = React.createClass({
  getDefaultProps : function () {
    return {
      title : 'Hello World'
    };
  },

  render: function() {
     return <h1> {this.props.title} </h1>;
   }
});

ReactDOM.render(
  <MyTitle />,
  document.getElementById('example')
);

Demo07: Finding a DOM node

demo / source

有时你需要在组件中引用一个DOM节点. 而React则给出了 ref 属性以便于查找节点.

var MyComponent = React.createClass({
  handleClick: function() {
    this.refs.myTextInput.focus();
  },
  render: function() {
    return (
      <div>
        <input type="text" ref="myTextInput" />
        <input type="button" value="Focus the text input" onClick={this.handleClick} />
      </div>
    );
  }
});

ReactDOM.render(
  <MyComponent />,
  document.getElementById('example')
);

被联想的DOM节点应该有一个ref 属性, 并且 this.refs.[refName] 会返回对应的DOM节点. 请注意: 只有在这个组件嵌入到DOM后, 你才能做这些事情, 否则只能得到 null.

Demo08: this.state

demo / source

React 把组件看成状态机, 并且使用 this.state 来获取组件状态, getInitialState() 这个方法就是用来初始化 this.state (初始化操作在组件绑定到DOM之前就被执行了), this.setState() 这个方法是用来更新 this.state 并且重新渲染组件.

var LikeButton = React.createClass({
  getInitialState: function() {
    return {liked: false};
  },
  handleClick: function(event) {
    this.setState({liked: !this.state.liked});
  },
  render: function() {
    var text = this.state.liked ? 'like' : 'haven\'t liked';
    return (
      <p onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </p>
    );
  }
});

ReactDOM.render(
  <LikeButton />,
  document.getElementById('example')
);

你也可以使用组件属性去注册事件函数, 就像 onClick, onKeyDown, onCopy 等等. 官方文档有所有的支持事件.

Demo09: Form

demo / source

根据React的设计理念, this.state 不仅描绘了组件的状态, 还会随着人机交互而改变组件; 同时, this.props 也陈述了组件的特性是稳定且不易改变的.

因此, Since that, 表单组件的属性值, 例如 <input>, <textarea>, and <option> 等等, 都是不会被任何用户输入所改变. 作为对用户输入的反馈, 如果想获取甚至对属性值进行更改, 你就要用到onChange事件.

var Input = React.createClass({
  getInitialState: function() {
    return {value: 'Hello!'};
  },
  handleChange: function(event) {
    this.setState({value: event.target.value});
  },
  render: function () {
    var value = this.state.value;
    return (
      <div>
        <input type="text" value={value} onChange={this.handleChange} />
        <p>{value}</p>
      </div>
    );
  }
});

ReactDOM.render(<Input/>, document.getElementById('example'));

更多信息请参考官方文档.

Demo10: Component Lifecycle

demo / source

组件生命周期分为三个部分:

  1. 绑定中(插入到DOM中)
  2. 更新中(重新渲染)
  3. 注销中(解除绑定)

React向三种状态都提供了钩子函数. will方法在某些事件发生之前执行,did 方法在事件后执行.

var Hello = React.createClass({
  getInitialState: function () {
    return {
      opacity: 1.0
    };
  },

  componentDidMount: function () {
    this.timer = setInterval(function () {
      var opacity = this.state.opacity;
      opacity -= .05;
      if (opacity < 0.1) {
        opacity = 1.0;
      }
      this.setState({
        opacity: opacity
      });
    }.bind(this), 100);
  },

  render: function () {
    return (
      <div style={{opacity: this.state.opacity}}>
        Hello {this.props.name}
      </div>
    );
  }
});

ReactDOM.render(
  <Hello name="world"/>,
  document.getElementById('example')
);

接下来是 一整套生命周期的方法.

  • componentWillMount(): 只会执行一次, 在初始化渲染之前. 在这里关联事件监听是最好的. this.setState 在这里不起作用.

  • componentDidMount(): 只会执行一次, 在初始化渲染之后, 可以使用this.getDOMNode()—我试过这个方法(getDOMNode()), 无论怎样都调不起来, 也不知道为什么.

  • componentWillUpdate(object nextProps, object nextState): 在组件更新并已经绑定到DOM之后执行. 可以使用this.getDOMNode() 进行更新操作.

  • componentDidUpdate(object prevProps, object prevState): 在组件更新并刷新到DOM后立即调用. 这个方法不是继承自初始化的render方法. 当组件被更新后, 可以凭借这个方法操作DOM.

  • componentWillUnmount(): 当组件从DOM被解绑之前立即执行. 在这儿可以清楚事件监听函数甚至全部清除.

  • componentWillReceiveProps(object nextProps): 当组件正在新建新的props被执行. 依靠这些props, 你可能想用this.setState .

  • shouldComponentUpdate(object nextProps, object nextState): 当收到新的props或者state之前被执行. 如果你知道一个更新没有必要的时候, 会return false.

Demo11: Ajax

demo / source

从服务器或者接口上如何获取到数据? 解决方案就是: 在componentDidMount函数中, 使用Ajax去抓取数据. 当收到服务器响应报文之后, 把数据用this.setState()存储下来, 并根据相应状态去重新渲染UI.

var UserGist = React.createClass({
  getInitialState: function() {
    return {
      username: '',
      lastGistUrl: ''
    };
  },

  componentDidMount: function() {
    $.get(this.props.source, function(result) {
      var lastGist = result[0];
      if (this.isMounted()) {
        this.setState({
          username: lastGist.owner.login,
          lastGistUrl: lastGist.html_url
        });
      }
    }.bind(this));
  },

  render: function() {
    return (
      <div>
        {this.state.username}'s last gist is
        <a href={this.state.lastGistUrl}>here</a>.
      </div>
    );
  }
});

ReactDOM.render(
  <UserGist source="https://api.github.com/users/octocat/gists" />,
  document.getElementById('example')
);

Demo12: Display value from a Promise

demo / source

这个demo得益于Nat Pryce 的文章“Higher Order React Components”所写.

如果一个React组件的数据被异步接收了, 我们也可以把Promise对象当做组件的属性, 如下所示:

ReactDOM.render(
  <RepoList
    promise={$.getJSON('https://api.github.com/search/repositories?q=javascript&sort=stars')}
  />,
  document.getElementById('example')
);

上面的代码是从 Github’s API获取数据, 并且RepoList 组件会获取到一个Promise对象作为自身属性.

现在, 当promise被阻塞时, 组件会展现一个loading标志. 当promise被成功解析, 组件会展现一个仓库信息的列表. 如果promise处于拒绝态, 组件会返回错误信息.

var RepoList = React.createClass({
  getInitialState: function() {
    return { loading: true, error: null, data: null};
  },

  componentDidMount() {
    this.props.promise.then(
      value => this.setState({loading: false, data: value}),
      error => this.setState({loading: false, error: error}));
  },

  render: function() {
    if (this.state.loading) {
      return <span>Loading...</span>;
    }
    else if (this.state.error !== null) {
      return <span>Error: {this.state.error.message}</span>;
    }
    else {
      var repos = this.state.data.items;
      var repoList = repos.map(function (repo) {
        return (
          <li>
            <a href={repo.html_url}>{repo.name}</a> ({repo.stargazers_count} stars) <br/> {repo.description}
          </li>
        );
      });
      return (
        <main>
          <h1>Most Popular JavaScript Projects in Github</h1>
          <ol>{repoList}</ol>
        </main>
      );
    }
  }
});

demo13 根本跑不起来, 除非找梯子FQ.

猜你喜欢

转载自blog.csdn.net/gong_zhe_511/article/details/72869654