likes
comments
collection
share

前端小白学 React 框架(一)

作者站长头像
站长
· 阅读数 10

React

最近打算在科研之余开始学习 React 框架,感觉大厂都用的 React 比较多,因此想搞一个专栏放学习 React 时的笔记,方便以后查找阅读吧 🥳,共勉。

React 的介绍

React 是什么

前端小白学 React 框架(一)

React 的特点

  • 声明式: React 使创建交互式 UI 变得轻而易举。为你应用的每一个状态设计简洁的视图,当数据变动时 React 能高效更新并渲染合适的组件。以声明式编写 UI,可以让你的代码更加可靠,且方便调试。
  • 组件化: 构建管理自身状态的封装组件,然后对其组合以构成复杂的 UI。由于组件逻辑使用 JavaScript 编写而非模板,因此你可以轻松地在应用中传递数据,并保持状态与 DOM 分离。
  • ### 多跨平台适配: 无论你现在使用什么技术栈,在无需重写现有代码的前提下,通过引入 React 来开发新功能。React 还可以使用 Node 进行服务器渲染,或使用 React Native 开发原生移动应用。

声明式编程:

声明式编程是目前整个大前端开发的模式: Vue、React、Flutter、SwiftUl;它允许开发者只需要维护自己的状态,当状态改变时,React可以根据最新的状态去渲染UI界面。

前端小白学 React 框架(一)

组件化开发:

组件化开发页面目前前端的流行趋势,会将复杂的界面拆分成一个个小的组件;如何合理的进行组件的划分和设计也是学习的一个重点。

前端小白学 React 框架(一)

### 多平台适配:

  • 2013年,React发布之初主要是开发Web页面
  • 2015年,Facebook推出了ReactNative,用于开发移动端跨平台;(虽然目前Flutter非常火爆,但是还是有很多公司在使用ReactNative)
  • 2017年,Facebook推出ReactVR,用于开发虚拟现实Web应用程序;(VR也会是一个火爆的应用场景)

前端小白学 React 框架(一)

开发 React 前的热知识🔥

开发React必须依赖三个库:

  1. react: 包含react所必须的核心代码
  2. react-dom: react渲染在不同平台所需要的核心代码
  3. babel: 将jsx转换成React代码的工具

第一次接触React会被它繁琐的依赖搞蒙,居然依赖这么多东西:

  • 对于Vue来说,我们只是依赖一个vuejs文件即可,但是react居然要依赖三个包
  • 其实呢,这三个库是各司其职的,目的就是让每一个库只单纯做自己的事情
  • 在React的0.14版本之前是没有react-dom这个概念的,所有功能都包含在react里

为什么要进行拆分呢?

  • react包中包含了react web和react-native所共同拥有的核心代码
  • react-dom针对web和native所完成的事情不同:
    • web端: react-dom会将jsx最终渲染成真实的DOM,显示在浏览器中
    • native端: react-dom会将isx最终渲染成原生的控件(比如Android中的Button,iOS中的UIButton)。

原因就是react-native

Babel 和 React 的关系

  1. babel是什么呢? Babel,又名 Babel.js,是目前前端使用非常广泛的编译器、转移器。比如当下很多浏览器并不支持ES6的语法,但是确实ES6的语法非常的简洁和方便,我们开发时希望使用它,那么编写源码时我们就可以使用ES6来编写,之后通过Babel工具,将ES6转成大多数浏览器都支持的ES5的语法。

  2. React和Babel的关系 默认情况下开发React其实可以不使用babel,但是前提是我们自己使用React.createElement 来编写源代码,它编写的代码非常的繁琐和可读性差,那么我们就可以直接编写jsx (JavaScript XML) 的语法,并且让babel帮助我们转换成React.createElement

Hello React 案例

为了演练React,我们可以提出一个小的需求:在界面显示一个文本:Hello World,点击下方的一个按钮,点击后文本改变为Hello React。

前端小白学 React 框架(一)

React 的依赖引入

根据上面所说的,我们在编写React代码时,需要引入三个依赖,且这三个依赖都是必不可少的。那么,添加这三个依赖有如下方式:

  • 方式一: 直接CDN引入
  • 方式二:下载后,添加本地依赖
  • 方式三: 通过npm管理 (后续脚手架再使用)

暂时我们直接通过CDN引入,来演练下面的示例程序,这里有一个crossorigin的属性,这个属性的目的是为了拿到跨域脚本的错误信息

<!-- 1.引入React核心库-得到一个React对象 -->
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<!-- 2.引入React扩展库-得到ReactDOM对象 -->
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<!-- 3.引入babel-作用是将jsx转化为浏览器能够识别的js语法 --> 
<!-- 注:若是在开发过程中使用到了jsx语法(或使用es6等js高级语法)则引入babel,否则不需要引入 -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

❌ 注意:以上React库的CDN链接🔗来自React的官方文档中CDN连接Babel的CDN在这里👉 【在网站中添加 React】,使用CDN链接进行开发只能在开发环境使用,且引入顺序:必须先引入核心库再引入扩展库。

❌ 注意:如果想要使用babel,需要在script标签中加上type="text/babel",否则babel不会对script里的代码进行转换。

  1. 在页面上渲染一个页面结构
// React 18
const root = ReactDOM.createRoot(document.querySelector('#root'));
render();

function render() {
  root.render((
    <div>
      <h2>{message}</h2>
      <button onClick={btnClick}>修改文本</button>
    </div>
  ));
}
  1. 首先将文本定义成变量message,把文本内容设置成变量来进行数据管理
let message = 'Hello World';
  1. 定义一个回调函数,监听按钮的点击事件
function btnClick() {
  // ...
}
  1. 修改message变量后重新渲染页面即可
function btnClick() {
  message = 'Hello React';
  render();
}

Hello React 组件化开发

如果当整个逻辑其实可以看做一个整体,那么我们就可以将其封装成一个组件,因为root.render的参数是一个HTML元素或者一个组件,所以我们可以先将之前的业务逻辑封装到一个组件中,然后传入到 ReactDOM.render 函数中的第一个参数。

这里我们暂时使用类的方式封装一个组件,首先定义一个类类名大写,组件的名称是必须大写的,小写会被认为是HTML元素),继承自React.Component,然后实现当前组件的render函数render当中返回的JSX内容,就是之后React会帮助我们渲染的内容。

那么使用类组件的形式将静态页面渲染出来看看效果如何 😆

 // 使用类组件的形式重写example1的案例
class App extends React.Component {
  // 渲染方法的方法名必须为render
  render() {
    return (
      <div>
        <h2>Hello World</h2>
        <button>修改文本</button>
      </div>
    )
  }
}

const root = ReactDOM.createRoot(document.querySelector('#root'));
root.render(<App />);

有了静态页面后,下一个问题就是数据在哪里定义?,在组件中的数据,我们可以分成两类:

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

其中参与数据流,这个数据是定义在当前对象的state中,我们可以通过在构造函数中this.state = {定义的数据},当我们的数据发生变化时,我们可以调用this.setState来更新数据,并且通知React进行update操作,在进行update操作时,就会重新调用render函数,并且使用最新的数据,来渲染界面。那么把上面的代码改动一下:

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      message: 'Hello World'
    }
  }

  render() {
    return (
     // ...
     <h2>{this.state.message}</h2>
     // ...
    )
  }
}

接下来就是绑定函数,这里会有个小问题,因为React更新state是使用的this.setState方法,而如果像如下代码绑定函数将会出现问题,大家可以在控制台中查看打印信息:

class App extends React.Component {
  btnClick() {
    console.log('btnClick', this);
    this.setState({
      message: 'Hello React'
    })
  }
  
  render() {
    return (
      <div>
        <h2>{this.state.message}</h2>
        <button onClick={this.btnClick}>修改文本</button>
      </div>
    )
  }
}

你会发现打印的是btnClick undefined,然后一堆的报错信息:

前端小白学 React 框架(一)

出现以上错误的原因就是因为this指向出现了问题,在类中直接定义一个函数,并且将这个函数绑定到元素的onClick事件上,当前这个函数的this指向默认情况下undefined

💡 因为在正常的DOM操作中,监听点击,监听函数中的this其实是节点对象(比如说是button对象),而React并不是直接渲染成真实的DOM,我们所编写的button只是一个语法糖,它的本质React的Element对象,那么在这里发生监听的时候,react在执行函数时并没有绑定this,默认情况下就是一个undefined。

那么需要给它纠正一下,具体修改方法我们参见官方文档中的事件处理

class App extends React.Component {
    constructor() {
        // ...
        // 为了在回调中使用 `this`,这个绑定是必不可少的
        this.btnClick = this.btnClick.bind(this);
    }
}

其实除了上面这种写法,还有下面一种写法:

<button onClick={this.btnClick.bind(this)>改变文本</button>

但是这种写法,如果在render函数中要多次绑定btnClick方法,那么每绑定一次都写一遍bind,这样感觉比麻烦,因此可能更加推荐官方的那种写法 🥳。

写在最后

如果大家喜欢的话可以收藏本专栏,之后会慢慢更新,然后大家觉得不错可以点个赞或收藏一下 🌟。

本节的源码放在作者的GitHub仓库里,分别是:

转载自:https://juejin.cn/post/7232549203006849080
评论
请登录