React component-oriented programming (understanding and using +state+props+refs and event handling)

1 Basic understanding and use
Functional components
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>1_函数式组件</title>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入react-from,用于支持react操作dom -->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel"> 
    // 1. 创建函数式组件
    function MyComponent() {
      
      
        console.log(this);   // 此处的this是undefined,因为babel编译后开启了严格模式
        return <h2>我使用函数定义的组件(适用于【简单组件】的定义)</h2>;
    }

    // 2. 渲染组件到页面
    ReactDOM.render(<MyComponent/>, document.getElementById('test'));
    /*
    执行了React.render(<MyComponent/>.......之后发生了什么)
    1. react会解析组件标签,找到了Mycomponent组件。发现组件是使用函数定义的,随后调用该函数,将返回的虚拟Dom转为真实Dom,随后呈现在页面中
    */
    </script>
</body>
</html>
class component
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2_类式组件</title>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入react-from,用于支持react操作dom -->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel"> 
    // 1.创建类式组件
    class MyComponent extends React.Component{
      
      
        render() {
      
      
            // render方法放在了哪里? --- MyComponent的原型对象上,供实例使用
            // render中的this是谁? --- MyComponent的实例对象 MyComponent组件的实例对象
            console.log('render中的this', this);
            return <h2>我使用类定义的组件(适用于【复杂组件】的定义)</h2>;
        }
    }
    // 2.渲染组件到页面
    ReactDOM.render(<MyComponent/>, document.getElementById('test'));
    /*
    执行了React.render(<MyComponent/>.......之后发生了什么)
    1. react会解析组件标签,找到了Mycomponent组件。
    2.发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法
    3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中
    */
    </script>
</body>
</html>
Notice
  1. Component names must first be capitalized

  2. Virtual DOM elements can only have one root element

  3. Virtual DOM elements must have closing tags

class review
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>1_类的基本知识</title>
</head>
<body>
    <script type="text/javascript">
        /*
        总结:
        1.类中的构造器不是必须写的,要对实例进行一些初始化的操作,如添加指定属性时,才写
        2.如果A类继承了B类,且A类写了构造器,那么A类构造器中super是必须要调用的。
        3.类中所定义的方法,都是放在了类的原型对象上,供实例使用
        */

        // 创建一个Person类
        class Person {
      
      
            // 构造器方法
            constructor(name, age) {
      
      
                // 构造器中的this是谁?--类的实例对象
                this.name = name;
                this.age = age;
            }
            // 一般方法
            speak() {
      
      
                // speak方法放在了哪里? --- 类的原型对象上,供实例使用
                // 通过Person实例调用speak时,speak中的this就是Person实例
                console.log(`我叫${ 
        this.name},我年龄是${ 
        this.age}`);
            }
        }

        // 创建一个student类,继承于Person类
        class Student extends Person {
      
      
            constructor(name, age, grade) {
      
      
                super(name, age);
                this.grade = grade;
            }
            // 重写从父类继承过来的方法
            speak() {
      
      
                console.log(`我叫${ 
        this.name},我年龄时${ 
        this.age},我读的是${ 
        this.grade}年级`);
            }
            study() {
      
      
                // study方法放在了哪里? --- 类的原型对象上,供实例使用
                // 通过Student实例调用study时,study中的this就是Student实例
                console.log('我很努力的学习');
            }
        }
        // 创建一个Person的实例对象
        // const p1 = new Person('tom', 18);
        // const p2 = new Person('jerry', 19);
        // console.log(p1);
        // console.log(p2);
        // p1.speak();
        // p2.speak();
        // p1.speak.call({a: 1, b: 2});

        const s1 = new Student('小张', 15, '高一');
        console.log(s1);
        s1.speak();
        s1.study();
    </script>

</body>
</html>
2 Three core attributes of component instances 1.state
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>state.html</title>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入react-from,用于支持react操作dom -->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel"> 
    // 1.创建组件
    class Weather extends React.Component {
      
      
        constructor(props) {
      
      
            super(props);
            this.state = {
      
      isHot: true}
        }
        render() {
      
      
            // 读取状态
            const {
      
      isHot} = this.state;
            return <h1 onClick={
      
      demo}>今天天气很{
      
      isHot ? '炎热' : '凉爽'}</h1>
        }
    }
    // 2.渲染组件到页面
    ReactDOM.render(<Weather/>, document.getElementById('test'));

    function demo() {
      
      
        alert('按钮3被点击了');
    }
    </script>
</body>
</html>
2.1 Exercise

Requirement: Define a component that displays weather information

1. The default display is hot or cool

2. Click on the text to switch weather

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>state.html</title>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入react-from,用于支持react操作dom -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel">
      // 1.创建组件
      class Weather extends React.Component {
      
      
        // 构造器调用几次?-----1次
        constructor(props) {
      
      
          super(props);
          // 初始化状态
          this.state = {
      
       isHot: true, wind: '微风' };
          // 解决changeWeacther中this指向问题
          this.changeWeather = this.changeWeather.bind(this);
        }

        // render调用几次?----- 点几次调用几次
        render() {
      
      
          // 读取状态
          const {
      
       isHot, wind } = this.state;
          return (
            <h1 onClick={
      
      this.changeWeather}>今天天气很{
      
      isHot ? "炎热" : "凉爽"}, {
      
      wind}</h1>
          );
        }

        // changeWeather调用几次?----- 点几次调用几次
        changeWeather() {
      
      
          // changeWeather方法放在了哪里? --- Weather的原型对象上,供实例使用
          // 由于changeWeather是作为onClick的回调,所以不是通过实例调用,是直接调用
          // 类中的方法默认开启了局部的严格模式,所以changeWeather中的this位undefined
          
          // 获取原来的isHot值
          const isHot = this.state.isHot;
          // 严重注意:状态必须通过setState进行更新,更新是一种合并,不是替换
          this.setState({
      
      isHot: !isHot})


          // 严重注意:状态(state)不可以直接更改,下面这行就是直接更改
          // this.state.isHit = !isHot; // 错误写法

          
        }
      }
      // 2.渲染组件到页面
      ReactDOM.render(<Weather />, document.getElementById("test"));
    </script>
  </body>
</html>

abbreviation

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>state.html</title>
  </head>
  <body>
    <!-- 准备好一个容器 -->
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入react-from,用于支持react操作dom -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel">
      class Weather extends React.Component {
      
      
        state = {
      
       isHot: true, wind: '微风' };
        render() {
      
      
          // 读取状态
          const {
      
       isHot, wind } = this.state;
          return (
            <h1 onClick={
      
      this.changeWeather}>今天天气很{
      
      isHot ? "炎热" : "凉爽"}, {
      
      wind}</h1>
          );
        }

        // 自定义方法-----要用赋值语句形式 + 箭头函数
        changeWeather = () => {
      
      
          const isHot = this.state.isHot;
          this.setState({
      
      isHot: !isHot})
        }
      }
      ReactDOM.render(<Weather />, document.getElementById("test"));
    </script>
  </body>
</html>
2.2 Understanding
  1. State is the most important attribute of the component object, and the value is the object (can contain multiple key-value combinations)

  2. Components are called "state machines", and the corresponding page display is updated by updating the component's state (re-rendering the component)

2.3 Strong attention
  1. This in the render method of the component is the component instance object

  2. This is undefined in the component's custom method. How to solve it?

    a) Forcibly bind this: through bind() of the function object

    b) arrow function

  3. Status data cannot be modified or updated directly

3 Three core attributes of components 2: props

函数式组件能用props,但是不能用state,refs

3.1 Effect

Requirements Customize the component used to display a person's information

1. The name must be specified and is of string type;

2. Gender is a string type. If gender is not specified, it defaults to male

3. The age is a string type and a numeric type. The default value is 18

Insert image description here

3.2 Understanding
  1. Each component object will have props (abbreviation for properties) attributes

  2. All properties of component tags are saved in props

3.3 Function
  1. Pass changing data from outside the component to within the component through label attributes

  2. Note: Do not modify props data inside the component

3.4 Encoding operation
  1. Read an attribute value internallythis.props.name

  2. Type restrictions and necessity restrictions on attribute values ​​in props

The first way (deprecated since React v15.5):

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

The second way (new): use prop-types library to impose restrictions (prop-types library needs to be introduced)

Person.propTypes = {
    
          
    name: PropTypes.string.isRequired, 
    age: PropTypes.number      
} 
  1. Extended properties: Pass all properties of the object through props
<Person {
    
    ...person}/>
  1. Default property values:
Person.defaultProps = {
    
    
  age: 18,
  sex:'男'
  }
  1. Constructor of component class

    constructor(props){
          
          
      super(props)
      console.log(props)//打印所有属性
    }
    

propsIt is read-only and cannot be modified.

eg:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>hello_react</title>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="test1"></div>
    <div id="test2"></div>
    <div id="test3"></div>

    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入react-from,用于支持react操作dom -->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>
    <!-- 引入prop-types,用于对组件标签属性进行限制 -->
    <script type="text/javascript" src="../js/prop-types.js"></script>


    <script type="text/babel">  /* 此处一定要写babel */
    // 创建组件
    class Person extends React.Component {
      
      
        state = {
      
      name: 'tom', age: 18, sex: '女'};
        
        render() {
      
      
            console.log(this);
            const {
      
      name, age, sex} = this.props;
            // props是只读的
            this.props.name = 'jack'; // 此行代码会报错,因为props是只读的
            return (
                <ul>
                    <li>姓名:{
      
      name}</li>
                    <li>性别:{
      
      sex}</li>
                    <li>年龄:{
      
      age + 1}</li>
                </ul>
            )
        }
    }
    // 对标签属性进行类型、必要性限制
    Person.propTypes = {
      
      
        name: PropTypes.string.isRequired, // 限制name必传,且为字符串
        sex: PropTypes.string, // 限制name为字符串
        age: PropTypes.number, // 限制age为数值
        speak: PropTypes.func, // 限制speak为函数
    }
    // 只当默认标签属性值
    Person.defaultProps = {
      
      
        sex: '不男不女', // sex默认值为男
        age: 18 // sex默认值为男
    }
    // 渲染组件到页面
    ReactDOM.render(<Person name="jerry" speak="1"/>, document.getElementById('test1'));
    ReactDOM.render(<Person name="tom" age={
      
      18} sex="男"/>, document.getElementById('test2'));
    const p = {
      
      name: '老刘', age: 18, sex: '女'};
    console.log(...p);
    // ReactDOM.render(<Person name={p.name} age={p.age} sex={p.sex}/>, document.getElementById('test3'));
    ReactDOM.render(<Person {
      
      ...p}/>, document.getElementById('test3'));

    function speak() {
      
      
        console.log('我说话了');
    }
    </script>
</body>
</html>
4 Three core attributes of components 3: refs and event processing
practise

Requirements: Custom components, the function description is as follows:

  1. Click the button to prompt for the value in the first input box

  2. When the second input box loses focus, prompt the value in this input box

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>4_createRef</title>
      </head>
      <body>
        <!-- 准备好一个容器 -->
        <div id="test"></div>
    
        <!-- 引入react核心库 -->
        <script type="text/javascript" src="../js/react.development.js"></script>
        <!-- 引入react-from,用于支持react操作dom -->
        <script
          type="text/javascript"
          src="../js/react-dom.development.js"
        ></script>
        <!-- 引入babel,用于将jsx转为js -->
        <script type="text/javascript" src="../js/babel.min.js"></script>
    
        <script type="text/babel">
          // 创建组件
          class Demo extends React.Component {
            
            
            /*
            React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的
            */
            myRef = React.createRef();
            myRef2 = React.createRef();
            // 展示左侧输入框的数据
            showData = () => {
            
            
              alert(this.myRef.current.value);
            };
            showData2 = () => {
            
            
                alert(this.myRef2.current.value);
            }
            render() {
            
            
              return (
                <div>
                  <input ref={
            
            this.myRef} type="text" placeholder="点击按钮提示数据" />
                  &nbsp;
                  <button onClick={
            
            this.showData}>
                    点我提示左侧的数据
                  </button>
                  &nbsp;
                  <input onBlur={
            
            this.showData2} ref={
            
            this.myRef2} type="text" placeholder="失去焦点提示数据" />
                </div>
              );
            }
          }
          // 渲染组件到页面
          ReactDOM.render(<Demo />, document.getElementById("test"));
        </script>
      </body>
    </html>
    
understand

Tags within components can define ref attributes to identify themselves.

coding
  1. ref in string form
<input ref="input1"/>
  1. ref in callback form
<input ref={(c)=>{this.input1 = c}}
  1. createRef creates a ref container
myRef = React.createRef() 
<input ref={this.myRef}/>
event handling
  1. Specify the event processing function through the onXxx attribute (note the case)

    1. React uses custom (synthetic) events instead of native DOM events ---- for better compatibility

    2. Events in React are handled through event delegation (delegated to the outermost element of the component) ----- For efficiency

  2. Get the DOM element object where the event occurred through event.target ----- Don't overuse ref

Guess you like

Origin blog.csdn.net/m0_57809042/article/details/129578253