React的基本使用

介绍

根据官网介绍,React是用于构建用户界面的 JavaScript 库,起源于 Facebook 的内部项目,后又用来架设Instagram的网站,并于 2013 年5月开源。React在国内也是非常火爆的,很多中大厂都在使用,是每一个前端都应该掌握的库。

不使用脚手架引入React

  1. 首先创建一个空文件夹。
mkdir react-test
cd .\react-test\
  1. 初始化包管理工具并安装React包。
npm init -y              # or yarn init -y
npm i react react-dom    # or yarn add react react-dom
  1. 新建index.html文件并引入React相关js文件。
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello React!</title>
  </head>
  <body></body>
  // 引入React相关js文件
  <script src="./node_modules/react/umd/react.development.js"></script>
  <script src="./node_modules/react-dom/umd/react-dom.development.js"></script>
</html>
  1. 创建一个React元素,并且渲染到页面上。
<body>
  <!-- 1. 首先在结构中需要有一个根标签。-->
  <div id="root"></div>
</body>
<script src="./node_modules/react/umd/react.development.js"></script>
<script src="./node_modules/react-dom/umd/react-dom.development.js"></script>
<script>
  // 2. 创建一个React元素
  /**
   * 方法说明
   * React.createElement(type,[props],[...children])
   * - 返回值:React元素 
   * - 第一个参数:要创建的React元素名称 (**html规范定义的标签**)
   * - 第二个参数:该React元素的属性 
   * - 第三个及其以后的参数:该React元素的子节点 
   * 
  */
  const h1 = React.createElement('h1',null, 'Hello React!');
  /**
   * 方法说明
   * ReactDOM.render(element, container[, callback])
   * - 返回值:对根组件 ReactComponent 实例的引用
   * - 第一个参数:要渲染的React元素 
   * - 第二个参数:DOM对象,用于指定渲染到页面中的位置
  */
  ReactDOM.render(h1,document.getElementById('root'));
</script>
</html>
  1. 此时页面的DOM结构应该是这样的:
<div id="root">
  <h1>Hello React!</h1>
</div>

注意:如果你安装的包版本在v18.0.0以下,那么以上代码是没什么问题的,但如果你安装的是v18.0.0及以上,那么你会发现页面虽然正常渲染了,但是控制台会报错。

原因是React18已经弃用了这个API,所以我们要换一种写法:

<script>
  const root = ReactDOM.createRoot(document.getElementById('root'));
  const h1 = React.createElement('h1', null, 'React18 新API!');
  root.render(h1);
</script>

使用脚手架搭建React项目

在实际工作中,我们基本上都是使用脚手架进行项目的搭建,这样可以高效利用 Webpack、Babel、ESLint 等工具辅助项目开发,让我们自身更关注业务,而不是配置。

  1. 初始化项目
npx create-react-app my-app
  1. 初始化完成后,进入项目目录,启动项目。
npm start
  1. 打开控制台输出的地址即可。

JSX的基本使用

1.基本用法

声明式的编写UI是React的特点之一,JSX就是在JavaScript代码中写XML(HTML)格式的代码。

//jsx写法
const title = <h1>Hello JSX</h1>

注意:JSX并不是标准的 ECMAScript 语法,它是 ECMAScript 的语法扩展,需要使用 babel 编译处理后,才能在浏览器环境中使用,create-react-app 脚手架中已经默认有该配置,无需手动配置。 让我们来看上面的代码经过Babel转化后的代码是什么样的吧。

// babel 转化后的代码
"use strict";

const title = /*#__PURE__*/React.createElement("h1", null, "Hello JSX");

由此可见,其实JSX就是React.createElement()的一个语法糖。

2.嵌入JS表达式

  • 语法:{ JavaScript表达式 }
  • 支持的数据类型:值、变量、函数调用、三元运算符、数组(项为基本类型或JSX)。
const root = ReactDOM.createRoot(document.getElementById('root'));

const name = '翠花';
const getAge = function () {
  return 18;
}
const hobbyArr = ['唱歌、', '跳舞、', '烫头']
const div = (
  <div>
    <div>你的名字是:{ name }</div>
    <div>你今年{ getAge() }岁了</div>
    <div>你喜欢{hobbyArr}</div>
    <div>你昨天吃的是{ Math.round(Math.random() * 10) % 2 === 0 ? '火锅' : '烤肉' }</div>
  </div>
)

root.render(
  div
);

渲染结果:

3.条件渲染

三元表达式

const root = ReactDOM.createRoot(document.getElementById('root'));
const sex = Math.round(Math.random() * 10) % 2 === 0 ? '女' : '男';
const div = (
  <div>
    <div>热门推荐:{ sex === '男' ? <span>电脑、手机、耳机</span> : <span>口红、眼线、眉笔</span>}</div>
  </div>
)

函数返回

const root = ReactDOM.createRoot(document.getElementById('root'));
const sex = Math.round(Math.random() * 10) % 2 === 0 ? '女' : '男';
function getHot() {
  if (sex === '男') return <span>电脑、手机、耳机</span>;
  return <span>口红、眼线、眉笔</span>;
}
const div = (
  <div>
    <div>热门推荐:{ getHot() }</div>
  </div>
)
root.render(
  div
);

渲染结果:

4.列表渲染

const root = ReactDOM.createRoot(document.getElementById('root'));
const personArr = [
  {
    id: 1,
    name: '小张',
    age: '20',
    sex: '男'
  },
  {
    id: 2,
    name: '小红',
    age: '18',
    sex: '女'
  },
  {
    id: 3,
    name: '小绿',
    age: '25',
    sex: '男'
  },
]
const div = (
  <div>
    <div>人员列表</div>
    <ul>
      {personArr.map(p => <li key={p.id}>姓名:{p.name} 性别: { p.sex } 年龄: {p.age}</li>) }
    </ul>
  </div>
)
root.render(
  div
);

渲染结果:

5.样式处理

  • 语法:{{ css键值对 }}
  • 可以使用类名控制也可以使用行内样式
import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root'));

const div = (
  <div>
    <div className="title">标题</div>
    <p style={{ color: 'red' }}>正文一</p>
    <p style={{ color: 'blue' }}>正文二</p>
    <p style={{ color: 'green' }}>正文三</p>
  </div>
)

root.render(
  div
);
.title {
  font-size: 40px;
  font-weight: bold;
}

渲染结果:

组件的创建

1.使用函数创建组件

注意事项:

  1. 函数名称必须以大写字母开头,使用大驼峰命名法
  2. 函数组件必须有返回值,表示该组件的结构 (html=>长啥样)
  3. 组件标签可以单闭合
const root = ReactDOM.createRoot(document.getElementById('root'));
function Com() {
  return (
    <div>这是函数组件</div>
  )
}
root.render(
  <Com/>
);

2.使用class创建组件

语法:

  • 类组件:使用 ES6 的 class关键字 创建的组件
  • 类组件应该继承 React.Component 父类,从而可以使用父类中提供的方法和属性
  • 类里边实现父类提供的render(),返回一个模版

注意事项:

  • 类名称也必须以大写字母开头,使用大驼峰命名法
  • 类组件必须提供 render() 方法
  • render() 方法必须有返回值,表示该组件的html(jsx)结构
class Com extends React.Component {

  render() {
    return (
      <div>这是使用class创建的组件</div>
    )
  }
}

root.render(
  <Com/>
);

DOM事件处理

1.事件绑定与事件对象传递

class Com extends React.Component {
  handlerClick(e) {
    // react会默认帮我们把"合成事件对象"返回在第一个参数
    console.log(e);
    console.log('点击');
  }
  render() {
    return (
      <div>
        <button onClick={this.handlerClick}>button</button>
      </div>
    )
  }
}

2.this指向问题

class Com extends React.Component {
  handlerClick() {
    // 事件触发时 并不是实例调用的 所以获取不到this
    console.log(this); // log: undefined
    console.log('点击');
  }
  render() {
    return (
      <div>
        <button onClick={this.handlerClick}>button</button>
      </div>
    )
  }
}

解决方法

  1. 使用bind
class Com extends React.Component {
  handlerClick() {
    console.log(this);
    console.log('点击');
  }
  render() {
    return (
      <div>
        <button onClick={this.handlerClick.bind(this)}>button</button>
      </div>
    )
  }
}
  1. 使用箭头函数
class Com extends React.Component {
  handlerClick= () => {
    console.log(this);
    console.log('点击');
  }
  render() {
    return (
      <div>
        <button onClick={this.handlerClick}>button</button>
      </div>
    )
  }
}

类组件中实现响应式

类组件是有状态组件,可以使用state和setState()来让页面"动"起来。

模拟实现表单的数据双向绑定

class Com extends React.Component {

  state = {
    msg: 'hello'
  }

  handlerChange = e => {
    this.setState({
      msg: e.target.value,
    })
  }

  render() {
    return (
      <div>
        <h3>{this.state.msg}</h3>
        <input value={this.state.msg} onChange={this.handlerChange} type="text"/>
      </div>
    )
  }
}

root.render(
  <Com/>
);

渲染结果: