zoukankan      html  css  js  c++  java
  • React组件 (一)

    在React中定义组件

    函数式组件

    函数式组件(用函数定义的组件)比较简单一般用于静态没有交互事件内容的组件页面

    
    // 1、创建函数式组件 (组件是代码和资源的结合) 
    function MyComponent(){
        console.log(this) // 此处的this是undefin 因为babel翻译后开启了严格模式
        return <h1>我是函数定义的组件(适应于【简单组件】的定义)</h1>
    } 
    // 2、渲染到页面上 
    ReactDOM.render(<MyComponent />,document.getElementById('test'))
    
    

    注意

    • 首字母必须大写

    • 函数必须有返回值

    • ReactDOM.render第一个参数为组件标签(要闭合,必须有结束标签)

    执行了 ReactDOM.render(,document.getElementById('test')) 之后,发生了什么?(渲染函数式组件标签的基本流程)

    • React解析组件标签,找到了MyComponent组件。

    • 发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。

    类式组件

    类式组件(用类定义的组件)又称为动态组件,一般用于有交互事件或数据修改的组件页面

    
    // 1、创建类式组件 (组件是代码和资源的结合)
    class MyComponent extends React.Component { 
        render(){
            console.log('render中的this:',this);
            return <h1>我是类式组件(适应于【复杂组件】的定义)</h1>
        }
    } 
    // 2、渲染到页面上 
    ReactDOM.render(<MyComponent />,document.getElementById('test'))
    
    
    • render是放在哪里了? - 类MyComponent的原型对象上,供实例使用

    • render中的this是谁?—— MyComponent的实例对象 <=> MyComponent组件实例对象。

    注意

    • 必须继承父类

    • 必须写render

    • render必须有返回值

    执行了 ReactDOM.render(,document.getElementById('test')) 之后,发生了什么?渲染类式组件标签的基本流程

    • React解析组件标签,找到了MyComponent组件。

    • 发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。

    • 将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。

    组件实例的三大属性 1 : state

    复杂组件:有状态(state)的组件

    简单组件:没有状态的组件

    一个demo

    需求: 自定义组件, 功能说明如下

    1. 显示h1标题, 初始文本为: 你喜欢我
    2. 点击标题更新为: 我喜欢你

    第一步:创建一个自定义组件,显示h1标题,初始文本是:你喜欢我

    
    // 创建组件
    class Like extends React.Component{
      render(){
          return <h1>你喜欢我</h1>
      }
    }
    // 渲染组件
    ReactDOM.render(<Like /> , document.getElementById("test"))
    
    

    第二步:初始化state

    你喜欢我 会变成 我喜欢你 点击切换变化

    使用类构造器,定义一个标识 isLike (存放在状态state里)false 你喜欢我 true 我喜欢你

    
     //创建组件
    class Like extends React.Component{
      constructor(props){
        //调用父类的构造函数
          super(props) 
          // 初始化状态
          this.state = {
              isLike:false
          }
      }
      // 在render中state中存储的数据
      render(){
          // 读取状态
          const {isLike} = this.state
          return <h1>{isLike ? '我喜欢你' : '你喜欢我' }</h1>
      }
    }
    // 渲染组件
    ReactDOM.render(<Like /> , document.getElementById("test"))
    
    

    第三步:React中的事件绑定

    
    // 创建组件
    class Like extends React.Component{
      constructor(props){
          super(props) 
          // 初始化状态
          this.state = {
              isLike:false
          }
      }
      // 在render中state中存储的数据
      render(){
          // 读取状态
          const {isLike} = this.state
          
          return <h1 onClick={changeLike}>{isLike ? '我喜欢你' : '你喜欢我' }</h1>
      }
    }
    // 渲染组件
    ReactDOM.render(<Like /> , document.getElementById("test"))
    
    function changeLike(){
      console.log("触发了点击事件");
    }
    
    
    • React 事件绑定属性的命名采用驼峰式写法,而不是小写。比如: onClick

    • 如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)

    • HTML 通常写法是:<button onclick="activateLasers()">激活按钮</button>

    • React 中写法为:<button onClick={activateLasers}>激活按钮</button>

    第四步 在点击事件中修改isLike的值

    问题一、:第三步的function的this指向undefined 获取不到isLike(不采用这种写法 将事件写入类里面)

    1. 将事件写入类里面,changeLike this指向undefined
    
    class Like extends React.Component{
      constructor(props){
        super(props)  
          this.state = {
          isLike:false
        }
        console.log(this); // 类实例对象
      } 
      render(){
        console.log(this); // 类实例对象
        // 读取状态
        const {isLike} = this.state 
        return <h1 onClick={this.changeLike}>{isLike ? '我喜欢你' : '你喜欢我' }</h1>
      }
      changeLike(){
        console.log(this); // this 是 undefined
        console.log("触发了点击事件");
        console.log(this.state.isLike);
      }
    }
    // 渲染组件
    ReactDOM.render(<Like /> , document.getElementById("test")) 
    
    
    constructor、render、changeLike的this指向

    注意:
    • changeLike ==》放在了Like的原型上,供实例使用

    • 通过Like实例调用changeLike时,changeLike中的this就是Like实例

    • <h1 onClick={this.changeLike}>{isLike ? '我喜欢你' : '你喜欢我' }</h1> 并不是通过Like实例调用的

    • 由于changeLike是作为onClick的回调,所以不是通过实例调用的,是直接调用

    • 类中的方法默认开启了局部的严格模式,所以changeLike中的this为undefined

    解决办法
    this.changeLike = this.changeLike.bind(this);
    
    
     class Like extends React.Component{
      constructor(props){
        super(props) 
        // 初始化状态
        this.state = {
          isLike:false
        }
        // 生成了新的函数 改变函数的this指向
        // 在实例自身上生成一个方法
        // 解决changeLike中this指向问题
        this.changeLike = this.changeLike.bind(this);
      } 
      render(){
        console.log(this); 
        const {isLike} = this.state 
        return <h1 onClick={this.changeLike}>{isLike ? '我喜欢你' : '你喜欢我' }</h1>
      }
      changeLike(){
        console.log(this);
        console.log("触发了点击事件");
        console.log(this.state.isLike);
      }
    }
    // 渲染组件
    ReactDOM.render(<Like /> , document.getElementById("test")) 
    
    
    1. 修改isLike的值(setState),完成需求
    
    class Like extends React.Component{
      constructor(props){
        super(props)  
        this.state = {
          isLike:false
        } 
        this.changeLike = this.changeLike.bind(this);
      } 
      render(){ 
        const {isLike} = this.state 
        return <h1 onClick={this.changeLike}>{isLike ? '我喜欢你' : '你喜欢我' }</h1>
      }
      changeLike(){ 
      // 获取isLike的值 直接修改
      const isLike = this.state.isLike; 
      //注意:状态必须通过setState进行更新,且更新是一种合并,不是替换。
      this.setState({isLike:!isLike})
    
      //注意:状态(state)不可直接更改,下面这行就是直接更改!!!
      //this.state.isLike = !isLike //这是错误的写法
    
      }
    }
    // 渲染组件
    ReactDOM.render(<Like /> , document.getElementById("test")) 
    
    

    实例说明:

    • setState每次修改内容会自动触发React重新渲染页面

    • 因此示例中每次点击都会修改状态,更加状态重新渲染内容,达到内容切换的目的

    • constructor ———— 调用了1次

    • render ———— 调用1+n次 1是初始化的那次 n是状态更新的次数

    • changeLike ———— 点几次调几次

    State状态理解

    • state 是组件对象中最重要的属性,值是对象(可以包含多个数据)

    • 组件被称为"状态机",通过更新组件的state来更新对应的页面显示(重新渲染组件)

    • state是组件实例的属性,函数组件没有实例,因为函数组件没有状态

    • state可以理解是组件自己的数据, props数据是外部传入,state数据就是组件自己的

    State的使用规则

    • state 通常在组件的constructor中进行初始化

    • state 只能用setState方法更新

    • setState会导致render重新执行,渲染组件和所有的子组件

    1)初始化状态

    
    constructor(props){
        super(props)  
        this.state = {
            stateProp1 : value1,
            stateProp2 : value2
        } 
    }
    
    

    2)读取某个状态

    
    this.state.statePropertyName
    this.state.stateProp1
    
    

    3)更新状态 —> 组件界面更新

    
    this.setState({
        stateProp1 : value1,
        stateProp2 : value2
    })
    
    

    状态的简写定义

    说明

    • ES6 class类中 constructor 函数为构造函数, 内部通过this定义的属性是类实例的属性

    • class类中其他的方法确实实例原型上的方法

    • 但是class类中的表达式定义的内容确实实例上的内容

    示例

    
    class Person {
        constructor() {
          // 实例属性
          this.name = "张三"
        }
    
        // 实例上的属性
        age = 18
    
        // 实例上的方法
        eat = function () {
          console.log("eat")
        }
    
        // 原型上的方法
        run() {
          console.log("eat")
        }
    }
    
    var p1 = new Person
    console.log(p1)
    
    

    打印结果如下:

    实例说明

    • ES6中class类里定义的表达式,无论是函数表达式,函数普通的表达式,最后都是实例的属性或方法

    • ES6中class类中普通定义的函数是实例原型上的方法

    对state-demo进行简写

    
    
    // 创建组件
    class Like extends React.Component {
        //初始化定义state状态
        state = {
            isLike: false
        }
        render() {
            const { isLike } = this.state
            return <h1 onClick={this.changeLike}>{isLike ? '我喜欢你' : '你喜欢我'}</h1>
        }
        //组件实例化上的方法
        changeLike = () => {
            const isLike = this.state.isLike; 
            this.setState({ isLike: !isLike }) 
        }
    }
    // 渲染组件
    ReactDOM.render(<Like />, document.getElementById("test"))
    
    

    强烈注意

    组件中render方法中的this为组件实例对象

    组件自定义的方法中this为undefined,如何解决?

    • 强制绑定this: 通过函数对象的bind()

    • 箭头函数

    状态数据,不能直接修改或更新

    React中更新State对象的某一个属性值

    数据如下

    
    this.state = {
      login: {
        username: '',
        password: ''
      }
    }
    
    

    修改username

    正确更新

    
    const login = this.state.login
    login.username = 'admin'
    this.setState({ login })
    
    
    • 得到login的地址,再对对象属性赋值,更新对象
  • 相关阅读:
    C#设计模式(6)——原型模式(Prototype Pattern)
    C#设计模式(4)——抽象工厂模式
    C#设计模式(3)——工厂方法模式
    C#设计模式(2)——简单工厂模式
    cmd 打 jar 包
    java eclipse 中给args 传递参数
    java 中值传递和引用传递(转)
    java unreachable code不可达代码
    java语言中if语句的用法
    java中 构造器与void
  • 原文地址:https://www.cnblogs.com/jing428/p/14479571.html
Copyright © 2011-2022 走看看