概述

起因是,为了做毕设,顺便学点前端,我打算学习React。

MDN通过一个Todo List App的制作,教导React的知识点。

这是我在MDN学习React的总结,总结出了一些React开发的基本特性,加上MDN上这个教程的简体中文还没翻译过来,我的总结就更有意义了。

我的成品放在了Github

React基本概念

JSX是什么?

JSX语法,是长得很像HTML的JavaScript代码,简称:JavaScript语法的类HTML扩展(后面会介绍,它和HTML的区别)

const header = (
<header>
<h1>Mozilla Developer Network</h1>
</header>
);

关于它的一些原理:浏览器是无法理解JSX的,JSX语法会在编译的时候,被转换:

const header = React.createElement("header", null,
React.createElement("h1", null, "Mozilla Developer Network")
);

设置React APP

初始化APP

npx create-react-app moz-todo-react

应用结构

moz-todo-react
├── README.md
├── node_modules
├── package.json
├── package-lock.json
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── serviceWorker.js
  • src是源码
  • public包含了在开发APP过程中,浏览器需要读取的文件;index.html是最重要的文件,React会将src中的源码注入这个文件,是的浏览器能够运行源码;其中有个<title>标签,是应用的便签上显示的应用名

探索第一个React组件<App />

在React中,component是一个代表APP某部分的可重用的模块。

App.js 由三个主要部分组成:顶部的一些 import 语句、中间的App组件和底部的 export 语句。大多数React组件都遵循这种模式。

// 第一个语句导入React库本身。因为React将我们写入的JSX转换为React.createElement(),所以所有的React组件都必须导入React模块。如果跳过这一步,应用程序将产生一个错误。
import React from 'react';
// 注意./被使用在路径的开头,.svg扩展名在路径的结尾——这告诉我们文件是本地的,而且这不是JavaScript文件。
import logo from './logo.svg';
// 第三条语句导入了与我们的App组件相关的CSS。
import './App.css'; // 这个App函数返回一个JSX表达式。这个表达式定义了浏览器渲染到DOM的内容。
function App() {
return (
// 表达式中的某些元素具有属性,这些属性的编写方式与HTML类似,遵循attribute="value"的模式。
// <div>标签有一个className属性。这与HTML中的class属性相同,但因为JSX是JavaScript,所以我们不能使用class这个词——它是保留的,这意味着JavaScript已经将它用于特定目的,这将在我们的代码中引起问题。
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Hello, World!
</p>
</header>
</div>
);
} // 在App.js文件的最底部,export default App语句使我们的App组件可以被其他模块使用。
export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App'; ReactDOM.render(<App />, document.getElementById('root'));

调用React的ReactDOM.render()函数,有2个参数:

  1. 被渲染的组件,在这个例子中是<App />。
  2. 被渲染的DOM元素,在本例中是ID为root的元素。如果你查看public/index.html内部。你会看到这是<body>中的<div>元素。

变量和props

JSX中的变量

注意App.js文件中的这一行:

<img src={logo} className="App-logo" alt="logo" />

这里,<img />标签的src属性值用花括号括起来。

JSX就是这样识别变量的。React会识别{logo},知道你是在应用程序的第2行导入logo,然后检索logo文件并渲染它。

使用自定义变量,定义say Hello的对象subject

function App() {
const subject = "React";
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Hello, {subject}!
</p>
</header>
</div>
);
}

组件props

  • prop是传递到React组件中的任何数据。React props与HTML属性类似。HTML元素有属性,React组件有props。
  • props是在组件调用时直接定义和初始化的,使用与HTML属性相同的语法——prop="value"。(你可以将使用一个组件,看作是调用一个组件的函数,函数的返回值是JSX表达式)
  • 在React中,数据流是单向的:props只能从父组件向下传递到子组件;props是只读的。
props使用实例

打开index.js,在调用<App />时,直接定义和初始化props。

ReactDOM.render(<App subject="Clarice" />, document.getElementById('root'));

在App.js中,接收props。

function App(props) {
const subject = props.subject;
return (
// return statement
);
}

小结(React基本概念)

  • 组件可以import需要的module,且必须在文件底部export自己。
  • 组件函数使用PascalCase命名。(可以理解为,将camelCase的第一个单词首字母大写)
  • 您可以通过将变量放在花括号之间,在JSX中读取它们,比如{so}。
  • 为了不与JavaScript保留字冲突,一些JSX属性与HTML属性不同。例如,HTML中的class转换为JSX中的className。注意,多单词属性是camelCase的。
  • Props就像HTML属性一样,在组件调用时被初始化,并被传递到组件中。

常用特性(以Todo List App的开发为例)

迭代(遍历)渲染

需求:Todo List会由很多待办事项,即Todo item组成。通过迭代渲染,我们可以很优雅的渲染一系列的Todo component。

通常用来渲染一个JSX对象数组。

初始化<Todo />数组:

const taskList = props.tasks.map(task => (
<Todo id={task.id} name={task.name} completed={task.completed} />
));

渲染数组:

<ul
role="list"
className="todo-list stack-large stack-exception"
aria-labelledby="list-heading"
>
{taskList}
</ul>

唯一key

  • 现在React将我们的待办事项从一个数组中渲染出来,为了正确地渲染它们,React必须记录并正确地区分它们。
  • React试图通过自己的猜测来记录,但是我们可以通过向<Todo />元素传递一个key props来帮助它解决这个问题。
  • key是React管理的一个特殊 props ——你不能将key用于任何其他目的。
  • 可以使用nanoid来生成。。。
const taskList = props.tasks.map(task => (
<Todo
id={task.id}
name={task.name}
completed={task.completed}
key={task.id}
/>
)
);
  • 被迭代渲染的每个元素,必须被传入一个唯一的key

处理事件(handling events)

需求:处理新增Todo事项的表单提交

在React中,我们直接在JSX中的元素上编写事件处理器:

<button
type="button"
onClick={() => alert("hi!")}
>
Say hi!
</button>

这似乎与最佳实践建议相悖,建议不要在HTML上使用内联事件处理程序,但请记住,JSX实际上是JavaScript的一部分。

onClick属性的意义:

  • 它使得React,在用户单击按钮时运行一个给定的函数。
  • onClick的camelCase非常重要——JSX不会识别onclick(同样,它已经在JavaScript中用于特定目的,这与标准的onclick处理程序属性相关但又不同)。
  • 在 JSX 中,所有的浏览器事件都遵循这种格式:on + 事件的名称。

处理表单提交

function handleSubmit(e) {
e.preventDefault();
alert('Hello, world!');
}

为<form>元素添加一个onSubmit属性,并将其值设置为handleSubmit函数:

<form onSubmit={handleSubmit}>

回调(callback) props

需求:在Todo List中,我们需要一个功能:在<Form />中提交新的待办事项,然后展示在<App />中。

这意味着,我们需要将数据从子组件传递到父组件!

  • 在React应用程序中,交互性很少局限于一个组件:一个组件中发生的事件会影响应用程序的其他部分。
  • 我们不能像使用标准props将数据从子组件传递到父组件那样,将数据从父组件传递到子组件。

因此,我们无法实现这个需求?

不,我们可以在<App />中编写一个函数,然后将该函数作为 props 传递给<Form />,该函数将从我们的 <Form /> 中获取一些数据作为输入。

  • 这个函数prop(function-as-a-prop)被称为回调(callback)prop。

实现:

  1. 在App()函数中,编写函数addTask()

    function addTask(name) {
    alert(name);
    }
  2. 将addTask函数作为prop传入<Form />

    <Form addTask={addTask} />
  3. 在Form()函数内部的handleSubmit方法中,调用callback prop

    function handleSubmit(e) {
    e.preventDefault();
    props.addTask("Say hello!");
    }

State和useState hook

前情提要:前面说到,我们能够使用callback prop将数据回传给父组件

需求:如何保存用户的输入内容呢?用户提交了表单之后,如何清空输入,也就是如何更新内容呢?

总所周知,软件工程嘛,封装肯定是越private越好,将数据留在和它最相关的地方。

  • 组件自身拥有的数据,称为State。
  • State是React的另一个强大工具,因为组件不仅拥有State,而且可以在以后,使用useState hook更新它。
  • 和State不同,prop是只读的(read-only)!
  • React提供了各种特殊的功能,被称为hook,允许我们为组件提供新的能力,比如state。

使用React hook前,需要先import:

import React, { useState } from "react";
  • useState()为组件创建一个state,它的唯一参数决定state的初始值。

  • 它返回两个东西:state和一个稍后可用于更新state的函数。

const [name, setName] = useState('Use hooks!');

文本替换(React 无关)

需求:动态显示未完成的待办事项

反单引号字符串拼接+三元表达式

const tasksNoun = taskList.length !== 1 ? 'tasks' : 'task';
const headingText = `${taskList.length} ${tasksNoun} remaining`;

应用:

<h2 id="list-heading">{headingText}</h2>

React开发入门:以开发Todo List为例的更多相关文章

  1. [嵌入式开发入门]4412开发板从零建立Linux最小系统

    本文转自iTOP-4412开发板实战教程书籍 http://www.topeetboard.com iTOP-4412开发板不仅可以运行Android,还可以运行简单的Linux最小文件系统. 最小L ...

  2. spring boot + vue + element-ui全栈开发入门——windows开发环境

     一.node.js开发环境 windows系统,去网站https://nodejs.org/en/download/,下载对应的安装程序,并安装Windows Installer (.msi) 接下 ...

  3. 【转载】Servlet Filter(过滤器)、Filter是如何实现拦截的、Filter开发入门

    Servlet Filter(过滤器).Filter是如何实现拦截的.Filter开发入门 Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过F ...

  4. spring boot + vue + element-ui全栈开发入门——开篇

    最近经常看到很多java程序员朋友还在使用Spring 3.x,Spring MVC(struts),JSP.jQuery等这样传统技术.其实,我并不认为这些传统技术不好,而我想表达的是,技术的新旧程 ...

  5. spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发

     前言 Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库. Electron通过将Chromium和Node.js合并到同一个运行时环 ...

  6. spring boot + vue + element-ui全栈开发入门

    今天想弄弄element-ui  然后就在网上找了个例子 感觉还是可以用的  第一步是完成了  果断 拿过来  放到我这里这  下面直接是连接  点进去 就可以用啊 本想着不用vue   直接导入连接 ...

  7. Servlet Filter(过滤器)、Filter是如何实现拦截的、Filter开发入门

    Servlet Filter(过滤器).Filter是如何实现拦截的.Filter开发入门 Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过F ...

  8. React Native开发入门

    目录: 一.前言 二.什么是React Native 三.开发环境搭建 四.预备知识 五.最简单的React Native小程序 六.总结 七.参考资料   一.前言 虽然只是简单的了解了一下Reac ...

  9. React开发入门

    目录: 一.前言 二.什么是React 三.开发环境搭建 四.预备知识 五.最简单的React小程序 六.基础语法介绍 七.总结 八.参考资料   一.前言 近段时间看到学长公司招聘React Nat ...

随机推荐

  1. Codeforces Global Round 7 C. Permutation Partitions(组合数学)

    题意: 给你 n 长全排列的一种情况,将其分为 k 份,取每份中的最大值相加,输出和的最大值和有多少种分法等于最大值. 思路: 取前 k 大值,储存下标,每两个 k 大值间有 vi+1 - vi 种分 ...

  2. 关于贪心算法的经典问题(算法效率 or 动态规划)

    如题,贪心算法隶属于提高算法效率的方法,也常与动态规划的思路相挂钩或一同出现.下面介绍几个经典贪心问题.(参考自刘汝佳著<算法竞赛入门经典>).P.S.下文皆是我一个字一个字敲出来的,绝对 ...

  3. Educational Codeforces Round 89 (Rated for Div. 2) D. Two Divisors (数学)

    题意:有\(n\)组数,对于每组数,问是否能找到两个因子\(d_{1},d{2}\),使得\(gcd(d_{1}+d_{2},a_{i}=1)\),如果有,输出它们,否则输出\(-1\). 题解:对于 ...

  4. ssh配置方面小实验②

    4.禁止使用密码登录当我们学会了使用密钥对进行验证后,建议生产环境下将账户密码登录功能关掉配置文件:/etc/ssh/sshd_config选项: PasswordAuthentication no ...

  5. [备忘] DevOps 工具上的准备清单(不断补充中……)

    目录 概念 发展历程 工具清单 规划 概念 从字面上来看,"DevOps"一词是由英文 Development(开发)和 Operations (运维)组合而成,但它所代表的理念和 ...

  6. cookie,session,token之间的联系与区别

    发展史 1.很久很久以前,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, 不需要记录谁在某一段时间里都浏览了什么文档,每次请求都是一个新的HTTP协议, 就是请求加响应,  尤其是我不用 ...

  7. flex item default All In One

    flex item default All In One flex item default 初始值 === flex: 0 1 auto; https://drafts.csswg.org/css- ...

  8. 前端监控平台 & 架构

    前端监控平台 & 架构 1px 透明的 gif 字节小, 43 bytes 支持跨域, 兼容场景多,零配置 https://en.wikipedia.org/wiki/GIF demo htt ...

  9. js 裁剪图片

    js 裁剪图片 https://gugeji.com/search?q=js剪切图片

  10. js navigator.wakeLock 保持屏幕唤醒状态

    let lock; btn.addEventListener("click", async () => { try { if (lock) { lock.release(); ...