React基础速览

南山隐士 2022年06月25日 21 0

什么是JSX

JSX是javascript的扩展语言, 在JSX中, 你不仅可以写 html 还可以 写 javascript 表达式

以下是简单的例子

const myName = '遥近'
const template = <h1>Hello, {myName}</h1>
ReactDOM.render(template, document.getElementById('app'))

可以看到 在 jsx 中, 可以通过 {} 来编写javascript表达式, 这样就可以很方便得渲染你想呈现的内容

jsx是一个表达式

更神奇的是, jsx也是一个表达式, 也就是说你可以将其作为函数返回, 或者赋值到一个变量中.

function createName(name) {
if (name) {
        return <h1>Hello, {name}</h1>
      } else {
        return <h1>Hello, World</h1>
      }
    }
ReactDOM.render(createName(), document.getElementById('app'))

jsx中设置属性

在jsx中,使用驼峰命名来设置属性值, 例如 className 而不是 class , 想在属性中使用表达式, 使用 { } 包裹即可

组件 和 props

在react 中, 组件可以分为函数组件和 class 组件, 组件是由各个元素组合起来, 一般可以用来复用的, 并接受参数, 即props, 最终返回用来展示页面的 react 元素, 不论是函数组件和或者class 组件, ==都必须以大写字母作为开头==, 不然react 将视为普通的dom元素

函数组件

一旦你使用了大写作为开头, 那么react将视为组件, 你在标签中定义的属性将会作为参数(props)给到组件内部使用, 子元素标签将会作为props 的 children 属性 给到组件内部

// 定义一个Welcome函数组件
    function Welcome(props) {
      console.log(props)
      return (
        <div>
          <div>你好, {props.name}</div> // 你好遥近
          <div>{props.children}</div> {/* <span>您好啊我是子元素</span> */}
        </div>
      )
    }
    const element = (
      <Welcome name="遥近">
        <span>您好啊我是子元素</span>
      </Welcome>
    )
    ReactDOM.render(element, document.getElementById('app'))

class组件

class 组件是 使用了es6 的 class 继承 React.Component 来定义的组件, 通过这个方式定义的组件, 可以拥有react的生命周期, state 等其他特征

props

在组件中,我们接受props, 但是, 需要注意的是, 无论如何我们都不可以改变props的值, ==props只是只读的==

State

props不能更改, 为了随数据的更改,页面保持 变化, react 引入了一种新的概念, 称为 state, 想定义state, 就不能使用函数组件, 必须通过class组件定义

export default class Time extends React.Component {
  constructor(props) {
    super(props) // 调用了super才可以使用this,添加state, 并且在this中读取props
    this.state = { date: new Date() }
  }
}

通过class定义组件后,我们还需要在constructor中定义并且初始state, 需要注意的是, 必须先调用super, 才可以读取this, 这是es6 class 定义的规则, 因为子类是没有自己的this的, 只能继承父类的this, 在对这个this加以使用

现在让我们在 componentDidMount 创建定时器, 以及在 componentWillUnmount 清除定时器, 最后通过render 方法读取state的值, 就可以看到数据和页面是同步更新的了

// 挂载完毕执行
  componentDidMount() {
    this.timerID = setInterval(() => this.tick(), 1000)
  }

  // 卸载时候执行
  componentWillUnmount() {
    clearInterval(this.timerID)
  }

  tick() {
    this.setState({
      date: new Date(),
    })
  }

  render() {
    return (
      <div>
        <h1>你好</h1>
        <p>现在时间是: {this.state.date.toLocaleTimeString()}</p>
      </div>
    )
  }

需要注意的state 只能通过 this.setState 来进行更新, 并且State 的更新可能是异步的, state是单项数据流的, 意味着不可以通过子组件去改变父组件的state

定义事件

在html中,我们定义事件, 例如onclick, 使用小字母, 但是在react中, 你需要使用驼峰命名来定义事件

<div>
   <button onClick={this.handleClick}>点击测试</button>
</div>

在事件中

如果你需要阻止默认行为, 你必须显式得使用 .preventDefault()

想要在事件中,使用组件的实例(即可以读取this)
你需要通过以下几种方法

constructor绑定this

constructor(props) {
    super(props)
    // 通过在constructor中改变this执行
    this.handleClick = this.handleClick.bind(this)
  }
render() {
    return (
      <div>
        <button onClick={this.handleClick}>点击测试</button>
      </div>
    )
  }

public class fields 语法
public class fields 语法

handleClick = () => {
    console.log('this is:', this);
  }

其他方法

<button onClick={(e) => this.handleClick(e)}>点击测试</button>
<button onClick={this.handleClick.bind(this)}>点击测试</button>

需要读取event对象,使用箭头函数, 需要显式地传递

==官方推荐使用前面两种方法定义事件, 因为使用箭头函数可能会造成不必要的渲染, 这是因为当你将箭头函数作为props传递给子组件的时候, 回调函数每次在render都会创建一个新的函数, 导致不必要的渲染==

状态提升

当某些数据多个子组件需要共同使用的时候, 可以将数据放到父组件统一进行处理,React称为状态提升

组合

在react中, 想跟vue在使用插槽, react称为组合, 可以很方便实现

import React from 'react'

class Combination extends React.Component {
  
  constructor(props) {
    super(props)
  }

  render() {
    return (
      <div>
        <div>{this.props.title}</div>
        <div>{this.props.left}</div>
        {this.props.children}
      </div>
    )
  }
}

function SlotPage () {
  return (
    <Combination title='这是组合组件, 也就是vue的插槽类似' left={<Left />}>
      <div>哈哈哈,我是子元素</div>
    </Combination>
  )
} 

function Left () {
  return (
    <div>我是左插槽</div>
  )
}

export default SlotPage

你可以理解成, 在React中, props是可以接受来自 class 和 React 元素作为 对象传到别的 组件中, 用于使用

Last Updated: 2022/06/25 19:16:57
你需要知道的Redux知识 React高级指引