React开发入门:以开发Todo List为例
概述
起因是,为了做毕设,顺便学点前端,我打算学习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个参数:
- 被渲染的组件,在这个例子中是<App />。
- 被渲染的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 />元素传递一个
keyprops来帮助它解决这个问题。 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。
实现:
在App()函数中,编写函数addTask()
function addTask(name) {
alert(name);
}
将addTask函数作为prop传入<Form />
<Form addTask={addTask} />
在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为例的更多相关文章
- [嵌入式开发入门]4412开发板从零建立Linux最小系统
本文转自iTOP-4412开发板实战教程书籍 http://www.topeetboard.com iTOP-4412开发板不仅可以运行Android,还可以运行简单的Linux最小文件系统. 最小L ...
- spring boot + vue + element-ui全栈开发入门——windows开发环境
一.node.js开发环境 windows系统,去网站https://nodejs.org/en/download/,下载对应的安装程序,并安装Windows Installer (.msi) 接下 ...
- 【转载】Servlet Filter(过滤器)、Filter是如何实现拦截的、Filter开发入门
Servlet Filter(过滤器).Filter是如何实现拦截的.Filter开发入门 Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过F ...
- spring boot + vue + element-ui全栈开发入门——开篇
最近经常看到很多java程序员朋友还在使用Spring 3.x,Spring MVC(struts),JSP.jQuery等这样传统技术.其实,我并不认为这些传统技术不好,而我想表达的是,技术的新旧程 ...
- spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发
前言 Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库. Electron通过将Chromium和Node.js合并到同一个运行时环 ...
- spring boot + vue + element-ui全栈开发入门
今天想弄弄element-ui 然后就在网上找了个例子 感觉还是可以用的 第一步是完成了 果断 拿过来 放到我这里这 下面直接是连接 点进去 就可以用啊 本想着不用vue 直接导入连接 ...
- Servlet Filter(过滤器)、Filter是如何实现拦截的、Filter开发入门
Servlet Filter(过滤器).Filter是如何实现拦截的.Filter开发入门 Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过F ...
- React Native开发入门
目录: 一.前言 二.什么是React Native 三.开发环境搭建 四.预备知识 五.最简单的React Native小程序 六.总结 七.参考资料 一.前言 虽然只是简单的了解了一下Reac ...
- React开发入门
目录: 一.前言 二.什么是React 三.开发环境搭建 四.预备知识 五.最简单的React小程序 六.基础语法介绍 七.总结 八.参考资料 一.前言 近段时间看到学长公司招聘React Nat ...
随机推荐
- hdu4710 Balls Rearrangement(数学公式+取模)
Balls Rearrangement Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- 2019牛客暑期多校训练营(第七场)B Irreducible Polynomial
传送门 题意: 给你一个n次n+1项式(An*X^n+A(n-1)*X^(n-1)...A*X+A0),将系数An都给你,问你这个多项式是不是一个不可约多项式,可约多项式就是类型(x+1)*(x+2) ...
- Educational Codeforces Round 89 (Rated for Div. 2) C Palindromic Paths
题目链接:Palindromic Paths 题意: 给你一个n行m列的矩阵,这个矩阵被0或者1所填充,你需要从点(1,1)走到点(n,m).这个时候会有很多路径,每一条路径对应一个01串,你可以改变 ...
- 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)
1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e, 要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...
- MySQL——时间、字符串、时间戳相互转换
一.时间转字符串 select data_format(now(),'%Y-%m-%d %H:%i:%s'); 二.时间转时间戳 select unix_timestamp(now()); 三.字符串 ...
- ArcGIS处理栅格数据(一)
一.建立影像金字塔 ArcToolbox--数据管理工具--栅格--栅格属性--构建金字塔(pyramid) 说明:该方式一次只能为一张影像数据建立影像金字塔. ArcToolbox--数据管理工具- ...
- leetcode31 下一个排列 字典序
数字的字典序就是比大小 先想几个例子 123_>132 1243-> 1324 ,12453-> 12534 1.不可排的序列就是降序序列 2.两个相同长度的串比大小,前面相同, ...
- oslab oranges 一个操作系统的实现 实验二 认识保护模式
https://github.com/yyu/osfs00 实验目的: 理解x86架构下的段式内存管理 掌握实模式和保护模式下段式寻址的组织方式. 关键数据结构.代码组织方式 掌握实模式与保护模式的切 ...
- Java中输出小数点后几位
笔试时候,遇到让你写输出小数点后几位,当时很是头疼,下来后,查了查发现,没什么难的.网上有各种情况都讨论了(一般分为4种),在这里我着重讨论一下比较实用,比较简单,比较方便操作的几种: 1 publi ...
- Leetcode(94)-二叉树的中序遍历
给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 思路:和上篇的前序遍历一样,同样有递归和非递归的做法 (1)递归 vecto ...