React组件

// 导入React、React-DOM
// React负责创建React元素 - 虚拟DOM
// ReactDOM负责渲染React元素
// JSX - 插值表达式
// 表达式
// 1. 变量
// 2. 基本数据类型:string、number、boolean、undefined、null
// 3. 其他:三元、逻辑表达式、JSX

// 其中string和number正常显示而null、boolean、undefined不显示

import React, { Component } from 'react'
import ReactDOM from 'react-dom/client'
import { nanoid } from 'nanoid'
import './base.css'
import App from './App'

// 通过React.createElement创建相关元素
// React.createElement('标签类型', {标签属性: 属性值}, '标签内容')
const root = ReactDOM.createRoot(document.getElementById('root'))

// 🤴🏻 React组件 - 创建函数式组件 (💥 组件名称必须是大写开头的)
function Hello() {
  // 必须有返回值,表示渲染一段JSX,如果不渲染任何内容则返回null
  // return null
  return <h1>Hello React</h1>
}

// 👨🏻 通过class创建组件

class MyApp extends React.Component {
  render() {
    return (
      <>
        <h1>We are the world</h1>
      </>
    )
  }
}

// 🍣 使用组件状态state对象存储组件状态数据
// => 声明数据
// 1. state是对象,以key:value存储
// 2. class组件中有声明 state 的写法,函数组件中没有
// 3. this指向组件的实例对象
class MyAppWithState extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      msg: '浙商CFer',
      count: 220,
    }
  }
  render() {
    console.log('this: ', this)
    return (
      <>
        消息:{this.state.msg}
        <br />
        技术:{this.state.count}
        <br />
      </>
    )
  }
}

// 绑定事件
// on + 驼峰事件 = {函数}
class MyApp01 extends React.Component {
  render() {
    return (
      <>
        <button onClick={() => this.handleClick01()}>App Click01</button>
        <br />
        <button onClick={this.handleClick02}>App Click02</button>
      </>
    )
  }

  handleClick01() {
    console.log('普通函数 - this: ', this)
    console.log('say: ', 4321)
  }

  // 推荐写法
  handleClick02 = () => {
    console.log('箭头函数 - this: ', this)
  }
}

// 获取事件对象
class MyApp02 extends React.Component {
  render() {
    return (
      <>
        <a
          onClick={(e) => {
            e.preventDefault()
          }}
          href="http://www.baidu.com"
        >
          点击
        </a>
        <br />
        <a onClick={this.handleClick} href="http://www.baidu.com">
          点击
        </a>
      </>
    )
  }

  handleClick = (e) => {
    e.preventDefault()
    console.log('e ---> ', e)
  }
}

class MyApp03 extends React.Component {
  handleClick = (num, e) => {
    e.preventDefault()
    console.log('num ----> ', num)
  }

  render() {
    return (
      <>
        <a
          href="http://www.baidu.com"
          onClick={(e) => this.handleClick(279, e)}
        >
          点我传递数据
        </a>
        <br />
      </>
    )
  }
}
// 掌握React组件中this指向的两种情况
// 1. React自带结构体: this指向正确,指向组件实例对象
// 2. 非React自带结构体:this指向不正确,指向undefined

class App04 extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      msg: 'we a................',
    }
  }

  handleXxx = () => {
    console.log('this -> ', this.state.msg)
  }

  render() {
    return (
      <>
        <button onClick={this.handleXxx}>点我</button>
      </>
    )
  }
}
// 🤴🏻 处理this指向undefined的三种办法
// 箭头函数本身没有this,自动绑定调用的时候所处的环境中的this
// 步骤:
// 1. ⚡ React自带结构体:this指向正确,指向组件实例对象
// 2. ⚡非React自带结构体:this指向不正确,指向undefined
class App05 extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 99,
      msg: 'Everything will be bright!',
    }
  }

  handleClick = () => {
    // 正确修改state数据方式
    this.setState({
      count: this.state.count + 1,
    })
    // 错误修改state数据方式
    // this.state.count = 100;

    console.log('this.state.count:  ', this.state.count) // 99 因为设置state数据是异步的不会立即改变
  }

  render() {
    return (
      <>
        <button onClick={this.handleClick}>修改state</button>
      </>
    )
  }
}

//
class App06 extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [1, 2, 3, 4],
      userinfo: 'we are the world',
    }
  }

  handleClick = () => {
    // ❌ this.state.list.push(4);

    // 设置状态数据
    this.setState({
      // 🥩 不可变数据:不允许修改原始数据, 使用新的值覆盖旧的值
      list: [...this.state.list, 4],
    })
  }

  render() {
    return (
      <>
        <div>
          <h1>{this.state.list}</h1>
          <button onClick={this.handleClick}>点我 +4</button>
        </div>
      </>
    )
  }
}

// 购物车练习
class App07 extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 0,
    }
  }

  // 1. 定义add函数
  handleClick = (num) => {
    this.setState({
      count: this.state.count + num,
    })
  }

  render() {
    return (
      <>
        <div>
          <p>当前数值为:{this.state.count}</p>
          <hr />
          <button onClick={() => this.handleClick(1)}>+1</button>
          <button onClick={() => this.handleClick(-1)}>-1</button>
        </div>
      </>
    )
  }
}

// 受控组件的基本使用
// 表单元素的值,由state控制
// 🌰 和v-model类似
// 1. 收集用户输入的内容
// 2. 回填表单数据

class App08 extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      msg: 'hello 79',
    }
  }

  render() {
    // 表单元素的value或checked属性收到state的控制
    return (
      <>
        <div>
          <input
            // 使用onChange替代onInput
            onChange={(e) => {
              this.setState({ msg: e.target.value })
            }}
            type="text"
            value={this.state.msg}
            // onBlur称为失去焦点事件
            onBlur={(e) => {
              console.log('e.target.value ----> ', e.target.value)
            }}
          ></input>
        </div>
      </>
    )
  }
}

class App09 extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      msg: 'hello 79',
    }
  }
  state = {
    username: '',
    desc: '',
    city: 2,
    isSingle: true,
  }

  handleChangeName = (e) => {
    this.setState({
      username: e.target.value,
    })
  }

  handleChangeDesc = (e) => {
    this.setState({
      desc: e.target.value,
    })
  }

  handleChangeCity = (e) => {
    this.setState({
      city: e.target.value,
    })
  }

  handleChangeSingle = (e) => {
    this.setState({
      isSingle: e.target.checked,
    })
  }

  handleChange = (e) => {
    const { name, type, checked, value } = e.target
    this.setState({
      [name]: type === 'checkbox' ? checked : value,
    })
  }

  handleSubmit = () => {
    const username = document.querySelector('#username').value
    const desc = document.querySelector('#desc').value
    const data = { username, desc }
    console.log('data: => ', data)
  }
  render() {
    const { username, desc, city, isSingle } = this.state
    return (
      <>
        <div>
          姓名:
          <input
            id="username"
            name="username"
            type="text"
            onChange={this.handleChangeName}
            value={username}
          />
          <br />
          描述:
          <textarea
            id="desc"
            name="desc"
            onChange={this.handleChangeDesc}
            value={desc}
          />
          <br />
          城市:
          <select value={city} onChange={this.handleChangeCity}>
            <option value="1">北京</option>
            <option value="2">上海</option>
            <option value="3">广州</option>
            <option value="4">深圳</option>
          </select>
          <br />
          是否单身:{' '}
          <input
            onChange={this.handleChangeSingle}
            checked={isSingle}
            type="checkbox"
          />
          <button onClick={this.handleSubmit}>提交表单</button>
        </div>
      </>
    )
  }
}
// 学习目标: ref的使用
// 场景:
// 1. 获取DOM元素
// 2. 获取组件实例对象
class App10 extends React.Component {
  // 创建Ref
  childRef = React.createRef()

  handleClick = () => {
    // 通过ref.current属性获取DOM元素或组件实例对象
    console.log('this.childRef.current: ', this.childRef.current)
    this.childRef.current.handleClick()
    this.childRef.current.sayInfo()
  }
  render() {
    return (
      <>
        <Child
          // 绑定到DOM元素或组件标签上
          // 🔥 只有class组件才有实例对象,函数式组件没有实例对象
          ref={this.childRef}
        ></Child>
        <button onClick={this.handleClick}>点我激活input</button>
      </>
    )
  }
}

class Child extends React.Component {
  state = {
    username: 'wangzz',
    age: 24,
    info: 'we are the world',
  }
  handleClick = () => {
    console.log('触发!!')
  }
  sayInfo = () => {
    console.log("I don't know, but i will try my best!")
  }

  render() {
    return (
      <>
        <p>we are the world</p>
      </>
    )
  }
}
const divNode = (
  <div>
    <App10 />
  </div>
)
root.render(divNode)

posted @ 2023-03-20 20:29  Felix_Openmind  阅读(26)  评论(0)    收藏  举报
*{cursor: url(https://files-cdn.cnblogs.com/files/morango/fish-cursor.ico),auto;}