React(coderwhy)- 01(介绍及基础)

React是一个用于构建用户界面的JavaScript库,强调声明式编程和组件化开发。文中介绍了React的基础,包括如何使用React、ReactDOM和Babel,以及如何创建和渲染组件。文章还详细讨论了组件的状态管理和事件处理,展示了如何通过JSX语法定义和更新UI,并提供了计数器和电影列表展示的示例。此外,提到了React选择JSX的原因和其工作原理,以及如何利用create-react-app创建React项目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

React的介绍(技术角度)

React是什么?
  1. React:用于构建用户界面的 JavaScript 库
  2. React的官网文档https://zh-hans.reactjs.org/

React的特点:

  1. 声明式编程
  2. 组件化开发
  3. 多平台适配

Hello React

react需要3个依赖,( 可以使用官方CDN )

  1. react : 包含react所必须的核心代码
  2. react_dom : react渲染在不同平台所需要的核心代码
  3. babel :将jsx转换成React代码的工具
  <div id="app"></div>
  
  <script src="./lib/react.js"></script>
  <script src="./lib/react_dom.js"></script>
  <script src="./lib/babel.js"></script>
  <script type="text/babel">
    // 1.定义变量
    const message = "Hello World"

    // 2.渲染内容
    const root = ReactDOM.createRoot(document.querySelector("#app"))
    root.render(<h2>{message}</h2>)
  </script>

点击按钮修改内容:

   需要只用render方法来修改

<script type="text/babel">
    // 1.定义变量
    let message = "Hello World"
    const btnClick = () => {
      message = "Hello React"
      render()
    }

    // 2.渲染内容
    const root = ReactDOM.createRoot(document.querySelector("#app"))
    render()

    function render() {
      root.render((
        <div>
          <h2>{message}</h2>
          <button onClick={btnClick}>修改文本</button>
        </div>
      ))
    }
  </script>

Hello React – 组件化开发

整个逻辑其实可以看做一个整体,那么我们就可以将其封装成一个组件:
        1. 我们说过root.render 参数是一个HTML元素或者一个组件
        2. 所以我们可以先将之前的业务逻辑封装到一个组件中,然后传入到 ReactDOM.render 函数中的第一个参数;
在React中,如何封装一个组件呢?这里我们暂时使用类的方式封装组件:
        1. 定义一个类(类名大写,组件的名称是必须大写的,小写会被认为是HTML元素),继承自React.Component
        2. 实现当前组件的render函数
        render当中返回的jsx内容,就是之后React会帮助我们渲染的内容
  <script type="text/babel">
    function foo() {
      console.log("foo", this)
    }

    // 1.定义根组件
    class App extends React.Component {
      constructor() {
        super()
        this.state = {
          message: "Hello World"
        }
      }

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

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

    // 2.渲染根组件
    const root = ReactDOM.createRoot(document.querySelector("#root"))
    root.render(<App/>)
  </script>

组件化 - 数据依赖

组件化问题一:数据在哪里定义
在组件中的数据,我们可以分成两类:
        1. 参与界面更新的数据:当数据变量时,需要更新组件渲染的内容;
        2. 不参与界面更新的数据:当数据变量时,不需要更新将组建渲染的内容;
参与界面更新的数据我们也可以称之为是参与数据流,这个数据是定义在当前对象的state
        1. 我们可以通过在构造函数中 this.state = {定义的数据}
        2. 当我们的数据发生变化时,我们可以调用 this.setState 来更新数据,并且通知React进行update操作;
        在进行update操作时,就会重新调用render函数,并且使用最新的数据,来渲染界面

组件化 – 事件绑定

组件化问题二:事件绑定中的this
        在类中直接定义一个函数,并且将这个函数绑定到元素的onClick事件上,当前这个函数的this指向的是谁呢?
默认情况下是undefined
        1. 很奇怪,居然是undefined
        2. 因为在正常的DOM操作中,监听点击,监听函数中的this其实是节点对象(比如说是button对象);
        3. 这次因为React并不是直接渲染成真实的DOM,我们所编写的button只是一个语法糖,它的本质React的Element对象;
        4. 那么在这里发生监听的时候,react在执行函数时并没有绑定this,默认情况下就是一个undefined;
        
我们在绑定的函数中,可能想要使用当前对象,比如执行 this.setState 函数,就必须拿到当前对象的this
        1. 我们就需要在传入函数时,给这个函数直接绑定this
        2. 类似于下面的写法: <button onClick={this.changeText.bind(this)}>改变文本</button>

电影列表展示

<script type="text/babel">
    // 1.定义根组件
    class App extends React.Component {
      constructor() {
        super()
        this.state = {
          message: "Hello App",
          movies: ["星际穿越", "大话西游", "盗梦空间", "少年派的奇幻漂流"]
        }
      }

      render() {
        return (
          <ul>
            {
              this.state.movies.map(item => {
                return <li key={item}>{item}</li>
              })
            }
          </ul>
        )
      }
    }

    // 2.渲染根组件
    const root = ReactDOM.createRoot(document.querySelector("#root"))
    root.render(<App/>)
  </script>

计数器案例

  <script>
    function foo() {
      console.log("foo:", this);
    }

    foo()

    // 1.定义根组件
    class App extends React.Component {
      constructor() {
        super()
        this.state = {
          counter: 0
        }
      }

      render() {
        const { counter } = this.state
        return (
          <div>
            <h2>当前计数: {counter}</h2>
            <button onClick={this.increment.bind(this)}>+1</button>
            <button onClick={this.decrement.bind(this)}>-1</button>
          </div>
        )
      }

      increment() {
        this.setState({
          counter: this.state.counter + 1
        })
      }
      decrement() {
        this.setState({
          counter: this.state.counter - 1
        })
      }
    }

    // 2.渲染根组件
    const root = ReactDOM.createRoot(document.querySelector("#root"))
    root.render(<App/>)
  </script>

VSCode代码片段

我们在前面练习React的过程中,有些代码片段是需要经常写的,我们在VSCode中我们可以生成一个代码片段,方便我们快速
生成。
VSCode中的代码片段有固定的格式,所以我们一般会借助于一个在线工具来完成。
具体的步骤如下:
        第一步,复制自己需要生成代码片段的代码;
        第二步,https://snippet-generator.app/在该网站中生成代码片段;
        第三步,在VSCode中配置代码片段;

React基础

JSX语法

这段element变量的声明右侧赋值的标签语法是什么呢?
        1.它不是一段字符串(因为没有使用引号包裹);
        2.它看起来是一段HTML元素,但是我们能在js中直接给一个变量赋值html吗?
        3.其实是不可以的,如果我们将 type="text/babel" 去除掉,那么就会出现语法错误;
        4.它到底是什么呢?其实它是一段jsx的语法
JSX是什么?
        1.JSX是一种JavaScript的语法扩展(eXtension),也在很多地方称之为JavaScript XML,因为看起就是一段XML语法
        2.它用于描述我们的UI界面,并且其完成可以和JavaScript融合在一起使用
        3.它不同于Vue中的模块语法,你不需要专门学习模块语法中的一些指令(比如v-for、v-if、v-else、v-bind);
  <script type="text/babel">
    // 1.定义根组件
    const element = <div>Hello World</div>

    // 2.渲染根组件
    const root = ReactDOM.createRoot(document.querySelector("#root"))
    root.render(element)
  </script>
为什么React选择了JSX  ?
React认为渲染逻辑本质上与其他UI逻辑存在内在耦合
        1.比如UI需要绑定事件(button、a原生等等);
        2.比如UI中需要展示数据状态;
        3.比如在某些状态发生改变时,又需要改变UI
他们之间是密不可分,所以React没有将标记分离到不同的文件中,而是将它们组合到了一起,这个地方就是组件(Component)
         当然,后面我们还是会继续学习更多组件相关的东西;
在这里,我们只需要知道,JSX其实是嵌入到JavaScript中的一种结构语法;
JSX的书写规范:
        1.JSX的顶层只能有一个根元素,所以我们很多时候会在外层包裹一个div元素(或者使用后面我们学习的Fragment);
        2.为了方便阅读,我们通常在jsx的外层包裹一个小括号(),这样可以方便阅读,并且jsx可以进行换行书写;
        3.JSX中的标签可以是单标签,也可以是双标签
        注意:如果是单标签,必须以/>结尾;

JSX的基本使用

jsx中的注释
{/*  要注释的内容  */}
JSX嵌入变量作为子元素
 情况一:当变量是Number、String、Array类型时,可以直接显示
情况二:当变量是null、undefined、Boolean类型时,内容为空;
如果希望可以显示null、undefined、Boolean,那么需要转成字符串;
转换的方式有很多,比如toString方法、和空字符串拼接,String(变量)等方式;
情况三Object对象类型不能作为子元素(not valid as a React child)
JSX嵌入表达式
运算表达式
三元运算符
执行一个函数
jsx绑定属性
比如元素都会有title属性   : 使用{xxx变量}的方式绑定 ==>   <h2 title={title}><h2/>
比如img元素会有src属性 
比如a元素会有href属性 
比如元素可能需要绑定class  :  三元表达式、数组、 第三方库
比如原生使用内联样式style : {{ key value }} ,不能写- ,要写驼峰

JSX的事件绑定

如果原生DOM原生有一个监听事件,我们可以如何操作呢?
方式一:获取DOM原生,添加监听事件;
方式二:在HTML原生中,直接绑定onclick;
在React中是如何操作呢?我们来实现一下React中的事件监听,这里主要有两点不同
React 事件的命名采用小驼峰式(camelCase),而不是纯小写
我们需要通过{}传入一个事件处理函数,这个函数会在事件发生时被执行;
this的绑定问题
在事件执行后,我们可能需要获取当前类的对象中相关的属性,这个时候需要用到this
如果我们这里直接打印this,也会发现它是一个undefined
为什么是undefined呢?
原因是btnClick函数并不是我们主动调用的,而且当button发生改变时,React内部调用了btnClick函数;
而它内部调用时,并不知道要如何绑定正确的this;
如何解决this的问题呢?
方案一:bind给btnClick显示绑定this
方案二:使用 ES6 class fields 语法
方案三:事件监听时传入箭头函数(个人推荐)
事件参数传递
在执行事件函数时,有可能我们需要获取一些参数信息:比如event对象、其他参数
情况一:获取event对象
很多时候我们需要拿到event对象来做一些事情(比如阻止默认行为)
那么默认情况下,event对象有被直接传入,函数就可以获取到event对象;
情况二:获取更多参数
有更多参数时,我们最好的方式就是传入一个箭头函数主动执行的事件函数,并且传入相关的其他参数

JSX的条件渲染

  • if判断

  • 三元运算符

  • &&逻辑与

  • v-show实现效果

JSX的列表渲染

  • map高阶函数(重要)

  • filter

  • slice

循环要加 key

JSX的原理和本质

实际上,jsx 仅仅只是 React.createElement(component, props, ...children) 函数的语法糖。
所有的jsx最终都会被转换成React.createElement的函数调用。
createElement需要传递三个参数:
参数一:type
当前ReactElement的类型;
如果是标签元素,那么就使用字符串表示 “div”;
如果是组件元素,那么就直接使用组件的名称;
参数二:config
所有jsx中的属性都在config中以对象的属性和值的形式存储;
比如传入className作为元素的class;
参数三:children
存放在标签中的内容,以children数组的方式进行存储;
当然,如果是多个元素呢?React内部有对它们进行处理,处理的源码在下方

购物车案例


React脚手架解析

认识脚手架工具

对于现在比较流行的三大框架都有属于自己的脚手架:
Vue的脚手架:@vue/cli
Angular的脚手架:@angular/cli
React的脚手架:create-react-app
它们的作用都是帮助我们生成一个通用的目录结构,并且已经将我们所需的工程环境配置好。
使用这些脚手架需要依赖什么呢?
目前这些脚手架都是使用node编写的,并且都是基于webpack的;
所以我们必须在自己的电脑上安装node环境
这里我们主要是学习React,所以我们以React的脚手架工具:create-react-app作为讲解

create-react-app

创建Eeact项目

创建React项目的命令如下:
注意:项目名称不能包含大写字母
另外还有更多创建项目的方式,可以参考GitHub的readme
创建完成后,进入对应的目录,就可以将项目跑起来:
创建React项目
create-react-app 项目名称
cd 01-test-react
yarn start

 了解 PWA

整个目录结构都非常好理解,只是有一个PWA相关的概念:
PWA全称Progressive Web App,即渐进式WEB应用
一个 PWA 应用首先是一个网页, 可以通过 Web 技术编写出一个网页应用
随后添加上 App Manifest Service Worker 来实现 PWA 的安装和离线等功能;
这种Web存在的形式,我们也称之为是 Web App
PWA解决了哪些问题呢?
可以添加至主屏幕,点击主屏幕图标可以实现启动动画以及隐藏地址栏;
实现离线缓存功能,即使用户手机没有网络,依然可以使用一些离线功能;
实现了消息推送
等等一系列类似于Native App相关的功能;
更多PWA相关的知识,可以自行去学习更多;
https://developer.mozilla.org/zh-CN/docs/Web/Progressive_web_apps

webpack的配置

默认给隐藏起来了

从零编写代码
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值