React初体验-Hello React的组件化方式-React入门小案例

news2025/2/25 3:43:30

文章目录

    • React初体验
      • Hello React案例演练
      • Hello React案例升级
      • Hello React的组件化
        • 组件化的方式
        • 数据依赖
        • 事件绑定
    • 其他案例练习
      • 电影列表展示
      • 计数器的案例

React初体验

接下来我们通过Hello React的案例, 来体验一下React开发模式, 以及jsx的语法

Hello React案例演练

第一步: 先引入React开发依赖

<!-- crossorigin用来解决跨域 -->
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

第二步: 这里我们编写React的script代码中,必须添加 type="text/babel",作用是可以让babel解析jsx的语法

<script type="text/babel">
  // jsx语法编写react代码
</script>

第三步: 创建元素渲染到页面

React18之前的做法: 通过ReactDOM.render()函数进行渲染的, 需要传入两个参数

参数一: 要渲染的内容

参数二: 渲染的内容要挂载到的HTML元素

<!-- 挂载的HTML元素 -->
<div id="app"></div>

<!-- crossorigin用来解决跨域 -->
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<!-- jsx语法编写react代码 -->
<script type="text/babel">
  // React18之前的做法
  
  ReactDOM.render(<h2>Hello World</h2>, document.querySelector("#app"))
</script>

React18之后的做法: 通过ReactDOM. createRoot()函数进行渲染, 传入一个参数, 创建一个React根,之后渲染的内容会包含在这个根中(可以有多个根, 一般是一个根)

<!-- 挂载的元素 -->
<div id="app"></div>
<div id="root"></div>

<!-- crossorigin用来解决跨域 -->
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<!-- jsx语法编写react代码 -->
<script type="text/babel">
  // React18之后的做法
  
  const app = ReactDOM.createRoot(document.querySelector("#app"))
  const root = ReactDOM.createRoot(document.querySelector("#root"))
</script>

再通过root.render()函数向根组件中渲染元素, 参数传要渲染的元素

<!-- 挂载的元素 -->
<div id="app"></div>
<div id="root"></div>

<!-- crossorigin用来解决跨域 -->
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<!-- jsx语法编写react代码 -->
<script type="text/babel">
  // React18之后的做法
  const app = ReactDOM.createRoot(document.querySelector("#app"))
  app.render(<h2>Hello React</h2>)

  const root = ReactDOM.createRoot(document.querySelector("#root"))
  root.render(<h2>Hello React18</h2>)
</script>

在这里插入图片描述


Hello React案例升级

为了演练React,我们可以提出一个小的需求:

在界面显示一个文本:Hello World

点击下方的一个按钮,点击后再将文本改变为Hello React

在这里插入图片描述

第一步: 将元素渲染到页面

jsx中是通过{}绑定变量, 大家先对jsx语法有个体验即可, 后面会详细讲解jsx语法

<!-- 挂载的元素 -->
<div id="app"></div>

<!-- crossorigin用来解决跨域 -->
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<!-- jsx语法编写react代码 -->
<script type="text/babel">
  const app = ReactDOM.createRoot(document.querySelector("#app"))

  // 将文本定义成变量
  let message = "Hello World"

  // 第二个小括号表示括号内容是一个整体
  app.render((
    <div>
      <h2>{message}</h2>
      <button>改变文本</button>
    </div>
  ))
</script>

第二步: 监听按钮点击, 改变message的值

监听按钮点击jsx是通过onClick绑定一个函数, 注意C一定是大写的

const app = ReactDOM.createRoot(document.querySelector("#app"))

// 将文本定义成变量
let message = "Hello World"

// 定义一个函数, 处理按钮点击事件
function btnClick() {
  // 修改数据
  message = "Hello React"

  // 修改完成后需要重新渲染界面
  app.render((
    <div>
      <h2>{message}</h2>
      <button onClick={btnClick}>改变文本</button>
    </div>
  ))
}

// 第二个小括号表示括号内容是一个整体
app.render((
  <div>
    <h2>{message}</h2>
    <button onClick={btnClick}>改变文本</button>
  </div>
))

第三步: 简化代码, 上面代码中明显有重复代码, 我们可以抽取到一个函数中

const app = ReactDOM.createRoot(document.querySelector("#app"))

// 将文本定义成变量
let message = "Hello World"

// 定义一个函数, 处理按钮点击事件
function btnClick() {
  // 修改数据
  message = "Hello React"

  // 修改完成后需要重新渲染界面
  rootRander()
}

rootRander()
// 封装一个渲染函数
function rootRander() {
  // 第二个小括号表示括号内容是一个整体
  app.render((
    <div>
      <h2>{message}</h2>
      <button onClick={btnClick}>改变文本</button>
    </div>
  ))
}

Hello React的组件化

组件化的方式

Hello React这整个逻辑其实可以看做一个整体,那么我们就可以将其封装成一个组件:

root.render()函数的参数可以是一个HTML元素, 也可以是一个组件;

所以我们可以先将之前的业务逻辑封装到一个组件中,然后传入到 root.render 函数中的第一个参数;

在React中,如何封装一个组件呢?

React的组件分为两种: 类组件函数式组件

这里我们暂时使用类的方式封装组件:

定义一个类(类名大写,组件的名称是必须大写的,小写会被认为是HTML元素),继承自React.Component

// 类继承自React.Component, 才是组件
class App extends React.Component{}

实现当前组件的render函数, render当中返回的jsx内容,就是之后React会帮助我们渲染的内容

class App extends React.Component {
  // 类中render函数的返回值, 就是要渲染到页面的内容
  render() {
    return (
      <div>
        <h2>Hello World</h2>
        <button>改变文本</button>  
      </div>
    )
  }
}

const app = ReactDOM.createRoot(document.querySelector("#app"))
app.render(<App/>)

数据依赖

组件化问题一:数据在哪里定义?

在组件中的数据,我们可以分成两类:

参与界面更新的数据:当数据变量时,需要更新组件渲染的内容;

不参与界面更新的数据:当数据变量时,不需要更新将组建渲染的内容;

参与界面更新的数据我们也可以称之为是参与数据流,这个数据是定义在当前对象的state中(这个名字是固定的)

我们可以通过在类的构造器中 this.state = {定义的数据}

当我们的数据发生变化时,我们可以调用 this.setState 来更新数据,并且通知React进行update操作;

在进行update操作时,就会重新调用render函数,并且使用最新的数据,来渲染界面

class App extends React.Component {
  constructor() {
    super()

    this.state = {
      message: "Hello World"
    }
  }

  // 类中render函数的返回值, 就是要渲染到页面的内容
  render() {
    return (
      <div>
        <h2>{this.state.message}</h2>
        <button>改变文本</button>  
      </div>
    )
  }
}

const app = ReactDOM.createRoot(document.querySelector("#app"))
app.render(<App/>)

事件绑定

组件化问题二:事件绑定中的this

在类中直接定义一个函数,并且将这个函数绑定到元素的onClick事件上,那么问题来了当前这个函数中的this指向的是谁呢?

默认情况下是undefined

很奇怪,居然是undefined;

因为在正常的DOM操作中,监听点击,监听函数中的this其实是节点对象(比如说是button对象);

这次因为React并不是直接渲染成真实的DOM,我们所编写的button只是一个语法糖,它的本质React的Element对象;

那么在这里发生监听的时候,react在执行函数时并没有绑定this,默认情况下就是一个undefined;

我们在绑定的函数中,可能想要使用当前对象,比如执行 this.setState 函数,就必须拿到当前对象的this

我们就需要在传入函数时,需要给这个函数直接绑定this

类似于这种写法: <button onClick={this.changeText.bind(this)}>改变文本</button>

class App extends React.Component {
  constructor() {
    super()

    this.state = {
      message: "Hello World"
    }
  }

  btnClick() {
    // setState内部会做两件事情: 1.将state中的值改掉 2.自动执行render函数渲染页面
    this.setState({
      message: "Hello React"
    })
  }

  render() {
    return (
      <div>
        <h2>{this.state.message}</h2>
        <button onClick={this.btnClick.bind(this)}>改变文本</button>  
      </div>
    )
  }
}

const app = ReactDOM.createRoot(document.querySelector("#app"))
app.render(<App/>)

如果有多个按钮, 每次都需要编写this.btnClick.bind(this)是比较麻烦的, 因此React中还有另一种常见的写法, 在constructor在提前绑定this, 这样就可以直接使用方法

这也是官方文档在的做法

class App extends React.Component {
  constructor() {
    super()

    this.state = {
      message: "Hello World"
    }
    // 为方法提前绑定this
    this.btnClick = this.btnClick.bind(this)
  }

  btnClick() {
    this.setState({
      message: "Hello React"
    })
  }

  render() {
    return (
      <div>
        <h2>{this.state.message}</h2>
        <button onClick={this.btnClick}>改变文本</button>  
      </div>
    )
  }
}

const app = ReactDOM.createRoot(document.querySelector("#app"))
app.render(<App/>)

其他案例练习

电影列表展示

定义一个数组中存放电影, 再对电影列表进行展示

class App extends React.Component {
  constructor() {
    super()

    this.state = {
      movies: ["大话西游", "黑话律师", "独行月球"]
    }
  }

  render() {
    return (
      <div>
        <h2>电影列表</h2>
        <ul>
          <li>{this.state.movies[0]}</li>
          <li>{this.state.movies[1]}</li>
          <li>{this.state.movies[2]}</li>
        </ul>  
      </div>
    )
  }
}

const app = ReactDOM.createRoot(document.querySelector("#app"))
app.render(<App/>)

但是显然目前这种方法是好的, 我们最好对movies进行遍历展示, 而遍历的方式又有很多种, 先将下面两种方式

方式一: 对movies数组遍历放入一个新数组中

class App extends React.Component {
  constructor() {
    super()

    this.state = {
      movies: ["大话西游", "黑话律师", "独行月球"]
    }
  }

  render() {
    const liEls = []
    for (let item of this.state.movies) {
      const liEl = <li key={item}>{item}</li>
      liEls.push(liEl)
    }

    return (
      <div>
        <h2>电影列表</h2>
        <ul>
          {liEls}
        </ul>  
      </div>
    )
  }
}

const app = ReactDOM.createRoot(document.querySelector("#app"))
app.render(<App/>)

方式二: 使用map直接生成一个新数组, 直接将这个数组放入ul元素中

class App extends React.Component {
  constructor() {
    super()

    this.state = {
      movies: ["大话西游", "黑话律师", "独行月球"]
    }
  }

  render() {

    return (
      <div>
        <h2>电影列表</h2>
        <ul>
          {this.state.movies.map(item => <li key={item}>{item}</li>)}
        </ul>  
      </div>
    )
  }
}

const app = ReactDOM.createRoot(document.querySelector("#app"))
app.render(<App/>)

计数器的案例

接下来再使用React做一个熟悉的计数器案例

class App extends React.Component {
  constructor() {
    super()

    this.state = {
      conter: 0
    }

    // 为方法绑定this
    this.increment = this.increment.bind(this)
    this.decrement = this.decrement.bind(this)
  }

  increment() {
    this.setState({
      conter: this.state.conter + 1
    })
  }

  decrement() {
    this.setState({
      conter: this.state.conter - 1
    })
  }

  render() {
    return (
      <div>
        <h2>{this.state.conter}</h2>
        <button onClick={this.increment}>+</button>
        <button onClick={this.decrement}>-</button>
      </div>
    )
  }
}

const app = ReactDOM.createRoot(document.querySelector("#app"))
app.render(<App/>)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/408335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

〖大前端 - 基础入门三大核心之CSS篇⑲〗- CSS精灵的使用 与 background综合属性

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费开放&#xff0c;购买任意白宝书体系化专栏可加入TFS-CLUB 私域社区。福利&#xff1a;除了通过订阅"白宝书系列专栏"加入社区获取所有付费专栏的内容之外&#xff0c;还可以通过加入星荐…

vue pc项目 router.js 配置详解 ,vue项目中路由懒加载的正确使用,vue实现动态路由一步到位

这个是我之前一个项目的router.js 文件 xmjd import Vue from vue import http from ./plugins/axios import Router from vue-router import { getChnPinyin } from "/utils/chnpinyin"; import { clearLoginInfo, handlerMenu } from /utilsVue.use(Router) // 解…

css清除浮动的四种方法(详细)

浮动带来的影响 清除浮动主要是为了解决&#xff0c;父元素因为子级元素浮动引起的内部高度为0的问题 看下面一段代码 <div class"fater"><div class"box1">one</div><div class"box2">two</div></div> …

VUE中调用高德地图获取当前位置(VUE2.0和3.0通用)

标签&#xff1a; Vue vue 定位 js javascript1、去高德开放平台获取高德地图KEY地址&#xff1a;https://lbs.amap.com/注意&#xff1a;这里一定要选择WEB端的KEY&#xff0c;不要选择WEB服务的KEY&#xff0c;否则拿不到数据2、去项目中引入KEY&#xff0c;也就是CDN&#x…

基于RuoYi框架自动生成后端代码及前端界面

&#x1f3c0;&#xff08;1&#xff09;序言 &#x1f438;近来工作临近项目周期尾声&#xff0c;基本都是每天加班到晚上8到9点的节奏&#xff0c;似乎每年到10月份之际都是一个忙碌月&#xff0c;不知道这是一个&#x1f436;行业规律&#x1f436;还是仅仅对我而言的一个&a…

在vue中使用FullCanlendar实现日历预约会议室功能

最近接到任务,让实现一个预约功能,让我找找插件,需求是这个样子滴 明白任务以后,那咱就开抄呗~(bushi 开找 经过一番寻找,最后我决定使用FullCalendar,为啥用这个呢,你看它样子长的像不像我的需求,虽然说不上是有一些像吧,但简直就是一模一样. 更关键的是这玩意有很全的文档(但…

H5移动端适配方案rem/vw

前言 在讲解适配方案之前&#xff0c;我们聊聊为什么要做适配&#xff1f; 因为视口、逻辑像素、分辨率这些变量的不同&#xff0c;在每个设备展示都不一样&#xff0c;需要一种方案来统一。 物理像素&#xff1a;也就是分辨率&#xff0c;一个物理像素是显示器上的最小的物…

项目无法识别 ?. 语法,导致报错Module parse failed: Unexpected token

一、第一种情况是如果你需要引入的组件库源码的过程中&#xff0c;比如你要import一个封装好的组件这种场景&#xff1a; 首先找到报这个问题的地方 我这里是因为es语法问题 如果你也是npm安装了一个包&#xff0c;然后在导入的时候报这个语法错&#xff0c;那你可以接着往下…

【前端趋势】Vue、Vite作者尤雨溪前端趋势2022主题演讲

欢迎来到我的博客 &#x1f4d4;博主是一名大学在读本科生&#xff0c;主要学习方向是前端。 &#x1f36d;目前已经更新了【Vue】、【React–从基础到实战】、【TypeScript】等等系列专栏 &#x1f308;博客主页&#x1f449;codeMak1r.的博客 最新专栏【React–从基础到实战】…

Vant UI 中 van-collapse 下拉折叠面板如何默认展开第一项

问题重现 最近在做项目时&#xff0c;有一个需求是让 van-collapse 下拉折叠面板的第一项默认是展开状态&#xff1b;我使用到了 Vant UI 组件&#xff0c;首先按照官网文档的写法直接引入&#xff1a; <!--下拉折叠面板--><van-collapse class"collapse" …

vue路由的安装和使用

TOCVue 路由 vue-router 1 安装vue-router npm i vue-router -s 2 创建路由模块 // src/router/index.js就是当前项目的路由模块 // 1 导入Vue 和VueRouter的包 import Vue from vue import VueRouter from vue-router // 导入路由要用到的组件 import Home from ../component…

【TypeScript介绍】一文带你初步了解TypeScript

前言 博主主页&#x1f449;&#x1f3fb;蜡笔雏田学代码 专栏链接&#x1f449;&#x1f3fb;【TypeScript专栏】 今天开始学习学习TypeScript这门语言&#xff01; 感兴趣的小伙伴一起来看看吧~&#x1f91e; 文章目录TypeScript介绍1. TypeScript是什么2. TypeScript为什么要…

大文件上传

大文件上传原理 当我们在做文件上传的功能时&#xff0c;如果上传的文件过大&#xff0c;可能会导致长传时间特别长&#xff0c;且上传失败后需要整个文件全部重新上传。因此&#xff0c;我们需要前后端配合来解决这个问题。 最常用的解决方案就是 —— 切片上传。 这次我们…

图文详解uni-app PC端宽屏适配方案

图文详解uni-app PC端宽屏适配方案 随着互联网的发展&#xff0c;iOS、Android、H5以及各种小程序快应用层出不穷&#xff0c;随之而来的问题就是如何用一套代码&#xff0c;适配多个平台&#xff0c;其中uni-app表现优异&#xff0c;已经实现了手机端全覆盖&#xff0c;支持i…

【JavaScript速成之路】JavaScript对象

&#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f525;系列专栏&#xff1a;【JavaScript速成之路】 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; 文章目录前言1&#xff0c;初识对象1.1&#xff0c;对象概念1.2&#xff0c;对象创建1.2.…

手撕前端面试题【JavaScript】

前端的那些基本标签&#x1f353;&#x1f353; 浅拷贝&#x1f353;&#x1f353;简易深拷贝&#x1f353;&#x1f353;深拷贝&#x1f353;&#x1f353;什么是深拷贝&#xff0c;什么是浅拷贝&#xff0c;二者有什么区别&#xff0c;平时改怎么区分呢&#xff1f;&#x1f…

vue3.0本地引入vue.js

第一步获取vue版本 Vue的各种版本介绍&#xff1a; cjs&#xff08;两个版本都是完整版&#xff0c;包含编译器&#xff09; vue.cjs.js vue.cjs.prod.js&#xff08;开发版&#xff0c;代码进行了压缩&#xff09; global&#xff08;这四个版本都可以在浏览器中直接通过…

Vue中 provide、inject 详解及使用

传送门&#xff1a;Vue中 子组件向父组件传值 及 .sync 修饰符 详解 传送门&#xff1a;Vue中 状态管理器&#xff08;vuex&#xff09;详解及应用场景 传送门&#xff1a;Vue中 $ attrs、$ listeners 详解及使用 传送门&#xff1a;Vue中 事件总线&#xff08;eventBus&#x…

New Bing申请与使用教程

&#xff08;1&#xff09;安装 Edge 浏览器插件&#xff1a; 由于在 CN 访问 Bing 国际版会自动跳转到 CN 版&#xff0c;因此需要先重定向浏览器的 Header&#xff0c;先在 Edge 浏览器安装插件&#xff1a;Header Editor&#xff1a; 添加如下配置&#xff08;其中&#xf…

① 尚品汇的后台管理系统【尚硅谷】【Vue】

后台管理系统项目简介 什么是后台管理系统项目&#xff1f; 在前端领域当中&#xff0c;开发后台管理系统项目&#xff0c;并非是Java&#xff0c;PHP等后台语言项目 在前面课程当中&#xff0c;我们已经开发了一个项目【尚品汇电商平台项目】&#xff0c;这个项目主要针对的是…