手记

【备战春招】第3天 React零基础入门到实战,完成企业级项目简书网站开发——React基础篇

课程名称

课程章节

第3章 React基础精讲

  • 3-1 使用React编写TodoList功能
  • 3-2 React 中的响应式设计思想和事件绑定

课程讲师

课程内容

使用React编写TodoList功能

删除App.js
新建一个TodoList组件

import React from 'react';
import ReactDOM from 'react-dom/client';
import TodoList from './TodoList';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <TodoList />
  </React.StrictMode>
);
import React, { Component } from "react";

class TodoList extends Component {
  render(){
    return (
      <div>TodoList</div>
    )
  }
}

export default TodoList;

import React, { Component } from "react";

class TodoList extends Component {
  render(){
    return (
      <div>
        <input></input>
        <button>提交</button>
      </div>
    )
  }
}

export default TodoList;


需求:
● 添加任务
● 删除任务

实现:往input框里输入内容,点击提交可以将其显示到下方列表中。
添加列表

import React, { Component } from "react";

class TodoList extends Component {
  render(){
    return (
      <div>
        <input></input>
        <button>提交</button>
      </div>
      <ul>
      <li>学英语</li>
      <li>Learning Math</li>
      </ul>
    )
  }
}

export default TodoList;

报错:jsx元素出现了问题,jsx中要求一个组件,render函数的返回值,外层必须只有一个包裹元素,但是这里最外层里有两个元素,这就违反了规定。在最外层加一个div。

import React, { Component } from "react";

class TodoList extends Component {
  render(){
    return (
      <div>
        <div>
          <input></input>
          <button>提交</button>
        </div>
        <ul>
          <li>学英语</li>
          <li>Learning Math</li>
        </ul>
      </div>
    )
  }
}

export default TodoList;



flex布局中,就希望顶层有多个标签,不要在外层再多加一个标签,而这又与jsx的语法矛盾。
想在最外层包裹一个元素,又同时希望该元素不显示出来,React16提供了一个新语法 => Fragment占位符

import React, { Component, Fragment } from "react";

class TodoList extends Component {
  render(){
    return (
      <Fragment>
        <div>
          <input></input>
          <button>提交</button>
        </div>
        <ul>
          <li>学英语</li>
          <li>Learning Math</li>
        </ul>
      </Fragment>
    )
  }
}

export default TodoList;

课程收获

掌握React 中的响应式设计思想和事件绑定 =>
实现:在input框里输入内容,点击提交,会将其加入到列表中 =>
思路:在提交按钮上绑定一个事件,获取到input框里的value值,再找到列表的dom节点,将input框里的value值挂载到该dom节点中。
这是直接操作dom的形式,React的设计思想和以前直接操作dom的思想是完全不同的。
React是一个响应式的框架,它在做编程的时候,强调不要直接操作dom,操作的是数据,通过数据的变化,React会自动的感知到数据的变化,自动帮助我们生成dom。因此在写React代码的时候,再也不用关注dom相关的操作了,只需要关注数据层的操作。
实际在做这样一个简单功能的时候,页面上会有多少数据呢?其实只需要两组数据就够了,一组数据存储input框里的值,一组数据存储列表中的每一项。
在代码中定义两个数据项 =>
TodoList这个组件,即是一个类,在js中一个类就一定有一个构造函数 => constructor
当创建一个TodoList实例,或者使用该组件的时候,constructor是优于任何函数(该类的方法),最先被执行的函数。
constructor固定可以接收一个参数 => props
super(props) => TodoList组件是继承了React.Component组件,所以需要在创建TodoList组件的时候,super实际指的就是父类,即React.Component组件,调用React.Component的(父类的)构造函数。
在React中写构造函数注意两点:
1、接收props参数
2、super(props) => 调用父级的构造函数

import React, { Component, Fragment } from "react";

class TodoList extends Component {
  constructor(props){
    super(props);
  }

  render(){
    return (
      <Fragment>
        <div>
          <input></input>
          <button>提交</button>
        </div>
        <ul>
          <li>学英语</li>
          <li>Learning Math</li>
        </ul>
      </Fragment>
    )
  }
}

export default TodoList;

定义数据 =>
React中需要把数据定义在状态里 => this.state
● 称为“组件的状态”
● 在其中可以存很多很多的东西
○ inputValue 存储input框里的值
○ list 存列表里的每一项数据,设置为数组类型
如何绑定input的value值与inputValue,进行关联 => value = this.state.inputValue,input的value值由inputValue决定,在jsx的与法中,this.state.inputValue实际是js的一个变量,如果想在jsx语法中使用js的表达式或者变量,它的语法是在最外层加一个大括号“{}”。
设置inputValue默认值,可以看到input框里的值由它决定 =>

import React, { Component, Fragment } from "react";

class TodoList extends Component {
  constructor(props){
    super(props);

    this.state = {
      inputValue: "hello!!!!!",
      list: []
    }
  }

  render(){
    return (
      <Fragment>
        <div>
          <input value={this.state.inputValue}></input>
          <button>提交</button>
        </div>
        <ul>
          <li>学英语</li>
          <li>Learning Math</li>
        </ul>
      </Fragment>
    )
  }
}

export default TodoList;


React会自动感知到数据的变化,会将数据映射到页面上,页面会自动响应数据的变化。
我们尝试在input框里输入内容,但是input框里的值始终不变化,因为input的值是由this.state.inputValue 决定的,而且这里this.state.inputValue的值,固定写死了。所以input框里永远是这个值,不管在input框里输入任何内容,显然这样控制是不对的。

在input框上绑定事件,在React种也可以进行事件绑定,如果想监听input框数据发生改变。React的事件绑定和原生的事件绑定有一个差别,原生是onchange,而React是onChange,“C”要大写,这是React事件绑定的语法。注意绑定事件处理函数的时候,也需要加大括号。
onChange={this.handleInputChange} => handleInputChange中打印一下事件对象

import React, { Component, Fragment } from "react";

class TodoList extends Component {
  constructor(props){
    super(props);

    this.state = {
      inputValue: "hello!!!!!",
      list: []
    }
  }

  render(){
    return (
      <Fragment>
        <div>
          <input 
            value={this.state.inputValue}
            onChange={this.handleInputChange}
            ></input>
          <button>提交</button>
        </div>
        <ul>
          <li>学英语</li>
          <li>Learning Math</li>
        </ul>
      </Fragment>
    )
  }

  handleInputChange(e){
    console.log(e)
  }
}

export default TodoList;


Target属性,打印一下

handleInputChange(e){
  console.log(e.target)
}

e.target其实就是对应事件的dom节点,它其实有一个value值,其实就可以获取到用户在input框里输入的内容了。

想要输入什么,页面跟着变化,则必须使数据发生变化,改变state种的input的value值。

handleInputChange(e){
  this.state.inputValue = e.target.value;;
}

发现输入一个内容,报错了。
state未被定义,这里肯定是this指向出了问题。

打印this指向,发现是undefined

handleInputChange(e){
  console.log(this)
}


我们希望的this指向的是,TodoList组件,获取它的state状态。
=> 绑定事件处理函数的时候通过bind函数,改变this。

import React, { Component, Fragment } from "react";

class TodoList extends Component {
  constructor(props){
    super(props);

    this.state = {
      inputValue: "hello!!!!!",
      list: []
    }
  }

  render(){
    return (
      <Fragment>
        <div>
          <input 
            value={this.state.inputValue}
            onChange={this.handleInputChange.bind(this)}
            ></input>
          <button>提交</button>
        </div>
        <ul>
          <li>学英语</li>
          <li>Learning Math</li>
        </ul>
      </Fragment>
    )
  }

  handleInputChange(e){
    console.log(this)
    // this.state.inputValue = e.target.value;;
  }
}

export default TodoList;


这就可以,但是改变input值还是没效果。

handleInputChange(e){
  this.state.inputValue = e.target.value;;
}

原因:在React中,想改变state的状态,不能直接通过this.state的引用这种方式去改,React给每一个组件提供了一个方法,this.setState() 去改变state的数据。

handleInputChange(e){
  this.setState({
    inputValue: e.target.value
  })
}


一开始,render函数渲染的时候,会把input的value值,渲染成inputValue的值。当在input输入内容的时候,input的onChange事件就会触发,执行handleInputChange方法,获取到用户输入的内容,并将其赋值给inputValue。inputValue值发生了改变,页面就会自动跟着变化了。

总结:1、state负责存储组件中的数据;2、jsx中想用js的表达式或者变量,需要用花括号包起来;3、事件绑定时候主要this指向问题,可以使用bind函数变更;4、改变state值,不能直接改,需要通过setState函数去改,通过传递对象的方式更改。

0人推荐
随时随地看视频
慕课网APP