react.js学习笔记02

本文详细介绍了React的基础知识,包括HelloWorld、JSX语法、组件化开发、属性(props)、状态(state)、事件处理、生命周期方法以及服务器端渲染。通过实例展示了如何创建自定义组件、处理用户输入、利用AJAX请求数据,并讨论了受控组件和键(key)的重要性。此外,还探讨了React在服务器端渲染的优势和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

01_HelloWorld

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>01_HelloWorld</title>
</head>
<body>
<!--
1. 相关js库
  react.js: React的核心库
  react-dom.js: 提供操作DOM的扩展库
  babel.min.js: 解析JSX语法代码转为纯JS语法代码的库
2. 在页面中导入js
  <script src="../js/react.js"></script>
  <script src="../js/react-dom.js"></script>
  <script src="../js/babel.min.js"></script>
3. 编码
  <div id="example"></div>
  <script type="text/babel"> //必须用babel
    ReactDOM.render(<h1>Hello, React!</h1>,
          document.getElementById('example'));
  </script>
-->

<div id="demo"></div>

<script type="text/javascript" src="../js/react.js"></script>
<script type="text/javascript" src="../js/react-dom.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
  //页面中的真实容器元素
  var containDiv = document.getElementById('demo');
  //react的虚拟DOM对象
  var vDom = <div id="demo">Hello, React!</div>;  //不是字符串, 不能加引号
  //将虚拟DOM对象渲染到页面元素中
  ReactDOM.render(vDom, containDiv);

  //页面结果: <div id="demo"><div id="demo">Hello, React!</div></div>
</script>

</body>
</html>

02_JSX

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>02_JSX_DEMO</title>
</head>
<body>
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>
<hr>

<div id="example1"></div>
<div id="example2"></div>

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>

<script type="text/babel">
  /*
   功能: 动态展示列表数据
   */
  /*
   技术点:
   1). 使用JSX创建虚拟DOM
   2). React能自动遍历显示数组中所有的元素
   3). array.map()的使用
   */

  var names = ['Tom2', 'Jack2', 'Bob2'];

  ReactDOM.render(
    <ul>
      {
        names.map(function (item, index) {
          return <li key={index}>{item}</li>;
        })
      }
    </ul>,
    document.getElementById('example1')
  );

  //简化编码(箭头函数)
  ReactDOM.render(
      <ul>{names.map((item, index)=><li key={index}>{item}</li>)}</ul>,
      document.getElementById('example2')
  );

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

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>02_JSX</title>
</head>
<body>
<!--
1. 虚拟DOM
  1). React提供了一些API来创建一种 `特别` 的一般js对象
    * var element = React.createElement('h1', {id:'myTitle'}, 'hello');
    * 上面创建的就是一个简单的虚拟DOM对象
  2). 虚拟DOM对象最终都会被React转换为真实的DOM
  3). 我们编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界面
2. JSX
  1). 全称: JavaScript XML
  2). react定义的一种类似于XML的JS扩展语法: XML+JS
  3). 作用: 用来创建react虚拟DOM(元素)对象
    * var ele = <h1>Hello JSX!</h1>;
    * 注意1: 它不是字符串, 也不是HTML/XML标签
    * 注意2: 它最终产生的就是一个JS对象
  4). 标签名任意: HTML标签或其它标签
  5). 标签属性任意: HTML标签属性或其它
  6). 基本语法规则
    * 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
    * 遇到以 { 开头的代码,以JS的语法解析: 标签中的js代码必须用{}包含
  7). babel.min.js的作用
    * 浏览器的js引擎是不能直接解析JSX语法代码的, 需要babel转译为纯JS的代码才能运行
    * 只要用了JSX,都要加上type="text/babel", 声明需要babel来处理
3. 渲染虚拟DOM(元素)
  1). 语法: ReactDOM.render(virtualDOM, containerDOM) :
  2). 作用: 将虚拟DOM元素渲染到真实容器DOM中显示
  3). 参数说明
    * 参数一: 纯js或jsx创建的虚拟dom对象
    * 参数二: 用来包含虚拟DOM元素的真实dom元素对象(一般是一个div)
4. 创建虚拟DOM的2种方式:
  1). 纯JS(一般不用):
    React.createElement('h1', {id:'myTitle'}, title)
  2). JSX:
    <h1 id='myTitle'>{title}</h1>
-->
<div id="example1"></div>
<div id="example2"></div>

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>

<script type="text/babel">

  //初始化动态数据
  var title = 'I Love you!';
  var myName = 'xfzhang';

  //创建虚拟dom : JSX
  var vDOM = <h1 id="myTitle" name={myName}>{title}</h1>;
  //将虚拟dom渲染中页面元素中
  ReactDOM.render(vDOM, document.getElementById('example1'));
</script>

<script type="text/javascript">
  var title = 'You Love me!';
  var myName = 'zhiyong';
  //创建虚拟dom : 纯JS(一般不用)
  var vDOM2 = React.createElement('h1', {id: 'myTitle2', name: myName.toUpperCase()}, title.toUpperCase());
  //将虚拟dom渲染中页面元素中
  ReactDOM.render(vDOM2, document.getElementById('example2'));
</script>

</body>
</html>

在这里插入图片描述

03_component_basic

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>03_component_basic</title>
</head>
<body>

<div id="example1"></div>
<div id="example2"></div>
<div id="example3"></div>

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>

<script type="text/babel">
/*
1. 自定义组件(Component) :
  1). 定义组件
    //方式1: 工厂(无状态)函数(最简洁, 推荐使用)
    function MyComponent1() {
      return <h1>自定义组件标题11111</h1>
    }
    //方式2: ES6类语法(复杂组件, 推荐使用)
    class MyComponent3 extends React.Component {
      render () {
        return <h1>自定义组件标题33333</h1>
      }
    }
    //方式3: ES5老语法(不推荐使用了)
    var MyComponent2 = React.createClass({
      render () {
        return <h1>自定义组件标题22222</h1>
      }
    })
  2). 渲染组件标签
    ReactDOM.render(<MyComponent/>, document.getElementById('example'));
2. 注意:
  1). 返回的组件类必须首字母大写
  2). 虚拟DOM元素必须只有一个根元素
  3). 虚拟DOM元素必须有结束标签
3. ReactDOM.render()渲染组件标签的基本流程
  1). React内部会创建组件实例对象
  2). 得到包含的虚拟DOM并解析为真实DOM
  3). 插入到指定的页面元素内部
*/
  //1. 定义组件
  //方式1: 工厂(无状态)函数(简单组件, 推荐使用)
  function MyComponent1() {
    return <h1>工厂(无状态)函数--->自定义组件标题11111</h1>;
  }
  //方式2: ES6类语法(复杂组件, 推荐使用)
  class MyComponent2 extends React.Component {
    render() {
      console.log(this, this instanceof MyComponent3);
      return <h1>ES6类语法--->自定义组件标题22222</h1>;
    }
  }
  //方式3: ES5老语法(不推荐使用了)
  var MyComponent3 = React.createClass({
    render() {
      return <h1>ES5老语法--->自定义组件标题3333</h1>;
    }
  });
  console.log(typeof MyComponent3);

  /************************************************************************/

  //2. 渲染组件标签
  ReactDOM.render(<MyComponent1/>, document.getElementById('example1'));
  ReactDOM.render(<MyComponent2/>, document.getElementById('example2'));
  ReactDOM.render(<MyComponent3/>, document.getElementById('example3'));
</script>
</body>
</html>

在这里插入图片描述

04_component_props

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>04_component_props</title>
</head>
<body>

<ul>
  <li>姓名: 张三</li>
  <li>性别: 女</li>
  <li>年龄: 23</li>
</ul>
<hr>

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

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>

<script type="text/babel">
  /*
  组件实对象3大属性之一: props属性
  1. 每个组件对象都会有props(properties的简写)属性
  2. 组件标签的所有属性都保存在props中
  3. 内部读取某个属性值: this.props.propertyName
  4. 作用: 通过标签属性从组件外向组件内传递数据(只读)
  5. 对props中的属性值进行类型限制和必要性限制
    Person.propTypes = {
      name: React.PropTypes.string.isRequired,
      age: React.PropTypes.number.isRequired
    }
  6. 扩展属性: 将对象的所有属性通过props传递
    <Person {...person}/>
  7. 默认属性值
    Person.defaultProps = {
      name: 'Mary'
    };
  8. 组件类的构造函数
    constructor (props) {
      super(props);
      console.log(props); // 查看所有属性
    }

  问题: 为什么要设计对prop会进行约束的语法?
  */

  /*
  需求: 自定义用来显示一个人员信息的组件, 效果如页面. 说明
    1). 如果性别没有指定, 默认为男
    2). 如果年龄没有指定, 默认为18
  */

  class Person extends React.Component {

    constructor(props) {
      super(props);
      console.log(props); //查看所有属性
    }

    render() {
      return (
        <ul>
          <li>姓名: {this.props.name}</li>
          <li>性别: {this.props.sex}</li>
          <li>年龄: {this.props.age}</li>
        </ul>
      );
    }
  }

  Person.propTypes = {
   name: React.PropTypes.string.isRequired,
   sex: React.PropTypes.string.isRequired,
   age: React.PropTypes.number.isRequired
  };

  Person.defaultProps = {
    sex: '男',
    age: 18
  };

  /************************************************************************/

  //初始化数据
  let person = {name: 'qicaiyun', sex: '女', age: 3};
  // person = { name: 'qicaiyun', sex: '女', age: "3" }; // 会抛出警告age不是number类型的

  //根据数据动态渲染组件标签
  /*ReactDOM.render(<Person name={person.name} age={person.age} sex={person.sex}/>,
      document.getElementById('example'));*/
  ReactDOM.render(<Person {...person}/>,
      document.getElementById('example'));

  const person2 = {name: 'kobe', sex: '女'};
  ReactDOM.render(<Person {...person2}/>, document.getElementById('example2'));
</script>
</body>
</html>

在这里插入图片描述

05_components_composing

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>05_components_composing</title>
</head>
<body>
<div>
  <h2>Welcome A!</h2>
  <h2>Welcome B!</h2>
  <h2>Welcome C!</h2>
</div>
<hr>

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

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>

<script type="text/babel">
  /*
   1. 拆分组件: 拆分界面, 抽取组件
     * 单个标题组件: Welcome
     * 应用组件: App
   2. 分析确定传递数据和数据类型
     * Welcome: props.name  string
     * App: props.names    array
   */

  //定义内部标题组件
  class Welcome extends React.Component {
    render() {
      return <h2>Welcome {this.props.name}!</h2>;
    }
  }
  Welcome.propTypes = {
    name: React.PropTypes.string.isRequired
  };
  //定义外部应用组件
  class App extends React.Component {
    render() {
      return (
        <div>
          {
            this.props.names.map(
              (name, index) => <Welcome name={name} key={index}/>
            )
          }
        </div>
      );
    }
  }
  App.propTypes = {
    names: React.PropTypes.array.isRequired
  };

  /**********************************************************/

  var names = ['Tom', 'Jack', "Bob"];
  ReactDOM.render(<App names={names}/>, document.getElementById('example'));
</script>
</body>
</html>

在这里插入图片描述

06_component_refs_event

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>07_component_refs</title>
</head>
<body>
  <input type="text">
  <button>提示输入数据</button>
  <input type="text" placeholder="失去焦点提示数据">
  <hr>

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

  <script src="../js/react.js"></script>
  <script src="../js/react-dom.js"></script>
  <script src="../js/babel.min.js"></script>
  <script type="text/babel">
    /*
1. 组件实例对象的3大属性之二: refs属性
  1). 组件内的标签都可以定义ref属性来标识自己
  2). 在组件中可以通过this.refs.refName来得到对应的真实DOM对象
  3). 作用: 用于操作指定的ref属性的dom元素对象(表单标签居多)
    * <input ref='username' />
    * this.refs.username //返回input对象
2. 事件处理
  1). 通过onXxx属性指定组件的事件处理函数(注意大小写)
    * React使用的是自定义(合成)事件, 而不是使用的DOM事件
    * React中的事件是通过委托方式处理的(委托给组件最外层的元素)
  2). 通过event.target得到发生事件的DOM元素对象
    <input onFocus={this.handleClick}/>
    handleFocus(event) {
      event.target  //返回input对象
    }
3. 强烈注意
  1). 组件内置的方法中的this为组件对象
  2). 在组件中自定义的方法中的this为null
    * 强制绑定this
    * 箭头函数(ES6模块化编码时才能使用)
4. 问题: 如何给一个函数强制指定内部的this?
    */

    /*
    需求: 自定义组件, 功能说明如下:
      1. 界面如果页面所示
      2. 点击按钮, 提示第一个输入框中的值
      3. 当第2个输入框失去焦点时, 提示这个输入框中的值
    */
    class RefsTest extends React.Component {
      constructor (props) {
       super(props);

        this.showMsg = this.showMsg.bind(this); // 强制给showMsg()绑定this(组件对象)
        this.handleBlur = this.handleBlur.bind(this);
      }

      showMsg() {
        // console.log(this); //this默认是null, 而不组件对象
        const input = this.refs.msg;
        alert(input.value);
      }

      handleBlur(event) {
        const input = event.target;
        alert(input.value);
      }

      render () {
        return (
          <div>
            <input type="text" ref="msg"/>
            <button onClick={this.showMsg}>提示输入数据</button>
            <input type="text" placeholder="失去焦点提示数据" onBlur={this.handleBlur}/>
          </div>
        );
      }
    }

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

在这里插入图片描述

07_component_state

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>07_component_state</title>
</head>
<body>

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

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
  /*
  组件实例对象3大属性之: state属性
    1). 组件被称为"状态机", 通过更新组件的状态值来更新对应的页面显示(重新渲染)
    2). 初始化状态:
      constructor (props) {
        super(props)
        this.state = {
          stateProp1 : value1,
          stateProp2 : value2
        }
      }
    3). 读取某个状态值
      this.state.statePropertyName
    4). 更新状态---->组件界面更新
      this.setState({
        stateProp1 : value1,
        stateProp2 : value2
      })
    5). 问题: 请区别一下组件的props和state属性?
  */

  /*
  需求: 自定义组件, 功能说明如下
    1. 显示h2标题, 初始文本为: 你喜欢我
    2. 点击标题更新为: 我喜欢你
  */
  class LikeMe extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        isLikeMe: false
      }
      this.switchLikeMe = this.switchLikeMe.bind(this)
    }

    switchLikeMe() {
      let isLikeMe = !this.state.isLikeMe;
      this.setState({isLikeMe})
    }

    render() {
      let text = this.state.isLikeMe ? '你喜欢我' : '我喜欢你'
      return <h2 onClick={this.switchLikeMe}>{text}</h2>
    }
  }

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

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


<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>07_state_demo</title>
</head>
<body>
<div>
  <h2>Simple TODO List</h2>
  <input type="text">
  <button>Add #4</button>
  <ul>
    <li>吃饭</li>
    <li>睡觉</li>
    <li>打豆豆</li>
  </ul>
</div>
<hr>

<div id="example">在此实现页面效果和功能</div>

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
  /*
   功能: 组件化实现此功能
   1. 界面显示如上所示
   2. 输入文本, 点击按钮显示到下面列表的首位, 并清除输入的文本
   */
  /*
   分解组件:
   列表: TodoList
   props: todos
   应用: App
   state: todos, inputTodo
   */
  /*
   问题: 完善功能
   1). 如果没有输入或输入的只是空格, 不添加到列表
   2). 如果输入的文本两边有空格, 去掉空格后添加
   */
  /*
   *  拆分组件:
   *  1、添加 todo的组件  AddTodo
   *  2、显示todo列表: TodoList
   *  3、 应用主组件: App
   *
   * */
  //定义AddTodo组件
  class AddTodo extends React.Component{
    constructor(props){
      super(props);
      this.add = this.add.bind(this);
    }
    add(){
      //获取输入的值
      let value = this.refs.newTodo.value;
      //console.log(typeof value);
      //判断输入的内容是否为空格
      if(!value.trim()){
        return
      }
      //将输入的值添加到 todoList中
      //console.log(value);
      this.props.add(value);
      this.refs.newTodo.value = '';
    }
    render(){
      return (
          <div>
            <input ref="newTodo" type="text" />
            <button onClick={this.add}>Add #{this.props.length}</button>
          </div>
      )
    }
  }
  //定义 TodoList 组件
  class TodoList extends React.Component{
    render(){
      let {todoList} = this.props;
      return (
          <ul>
            {
              todoList.map(function (item, index) {
                return <li key={index}>{item}</li>
              })
            }
          </ul>
      )
    }
  }
  class App extends React.Component{
    constructor(props){
      super(props);
      this.state = {
        todoList : ['吃饭', '睡觉', '打豆豆', '学习']
      };
      this.add = this.add.bind(this);
    }
    add(newTodo){
      console.log(newTodo);
      let todoList = this.state.todoList;
      todoList.unshift(newTodo);
      this.setState({todoList})
    }
    render(){
      let {todoList} = this.state;
      return (
          <div>
            <h2>Simple TODO List</h2>
            <AddTodo add={this.add} length={this.state.todoList.length}/>
            <TodoList todoList={todoList}/>
          </div>
      )
    }
  }

  //渲染组件
  ReactDOM.render(<App />, document.getElementById('example'));


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


在这里插入图片描述

08_component_controlled

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>09_form</title>
</head>
<body>

<input type="text" value="qicaiyun">
<p>qicaiyun</p>

<hr>

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

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
  /*
  受控组件
  1. React是一个单向数据流
  2. 但可以自定义双向数据流组件(受控组件)
  */
  /*
  功能: 自定义组件, 功能如下
    1. 界面如页面所示
    2. 初始数据显示为qicaiyun
    3. 输入数据时, 下面的数据同步变化
  */

  class TwoWay extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        msg: 'qicaiyun'
      }
      this.handleChange = this.handleChange.bind(this)
    }

    handleChange(event) {
      let msg = event.target.value
      this.setState({msg})
    }

    render() {
      return (
        <div>
          <input type="text" value={this.state.msg} onChange={this.handleChange}/>
          <p>{this.state.msg}</p>
        </div>
      )
    }
  }

  ReactDOM.render(<TwoWay/>, document.getElementById('example'))
</script>
</body>
</html>

在这里插入图片描述

09_component_lifecycle

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>10_ComponentLife</title>
</head>
<body>

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

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
  /*
1. 组件的三个生命周期状态:
  * Mount:插入真实 DOM
  * Update:被重新渲染
  * Unmount:被移出真实 DOM
2. React 为每个状态都提供了两种勾子(hook)函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用
  * componentWillMount()
  * componentDidMount() : 已插入真实DOM, 在render之后才会执行
  * componentWillUpdate(object nextProps, object nextState)
  * componentDidUpdate(object prevProps, object prevState)
  * componentWillUnmount()
3. 生命周期流程:
  1). 第一次初始化渲染显示: render()
    * constructor(): 创建对象初始化state
    * componentWillMount() : 将要插入回调
    * render() : 用于插入虚拟DOM回调
    * componentDidMount() : 已经插入回调
  2). 每次更新state: this.setSate()
    * componentWillUpdate() : 将要更新回调
    * render() : 更新(重新渲染)
    * componentDidUpdate() : 已经更新回调
  3). 删除组件
    * ReactDOM.unmountComponentAtNode(document.getElementById('example')) : 移除组件
    * componentWillUnmount() : 组件将要被移除回调
4.注意:
  * 一般会在componentDidMount()中: 开启监听, 发送ajax请求
  * 可以在componentWillUnmount()做一些收尾工作: 停止监听
  * 生命周期还有一个方法(后面需要时讲): componentWillReceiveProps
  */
  class LifeCycle extends React.Component {
    constructor(props) {
      super(props);
      console.log('constructor(): 创建组件对象');

      this.state = {
        date: new Date().toLocaleString()
      };
    }

    componentWillMount() {
      console.log('componentWillMount(): 将要初始挂载');
    }

    componentDidMount() {
      console.log('componentDidMount(): 已经初始挂载');

      this.intervalId = setInterval(
          () => {
            this.setState({date: new Date().toLocaleString()});
          },
          1000
      );
    }

    componentWillUpdate() {
      console.log('componentWillUpdate(): 将要进行state更新');
    }

    componentDidUpdate() {
      console.log('componentDidUpdate(): 已经更新');
    }

    componentWillUnmount() {
      console.log('componentWillUnmount(): 将要被移除');
      clearInterval(this.intervalId);
    }

    removeComp() {
      ReactDOM.unmountComponentAtNode(document.getElementById('example'));
    }

    render() {
      console.log('render(): 渲染内部虚拟DOM');
      return (
          <div>
            <h2>{this.props.name}, 当前时间: {this.state.date}</h2>
            <button onClick={this.removeComp}>移除组件</button>
          </div>
      );
    }
  }

  ReactDOM.render(<LifeCycle name="JACK"/>, document.getElementById('example'));
</script>
</body>
</html>

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>10_ComponentLife</title>
</head>
<body>
<div id="example"></div>

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
  /*
   自定义组件:
   功能描述: 让指定的文本做显示/隐藏的动画
   */
  class AnimateMsg extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        opacity: 1.0
      }
    }

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

    componentWillUnmount() {
      clearInterval(this.intervalId)
    }

    render () {
      return (
          <p style={{opacity: this.state.opacity}}>{this.props.msg}</p>
      );
    }
  }
  AnimateMsg.propTypes = {
    msg: React.PropTypes.string.isRequired,
  }

  ReactDOM.render(<AnimateMsg msg="www.qicaiyun.com"/>, document.getElementById('example'));
</script>
</body>
</html>

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>04_component</title>
</head>
<body>
<div id="example"></div>
<br>

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
  /*
  验证:
  虚拟DOM+DOM Diff算法: 最小化页面重绘
  */

  class HelloWorld extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        date: new Date()
      };
    }

    componentDidMount () {
      setInterval(() => {
        this.setState({
          date: new Date()
        })
      }, 1000)
    }

    render () {
      console.log('render()')
      return (
          <p>
            Hello, <input type="text" placeholder="Your name here"/>!
            It is {this.state.date.toTimeString()}
          </p>
      );
    }
  }

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

在这里插入图片描述

10_ajax

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>11_ajax</title>
</head>
<body>
<div id="example"></div>

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script src="//cdn.bootcss.com/axios/0.15.3/axios.min.js"></script>
<script src="//cdn.bootcss.com/fetch/2.0.1/fetch.min.js"></script>
<script type="text/babel">

/*
1. React没有ajax模块
  * 集成其它的js库(如jQuery/fetch/axios), 发送ajax请求
2. 使用axios
  * https://github.com/mzabriskie/axios
3. 使用fetch:
  * https://github.github.io/fetch/
  * https://segmentfault.com/a/1190000003810652
4. 测试url:
  * https://api.github.com/users/octocat/gists
*/

  class UserGist extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        lastGistUrl: null
      };
    }

    componentDidMount() {
      const url = `https://api.github.com/users/${this.props.name}/gists`
      axios.get(url)
          .then((response) => {
            console.log(response.data)
            var data = response.data;

            var lastGist = data[0];
            this.setState({
              lastGistUrl: lastGist.html_url
            });
          })
          .catch((error) => {
            console.log(error.response.data);
          });

      /*fetch(url).then(
          (response) => {
            response.json().then((result) => {
              console.log(result);
              var lastGist = result[0];
              this.setState({
                lastGistUrl: lastGist.html_url
              });
            })
          },
          (error) => {
            console.log(error);
          }
      );*/
    }

    render() {
      if(this.state.lastGistUrl===null) {
        return <h2>loading...</h2>
      } else {
        return (
            <div>
              {this.props.name}'s last gist is <a href={this.state.lastGistUrl}>here</a>
            </div>
        );
      }
    }
  }

  var name = 'octocat'
  ReactDOM.render(<UserGist name={name}/>, document.getElementById('example'));
</script>
</body>
</html>




在这里插入图片描述

11_react-server

React服务器端渲染入门

  • 理解
    • 当服务器端接收到请求时, 在服务器端基于React动态渲染页面, 并返回给浏览器显示
    • 相对于浏览器端渲染的好处?
      • 服务器端和客户端可以共享某些代码,避免重复定义。
      • 首次加载页面的速度加快
      • 便于SEO优化。服务器端渲染可以让搜索引擎更容易读取页面的meta信息以及其他SEO相关信息
    • 相对于浏览器端渲染的不好?
      • 对服务器的压力增大
      • 要求服务器使用基于node搭建
  • 简单编码实现服务器端渲染
    • 应用文件结构
      react-node
        |-- src
            |-- App.js-----------------主组件js
            |-- server.js--------------启动服务器监听, 处理请求的js
        |-- index.js---------入口js
        |-- .babelrc---------babel配置文件
        |-- package.json-----应用包信息文件
      
    • 编码
      • package.json
        {
          "name": "react-node",
          "version": "1.0.0",
          "scripts": {
            "start": "node index"
          },
          "devDependencies": {
            "babel-preset-es2015": "^6.6.0",
            "babel-preset-react": "^6.5.0",
            "babel-register": "^6.8.0"
          },
          "dependencies": {
            "react": "^15.3.1",
            "react-dom": "^15.3.1"
          }
        }
        
      • .babelrc
        {
          "presets": ["react", "es2015"]
        }
        
      • App.js
        import React, {Component} from 'react'
        class App extends Component {
        
          render() {
            return (
              <div>测试React服务器</div>
            )
          }
        }
        export default App
        
      • server.js
        import React from 'react';
        import { renderToString } from 'react-dom/server';
        var http = require('http');
        import App from './App';
        
        //创建服务器对象, 并启动监听
        http.createServer(function (request, response) {
          //向浏览器端写头信息
          response.writeHead(200, {'Content-Type': 'text/html'});
          //渲染组件成标签结构字符串
          const appHTML = renderToString(<App />);
          //向浏览器返回结果
          response.end(appHTML);
        }).listen(8888);
        // 终端打印提示信息
        console.log('Server running at http://127.0.0.1:8888/');
        
      • index.js
        require('babel-register');
        require('./src/server.js');
        
    • 启动服务器运行:
      • 命令: npm start
      • 访问: http://127.0.0.1:8888

12_key

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Lists and Keys</title>
</head>
<body>

<div id="root"></div>

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>

<script type="text/babel">

  /*
   为什么列表的key尽量不要用index
   http://jsbin.com/wohima/edit?js,output
   http://taobaofed.org/blog/2016/08/24/react-key/?utm_source=tuicool&utm_medium=referral
   简单来说: 当数组中的数据发生变化时: React 比较更新前后的元素 key 值,
   如果相同则更新,如果不同则销毁之前的,重新创建一个元素
   */

  function ListItem({id, name, age}) {
    return <li>{id}--{name}--{age}---<input type="text"/></li>;
  }

  class PersonList extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        persons: [
          {id: 1, name: 'Tom', age: 12},
          {id: 2, name: 'Jack', age: 13}
        ]
      };
      this.update = this.update.bind(this);
    }

    update() {
      let persons = this.state.persons;
      persons.unshift({id: 3, name: 'Bob', age: 14})
      this.setState({persons})
    }

    render() {
      const persons = this.state.persons;
      const listItems = persons.map((person, index) =>
          <ListItem key={person.id} {...person}/>
      );
      const listItems2 = persons.map((person, index) =>
          <ListItem key={index} {...person}/>
      );
      return (
          <div>
            <h2>使用id作为key</h2>
            <ul>
              {listItems}
            </ul>

            <h2>使用index作为key</h2>
            <ul>
              {listItems2}
            </ul>
            <button onClick={this.update}>首位添加一个人</button>
          </div>
      );
    }
  }

  ReactDOM.render(
      <PersonList/>,
      document.getElementById('root')
  );
</script>
</body>
</html>

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值