一、简介

React 是一个用于构建用户界面的 JavaScript

二、三个特点

  • 声明式
    • 比较轻松创建交互 UI,为每个状态创建简洁的视图,数据变动时 React 会高效地去更新并渲染组件
    • 代码更加可预测,更容易调试
  • 组件化
    • 组件有它们的状态,将它们组合能够构建复杂的 UI
    • 组件使用 JavaScript 编写,所以很容易传递数据并保持状态与 DOM 分离
  • 一次学习,跨平台编写
    • 很容易引入 React 开发新功能
    • 可以使用 Node 进行服务器渲染,可以使用 React Native 开发原生移动应用

三、看一看 JSX

1. 简单组件

  • Rect 组件使用 render() 方法接受数据并返回需要展示的内容
  • 在示例中这种类似 XML 的写法被称为 JSX
  • 被传入的数据可在组件中通过 this.propsrender() 访问 ```jsx class HelloMessage extends React.Component { render() { return (
    1. <div>
    2. Hello {this.props.name}
    3. </div>
    ); } }

ReactDOM.render( , document.getElementById(‘hello-example’) );

  1. 对应的原生 JavaScript 代码
  2. ```javascript
  3. class HelloMessage extends React.Component {
  4. render() {
  5. return React.createElement(
  6. "div",
  7. null,
  8. "Hello ",
  9. this.props.name
  10. );
  11. }
  12. }
  13. ReactDOM.render(
  14. React.createElement(HelloMessage, { name: "Taylor" }),
  15. document.getElementById('hello-example')
  16. );

2. 有状态组件

  • 组件还可以维护其内部的状态(通过 this.state 访问)
  • 当组件的状态数据改变时,组件会再次调用 render() 方法更新对应的标记 ```jsx class Timer extends React.Component { constructor(props) { super(props); this.state = { seconds: 0 }; }

    tick() { this.setState(state => ({

    1. seconds: state.seconds + 1

    })); }

    componentDidMount() { this.interval = setInterval(() => this.tick(), 1000); }

    componentWillUnmount() { clearInterval(this.interval); }

    render() { return (

    1. <div>
    2. Seconds: {this.state.seconds}
    3. </div>

    ); } }

ReactDOM.render( , document.getElementById(‘timer-example’) );

  1. ```javascript
  2. class Timer extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = { seconds: 0 };
  6. }
  7. tick() {
  8. this.setState(state => ({
  9. seconds: state.seconds + 1
  10. }));
  11. }
  12. componentDidMount() {
  13. this.interval = setInterval(() => this.tick(), 1000);
  14. }
  15. componentWillUnmount() {
  16. clearInterval(this.interval);
  17. }
  18. render() {
  19. return React.createElement(
  20. 'div',
  21. null,
  22. 'Seconds: ',
  23. this.state.seconds
  24. );
  25. }
  26. }
  27. ReactDOM.render(
  28. React.createElement(Timer, null),
  29. document.getElementById('timer-example')
  30. );

3. 应用

  • 使用 propsstate 我们可以创建一个简易的 Todo 应用
  • 示例中使用 state 来保存现有的待办事项列表及用户的输入
  • 尽管时间处理器看似被内联地渲染,但它们其实会被事件委托进行收集和调用 ```jsx class TodoApp extends React.Component { constructor(props) { super(props); this.state = { items: [], text: ‘’ }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); }

    render() { return (

    1. <div>
    2. <h3>TODO</h3>
    3. <TodoList items={this.state.items} />
    4. <form onSubmit={this.handleSubmit}>
    5. <label htmlFor="new-todo">
    6. What needs to be done?
    7. </label>
    8. <input
    9. id="new-todo"
    10. onChange={this.handleChange}
    11. value={this.state.text}
    12. />
    13. <button>
    14. Add #{this.state.items.length + 1}
    15. </button>
    16. </form>
    17. </div>

    ); }

    handleChange(e) { this.setState({ text: e.target.value }); }

    handleSubmit(e) { e.preventDefault(); if (this.state.text.length === 0) {

    1. return;

    } const newItem = {

    1. text: this.state.text,
    2. id: Date.now()

    }; this.setState(state => ({

    1. items: state.items.concat(newItem),
    2. text: ''

    })); } }

class TodoList extends React.Component { render() { return (

    {this.props.items.map(item => (
  • {item.text}
  • ))}
); } }

ReactDOM.render( , document.getElementById(‘todos-example’) );

  1. ```javascript
  2. class TodoApp extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = { items: [], text: '' };
  6. this.handleChange = this.handleChange.bind(this);
  7. this.handleSubmit = this.handleSubmit.bind(this);
  8. }
  9. render() {
  10. return React.createElement(
  11. "div",
  12. null,
  13. React.createElement(
  14. "h3",
  15. null,
  16. "TODO"
  17. ),
  18. React.createElement(TodoList, { items: this.state.items }),
  19. React.createElement(
  20. "form",
  21. { onSubmit: this.handleSubmit },
  22. React.createElement(
  23. "label",
  24. { htmlFor: "new-todo" },
  25. "What needs to be done?"
  26. ),
  27. React.createElement("input", {
  28. id: "new-todo",
  29. onChange: this.handleChange,
  30. value: this.state.text
  31. }),
  32. React.createElement(
  33. "button",
  34. null,
  35. "Add #",
  36. this.state.items.length + 1
  37. )
  38. )
  39. );
  40. }
  41. handleChange(e) {
  42. this.setState({ text: e.target.value });
  43. }
  44. handleSubmit(e) {
  45. e.preventDefault();
  46. if (this.state.text.length === 0) {
  47. return;
  48. }
  49. const newItem = {
  50. text: this.state.text,
  51. id: Date.now()
  52. };
  53. this.setState(state => ({
  54. items: state.items.concat(newItem),
  55. text: ''
  56. }));
  57. }
  58. }
  59. class TodoList extends React.Component {
  60. render() {
  61. return React.createElement(
  62. "ul",
  63. null,
  64. this.props.items.map(item => React.createElement(
  65. "li",
  66. { key: item.id },
  67. item.text
  68. ))
  69. );
  70. }
  71. }
  72. ReactDOM.render(
  73. React.createElement(TodoApp, null),
  74. document.getElementById('todos-example')
  75. );

4. 在组件中使用外部插件

  • React 结合其他框架或库一起使用
  • 示例中使用一个名为 remarkable 的外部 Markdown 库,它可以实时转换 <textarea> 里的内容 ```jsx class MarkdownEditor extends React.Component { constructor(props) { super(props); this.md = new Remarkable(); this.handleChange = this.handleChange.bind(this); this.state = { value: ‘Hello, world!’ }; }

    handleChange(e) { this.setState({ value: e.target.value }); }

    getRawMarkup() { return { __html: this.md.render(this.state.value) }; }

    render() { return (

    1. <div className="MarkdownEditor">
    2. <h3>Input</h3>
    3. <label htmlFor="markdown-content">
    4. Enter some markdown
    5. </label>
    6. <textarea
    7. id="markdown-content"
    8. onChange={this.handleChange}
    9. defaultValue={this.state.value}
    10. />
    11. <h3>Output</h3>
    12. <div
    13. className="content"
    14. dangerouslySetInnerHTML={this.getRawMarkup()}
    15. />
    16. </div>

    ); } }

ReactDOM.render( , document.getElementById(‘markdown-example’) );

  1. ```javascript
  2. class MarkdownEditor extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.md = new Remarkable();
  6. this.handleChange = this.handleChange.bind(this);
  7. this.state = { value: 'Hello, **world**!' };
  8. }
  9. handleChange(e) {
  10. this.setState({ value: e.target.value });
  11. }
  12. getRawMarkup() {
  13. return { __html: this.md.render(this.state.value) };
  14. }
  15. render() {
  16. return React.createElement(
  17. "div",
  18. { className: "MarkdownEditor" },
  19. React.createElement(
  20. "h3",
  21. null,
  22. "Input"
  23. ),
  24. React.createElement(
  25. "label",
  26. { htmlFor: "markdown-content" },
  27. "Enter some markdown"
  28. ),
  29. React.createElement("textarea", {
  30. id: "markdown-content",
  31. onChange: this.handleChange,
  32. defaultValue: this.state.value
  33. }),
  34. React.createElement(
  35. "h3",
  36. null,
  37. "Output"
  38. ),
  39. React.createElement("div", {
  40. className: "content",
  41. dangerouslySetInnerHTML: this.getRawMarkup()
  42. })
  43. );
  44. }
  45. }
  46. ReactDOM.render(React.createElement(MarkdownEditor, null), document.getElementById('markdown-example'));

四、参考链接

React 简介:https://reactjs.org/