# 一、react 简介

# 1、特点

  • 声明式编程(vue3)
  • 组件化开发(vue)
  • 跨平台开发

可以使用 React Native 编写移动端程序、使用 React VR 开发虚拟 web 应用

# 3、简单上手

  react 开发中,必须要有的三个包:

  • react
  • react-dom
  • babel(将 jsx 转换为 React.createElement)
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

    <!-- Don't use this in production: -->
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  </head>
  <body>
    <div id="root"></div>

    <!-- 必须加上type:让babel解析jsx语法 -->
    <script type="text/babel">
      const root = ReactDOM.createRoot(document.getElementById('root'))
      root.render(<h1>Hello, world!</h1>)
    </script>
  </body>
</html>

# 二、JSX 语法

# 1、标签使用

React 组件必须以大写字母开头,而 HTML 标签则必须是小写字母

<script type="text/babel">
  function MyApp() {
    return <h1>Hello, world!</h1>
  }

  // jsx -> React.createElement
  root.render(<MyApp />)
</script>

JSX 比 HTML 更加严格,必须闭合标签

<script type="text/babel">
  root.render(
    <>
      <h1>今日新闻</h1>
      <p>lencamo正在学习React</p>
    </>
  )
</script>

# 2、class 属性

使用 className 来指定一个 CSS 的 class

更多写法 ✨
<script type="text/babel">
  const isShow = true

  // 方式1:使用字符串
  // const classList = `one two ${isShow ? 'avatar' : ''}`

  // 方式2:使用数组
  const classList = ['one', 'two']
  if (isShow) classList.push('avatar')

  root.render(
    <>
      <h1>今日新闻</h1>
      {/* 方式1 */}
      <img className={classList} />

      {/* 方式2 */}
      <img className={classList.join(' ')} />
    </>
  )
</script>

提示

  在项目开发中,我们还可以使用第三方库:classnames (opens new window)

<script type="text/babel">
  const isShow = true

  root.render(
    <>
      <h1>今日新闻</h1>
      {/* 单个class */}
      <img className="avatar" />

      {/* 多个class */}
      <img className={`one two ${isShow ? 'avatar' : ''}`} />
    </>
  )
</script>

<style>
  .avatar {
    border-radius: 50%;
  }
</style>

# 3、内容渲染

  上面使用""传递的是字符串,而下面的{}传递的是 js 内容

这意味着 react 和 vue 应用,在 jsx 中是可以嵌入:表达式、运算符、待执行函数等

  • 普通数据

值为 undefinednullBoolean 显示为 空值

Object 类型不能直接作为内容在元素中显示(可以使用其中的具体值)

<script type="text/babel">
  let message = 'lencamo正在学习React'

  root.render(
    // 本质上讲就是后面要将的 <React.Fragment></React.Fragment>
    <>
      <h1>今日新闻</h1>
      <p>{message}</p>
    </>
  )
</script>
  • 使用对象

如下

# 3、style 属性

style={{}} 并不是一个特殊的语法,而是 style={ } JSX 大括号内的一个普通 {} 对象

<script type="text/babel">
  const user = {
    name: 'Hedy Lamarr',
    imageUrl: 'https://picsum.photos/200/',
    imageSize: 200
  }

  root.render(
    <>
      <h1>{user.name}</h1>
      <img
        src={user.imageUrl}
        alt={'Photo of ' + user.name}
        style={{
          width: user.imageSize,
          height: user.imageSize
        }}
      />
    </>
  )
</script>

# 三、更新界面

# 1、响应事件

不同场景下的 click 事件使用方式
<!-- 原生 -->
<button onclick="myFunction()">Click me</button>

<!-- 小程序中 -->
<button bindtap="myFunction">Click me</button>

<!-- vue事件 -->
<button @click="myFunction">Click me</button>

<!-- react事件 -->
<!-- 
  <button onClick={myFunction}>Click me</button> 
-->
<script type="text/babel">
  let count = 1

  function myFunction() {
    console.log('你点击了按钮')
    // count++ // 更改失败
  }

  root.render(
    <>
      <div>{count}</div>
      <button onClick={myFunction}>点击我.</button>
    </>
  )
</script>

# 2、数据更新 ✨

  上面的案例中,我们要更新 count 其实最暴力的方法就是重新渲染界面:

代码实现
function myFunction() {
  count++

  // 重新渲染
  root.render(
    <>
      <div>{count}</div>
      <button onClick={myFunction}>点击我.</button>
    </>
  )
}

  在后面的 react 类组件中,我们可以直接使用 this.setState()进行数据更新

提示

  在修改多层次数据(对象)时,通常不会直接修改它而是先进行浅拷贝,然后对浅拷贝对象进行修改,最后使用this.setState()进行全局替换

increment(index) {
  const newBooks = [...this.state.books]

  newBooks[index].count += 1
  this.setState({book: newBooks})
}

  原因是实际开发中,我们更多的是继承于 PureComponent,而不是 Component

# 3、参数传递

  事件传参本就没什么好讲的,想想还是简单的记录一下吧

<script type="text/babel">
  let numb = 1

  function myFunction1(event) {
    console.log(event)
  }

  function myFunction2(event, a, b) {
    console.log(a + b)
  }

  const root = ReactDOM.createRoot(document.getElementById('root'))
  root.render(
    <>
      {/* 传递event对象 */}
      <button onClick={myFunction1}>点击我.</button>
      <button onClick={(event) => myFunction1(event)}>点击我.</button>

      {/* 传递自定义参数 */}
      <button onClick={(event) => myFunction2(event, 1, numb)}>点击我.</button>
    </>
  )
</script>

# 四、逻辑渲染

  react 中的条件渲染、列表渲染和写 js 没什么区别:

# 1、类组件 ✨

  类组件需要 Component (opens new window) 的支持,其被定义为 React 组件的基类,类式组件仍然被 React 支持,但我们不建议在新代码中使用它们

react 类组件中的 this.setState() 和 小程序中的 this.setData() 功能相似

this 指向问题

  默认调用,其 this 默认为 window;但在 babel 严格模式下,其 this 指向undefined

  • 代码体验
<script type="text/babel">
  const obj = {
    foo: function () {
      console.log('foo:', this)
    }
  }
  obj.foo()

  const config = {
    onClick: obj.foo
    // onClick: obj.foo.bind(obj)
  }
  const click = config.onClick
  click()
</script>
类组件使用详情

  在类组件中使用 this 时,我们要注意对 this 是否做了绑定,防止出现 undefined 的情况。

class Demo extends React.Component {
  // 参与数据流
  constructor(props) {
    super(props)

    this.state = {
      count: 1
    }

    // this绑定方式1
    // this.myFunction = this.myFunction.bind(this)
  }

  myFunction() {
    // console.log(this)

    // 更新界面🤔
    this.setState({
      count: this.state.count + 1
    })
  }

  // this绑定方式2
  // myFunction = () => {
  //   // console.log(this)

  //   // 更新界面🤔
  //   this.setState({
  //     count: this.state.count + 1
  //   })
  // }

  render() {
    const { count } = this.state

    return (
      <>
        <div>{count}</div>
        {/* <button onClick={this.myFunction}>点击我.</button> */}
        {/* this绑定方式1 */}
        <button onClick={this.myFunction.bind(this)}>点击我.</button>

        {/* this绑定方式2 */}
        <button onClick={() => this.myFunction()}>点击我.</button>
      </>
    )
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<Demo />)

# 2、条件渲染

  在 react 中,并没有想 vue 中的 v-if、v-show 等指令,而是让开发者自由发挥,自己编写判断逻辑。

class Demo extends React.Component {
  // 使用if
  render() {
    let content
    if (isLoggedIn) {
      content = <AdminPanel />
    } else {
      content = <LoginForm />
    }

    return <div>{content}</div>
  }

  // 使用 三目运算
  render() {
    return <div>{isLoggedIn ? <AdminPanel /> : <LoginForm />}</div>
  }

  // 使用 &&
  render() {
    return <div>{isLoggedIn && <AdminPanel />}</div>
  }
}
用户登录案例
class Demo extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    const { isLoggedIn } = this.props

    if (isLoggedIn) {
      return <UserGreeting />
    }
    return <GuestGreeting />
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<Greeting isLoggedIn={false} />)
显示与隐藏案例 ✨

  前面我们已经知道了,在内容渲染时:如果值为 undefinednullBoolean 显示的空值

class Demo extends React.Component {
  // 参与数据流
  constructor(props) {
    super(props)

    this.state = {
      isShow: false,
      message: '内容显示成功!'
    }
  }

  changeShow() {
    this.setState({ isShow: !this.state.isShow })
  }

  render() {
    const { isShow, message } = this.state

    return (
      <>
        <button onClick={() => this.changeShow()}>显示/隐藏</button>

        {/* 类似于 vue 中的 `v-if` */}
        {isShow && <h2>{message}</h2>}

        {/* 类似于 vue 中的 `v-show` */}
        {<h2 style={{ display: isShow ? 'block' : 'none' }}>{message}</h2>}
      </>
    )
  }
}

# 3、列表渲染

  和 vue 一样,在 react 中进行列表渲染时同样也需要 key 属性。

  不同的是,需要自己采用数组方法进行进行元素的迭代创建。

<script type="text/babel">
  function Demo() {
    const products = [
      { title: 'Cabbage', id: 1 },
      { title: 'Garlic', id: 2 },
      { title: 'Apple', id: 3 }
    ]

    // 使用map函数
    const listItems = products.map((product) => {
      return <li key={product.id}>{product.title}</li>
    })

    // 支持放数组🤔
    return <ul>{listItems}</ul>
  }
</script>
电影列表案例
class Movies extends React.Component {
  // 参与数据流
  constructor(props) {
    super(props)

    this.state = {
      movies: ['西虹市首富', '红海行动', '星际穿越', '战狼', '我不是药神'],
      currentIndex: 0
    }
  }

  itemClick(index) {
    this.setState({ currentIndex: index })
  }

  render() {
    const { movies, currentIndex } = this.state

    return (
      <div>
        {/* 这部分可以根据个人喜好是否封装 */}
        <ul>
          {movies.map((item, index) => {
            return (
              <li
                className={currentIndex === index ? 'active' : ''}
                key={item}
                onClick={() => this.itemClick(index)}
              >
                {item}
              </li>
            )
          })}
        </ul>
      </div>
    )
  }
}
更新于 : 8/7/2024, 2:16:31 PM