初学者教程系列:React入门[面向初学者]
初学者教程系列:(2部分)
什么是React?
为什么每个人都如此痴迷呢?
React是Facebook构建的JavaScript库。它用于构建前端用户界面。react的主要功能是通过将界面划分为较小的组件,使UI更具模块化。这种思维模式非常适合用户界面。
React确实改变了我们对Web应用程序和用户界面开发的思考方式,并使得以更高效和模块化的方式构建和管理大型Web应用程序(例如Facebook,Netflix等)成为可能。
它是如何工作的?
除了首先跳入学习反应之外,我们还应该至少至少了解它在引擎盖下的实际工作方式。
为了简单明了,用通俗易懂的话来说,所起的作用是代替直接操作Web浏览器的DOM,而是在内存中创建此虚拟DOM,并在其中进行所有这些操作。
然后,它检查在虚拟DOM中进行了哪些更改,然后将这些更改应用到浏览器的DOM中。
让我们讨论一些重要的概念。
A.组件
组件是React应用程序的最基本的构建块。在React中,单个网页可以分成代表屏幕不同部分的小块。以下面的布局为例。
在这里,您可以看到的每个彩色框代表一个不同的组件。
每个单独的组件彼此独立,并对其视觉外观及其交互负责。
用外行术语来说,组件基本上只是一个文件,其中包含一组中的所有html,样式和js逻辑。
B.JSX
由于React使用JavaScript,您可能想知道我们如何在屏幕上创建和呈现元素。为了通过香草javascript创建基本元素,我们通常使用
var header = document.createElement("h1");
header.innerHTML = "Hello World !";
尽管这种方法完全可以,并且我们仍然可以在React中使用这种方法,但是您可以想象,我们的代码看起来有多混乱?
仅举一个例子,让我们尝试以随意的方式创建一个由三个元素组成的无序列表。
const List = () => {
const alphabets = ["a", "b", "c"];
return React.createElement(
"div",
null,
React.createElement("h2", null, "Alphabets"),
React.createElement(
"ul",
null,
alphabets.map((item) => {
return React.createElement(
"li",
{ className: "alphabet" },
item
);
})
)
);
};
完成如此简单的任务看起来很恐怖,对吧?现在,让我们尝试以JSX方式实现相同的目标。
const List = () => {
const alphabets = ["a", "b", "c"];
return(
<div>
<h2>Alphabets</h2>
<ul>
{alphabets.map(item=>
<li className="alphabet">item</li>
)}
</ul>
</div>
)
}
注意到差异了吗?样板文件少得多,代码却更优雅一些。那就是JSX。
乍一看,您可能会想,这看起来像HTML。您并不孤单,每个新的React开发人员一开始都会这么认为。我也这么认为。
但是,有趣的是,它不是HTML。它只是JavaScript的语法扩展,或者您可以说一些糖语法,用于定义组件及其在标记中的位置。如果您想进一步了解JSX,请参阅React文档,在此处。
我相信通过实践学习,这就是为什么在本教程的其余部分中,我们将通过一个非常基本的React项目来探索React的原因。
C.组件状态
如果您尝试阅读react文档以确定状态,那么一开始可能很难掌握。这就是通常通常有许多初学者教程不包含此概念的原因。但是我认为,掌握起来并不是那么复杂和超级简单,我相信这是一个非常重要的概念,可供所有试图学习反应的人学习。
您可以根据某些特定数据或假设的变量将某个组件的状态想象为该组件的输出。例如,在一个小时时钟的情况下,组件的输出必须每隔一小时更改一次,比如说从凌晨1点到凌晨2点。因此,该时钟组件在凌晨1点的输出可以称为该组件的状态。
再举一个例子,如果有人试图访问您的网站,而您想向访问者显示登录页面,以防他们没有登录,而是在他们登录时显示仪表板。用户是否登录可以称为该组件的状态。
重要的是要记住,只要组件的状态发生变化,组件就会重新呈现自己。 例如,一旦用户登录,我们希望将其带到仪表板,而不是登录页面。
在我们处理项目的同时,我们将看到这一点。
1.设置我们的React项目。
出于测试目的,我们只需在index.html文件中包含三个脚本即可快速设置React。
一个。使用全局脚本
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
如果您想采用这种方法,则可以完全做到这一点,并且仍然可以按照本教程进行操作。但是,在生产环境中,我们更喜欢使用一些构建工具,因为React倾向于利用某些功能,这些功能在浏览器中默认情况下不起作用。
对于本教程,我将采用后一种方法,并实际设置一个生产反应环境。
但是,如果您决定使用上一个,请在同一目录中创建一个“ app.js”文件,并确保“ index.html”文件与此类似。
<!DOCTYPE html>
<html>
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<body>
<div id="root"></div>
<script type="text/babel" src="./app.js"></script>
</body>
</html>
b。使用构建工具
对于那些打算采用先前方法的人,可以跳过这一部分,但对于那些想要建立反应环境的人可以遵循。
- 确保已在系统上安装了node.js。
您可以通过node -v
在终端中运行来进行检查。如果输出的版本号为xx.xx.x。然后,你很好!但是,如果遇到诸如命令无法识别的错误,请从此处下载并安装node.js安装程序包。
- 创建一个新的react项目
一旦您设置了node。打开终端并cd
进入所需目录。
现在,您可以运行该命令,以使用npm(节点程序包管理器)在系统上全局安装create-react-app。npm install -g create-react-app
可能需要几秒钟,具体取决于您的互联网连接。
现在,我们终于可以创建我们的react项目。很简单 您可以跑步。
npx create-react-app todo
可能还要等一下。完成后,您只需将CD插入应用程序文件夹并使用以下命令在本地运行该应用程序
cd todo npm start
它将打开一个浏览器窗口,您应该能够看到类似这样的内容
恭喜,您刚刚创建了一个第一个React项目!🎊
我们将在一分钟之内介绍一下代码和文件夹结构中发生的一切,但是首先让我们清除一些不必要的混乱情况。
为了加快速度,您可以从此处下载这些入门文件,然后复制替换src文件夹。如果您已完成此操作,则可以直接运行,跳过后一部分,并跳至了解项目结构。npm start
如果您仍然希望手动操作,
在“ src”文件夹中,您必须能够看到很多文件。让我们从清洁这些开始。
让我们删除src文件夹中的所有其他文件,直到只剩下这3个“ App.js”,“ index.js”,“ index.css”。
您的终端中肯定有一个错误。让我们解决这个问题。
打开“ index.js”文件,并删除所有已删除的导入和serviceworker代码。直到您剩下类似的东西
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
ReactDOM.render(<App />, document.getElementById("root"));
仍然面临错误?让我们打开“ App.js”文件。
删除导入徽标和app.css行,并将return语句替换为h1标头。您的“ App.js”文件应如下所示
import React from "react";
function App() {
return <h1>Hello World</h1>;
}
export default App;
最后,打开index.css文件,全选并删除其内容。
确保您仍在运行npm start命令。现在,您应该可以在浏览器窗口中看到“ Hello World”。
2.了解项目结构。
让我们在资源管理器或finder中打开项目文件夹,您会注意到我们拥有的第一件事是
- 'node_modules'。“ node_modules”仅包含我们使用npm安装的所有不同软件包。我们从不经常触摸此文件夹,您可以忽略它。
要记住的提示是,我们永远不会在版本控制中提交node_modules文件夹,因为它们可以通过运行在主机上生成npm install
。
- “ public”包含我们的index.html文件,图标和清单文件(您现在可以忽略)。
- 'package.json'这个文件包含一些脚本和一些软件包的名称,这些脚本和软件包的名称基本上启动了我们的react项目。这只是npm创建的文件。
- 'src'我们的大部分工作都将在此文件夹中。
让我们打开App.js。
在我们的App.js文件中,“ App”是一个组件。这种特定的实现称为功能组件。我们编写的功能与我们在普通javascript中定义功能的方式完全相似。
function App(){}
它与普通javascript的不同之处在于,它不返回值,而是返回一个组件,例如
function App(){
return (
<h1>Hello World</h1>
)
}
我们还可以使用箭头功能在同一行中编写相同的代码。
const App = ()=> <h1>Hello World</h1>
现在,由于我们要在其他页面中使用此组件,因此需要使用
export default App
让我们跳回到“ index.js”文件,看看如何使用此组件。
您可以在index.js文件中看到发生了什么事,就是我们再次导入了react和ReactDOM
。
然后,我们使用一种方法ReactDOM.render
方法来呈现“ App”组件,后跟一个逗号和document.getElementById('root')
。
好的,这是怎么回事?发生的事情是,当我们使用ReactDOM.render方法时,我们要求它通过将其注入ID为'root'的元素中来呈现App组件。反应是它采用我们所有的JavaScript代码并从中生成所需的html。
您可以通过打开index.html
文件public
夹中的文件来验证这一点。您必须能够
<div id="root"></div>
在body标签中看到它。
3.创建开发卡
让我们分解一下我们对应用程序的最初想法,将三个用户展示为组件。我们可以很容易地观察到,在这三种情况下,这些配置文件卡的布局都非常相似,只是它们之间包含的数据不同。
首先让我们集中精力为该组件构建html布局。为了简单起见,我已经在启动文件的index.css中包含了该项目所需的所有CSS 。
如果您没有下载启动程序文件,而是采用手动方法,只需从下方将css复制粘贴到index.css文件中即可。
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap");
@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css");
* {
box-sizing: content-box;
margin: 0;
padding: 0;
font-family: "Poppins", sans-serif;
}
:root {
--main-color: #eee;
--dark-color: #2c3e50;
--text-color: #7f7f7f;
}
.wrapper {
min-height: 100vh;
background: var(--main-color);
display: flex;
justify-content: center;
align-items: center;
justify-content: space-evenly;
flex-wrap: wrap;
}
.card {
width: 300px;
height: 450px;
background: white;
margin: 1rem;
display: flex;
flex-direction: column;
justify-content: space-between;
box-shadow: 0px 0px 5px #233942;
}
.card img {
background: var(--main-color);
margin-top: 30px;
border-radius: 50%;
position: absolute;
width: 150px;
height: 150px;
padding: 0.15rem;
border: 0.2rem solid black;
}
.user-image {
position: relative;
width: 100%;
height: 200px;
display: flex;
justify-content: center;
}
.user-image:before {
content: "";
height: 125px;
width: 100%;
background: var(--dark-color);
}
.user-info {
display: flex;
flex-direction: column;
align-items: center;
}
.user-info .name {
font-size: 1.25rem;
text-transform: uppercase;
font-weight: 600;
}
.user-info .handle {
font-size: 0.9rem;
font-weight: 500;
color: var(--text-color);
}
.user-info .summary {
padding: 0.75rem 1rem;
text-align: center;
font-size: 0.75rem;
font-weight: 400;
color: var(--text-color);
}
.location {
text-align: center;
font-weight: 400;
font-size: 0.8rem;
color: var(--text-color);
padding: 2.5rem 0;
}
.location::before {
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: "\f3c5";
padding: 0 0.2rem;
}
里面的src文件夹,让我们创建一个新的文件card.js。在这里,我们将创建卡组件。
让我们从导入反应并为卡编写样板函数开始。
import React from "react";
function Card() {
return(
<h1>This is a Card</h1>
)
}
export default Card;
让我们保存更改并打开浏览器以查看结果。等等,它没有显示吗?那是因为我们没有在App
组件中导入它。
为了解决这个问题,让我们打开我们的App.js文件,并替换<h1>Hello World</h1>
用
import React from "react";
import Card from "./card";
function App(){
return (
<div class="wrapper">
<Card />
</div>
);
}
export default App;
现在您应该可以在浏览器中看到类似的内容
虽然可以,但是如果您打开控制台(Ctrl / Cmd + Shift + J-Chrome,Ctrl / Cmd + Shift + K-FireFox),则可以。您必须看到与此类似的警告
**为什么收到此警告消息?**
这是因为如果您仔细查看App函数,则我们返回的div具有class
包装器。虽然,这是我们如何定义HTML类的具体方式,但记得我前面提到的,这不是html
,但JSX
?
因为,JavaScript已经有一个class
用于构造函数的关键字,这就是为什么我们不能class
在此处使用此关键字来修复此React 的原因className
。我们可以通过更换我们解决这个问题class
有className
这样
import React from "react";
import Card from "./card";
function App(){
return (
<div className="wrapper">
<Card />
</div>
);
}
export default App;
完成此操作后,控制台中的所有警告都将得到解决。
除此之外,让我们跳回到card.js文件并构建html布局。我已经使用与CSS中相同的类创建了一个布局,以加快处理速度。
function Card() {
return (
<div className="card">
<div className="user-image">
<img src="user.png" alt="User Profile"></img>
</div>
<div className="user-info">
<div className="name">John Doe</div>
<div className="handle">@johndoe</div>
<div className="summary">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
</div>
<div className="location">New York</div>
</div>
);
}
保存更改后,您应该可以在浏览器中看到类似的内容。
恭喜!我们的应用程序终于成形。但这只是静态数据,对吗?我们希望根据用户名展示实际的用户数据。
为此,我们可以使用javascript中内置的Fetch API方法从以下端点检索dev.to用户数据:https ://dev.to/api/users/by_username?url=bob 。替换bob
为您的用户名。该端点发送具有以下结构的json数据,然后我们可以对其进行解析并显示在组件中。
{
"type_of": "user",
"id": 1234,
"username": "bob",
"name": "bob",
"summary": "Hello, world",
"twitter_username": "bob",
"github_username": "bob",
"website_url": null,
"location": "New York",
"joined_at": "Jan 1, 2017",
"profile_image": "https://res.cloudinary.com/...jpeg"
}
在JavaScript中使用提取API的最简单方法是像这样使用它
let username="ishandeveloper"; // You can write your username here
fetch(`https://dev.to/api/users/by_username?url=${username}`)
.then((res) => res.json())
.then((data) => data);
但是,我们如何才能在react应用程序中使用它,并且仅在将组件安装/注入到应用程序树中时,才想确保调用此fetch方法。为此,我们必须使用一种称为hooks的东西。
挂钩基本上只是一些函数,可以让我们在组件的某些事件中触发回调。您可以在此处阅读更多内容。
对于我们的目标,我们将使用useState
and useEffect
钩子。
一个。useState()钩子允许您在函数内部声明状态变量。
b。useEffect()挂钩允许功能组件通过在每次渲染之前执行回调来操纵DOM元素。
我们使用其中的任何之前,我们应该导入它们从反应模块,通过更换import React from 'react'
同
import React, {useState, useEffect} from 'react';
因此,让我们编写用于从API提取数据的函数。我们将使用useEffect
钩子来调用获取数据的函数。
我们可以简单地通过在功能组件内部的return语句之前编写这样的回调函数来做到这一点。
let user={};
useEffect(() => {
async function fetchData() {
let username="ishandeveloper"; // You can write your username here
// Retrieves json data from DEV API
let dev_data = await fetch(`https://dev.to/api/users/by_username?url=${username}`)
.then((res) => res.json())
.then((data) => data);
user=dev_data; // Sets the user data
}
fetchData(); // Calls the above function
}, [] );
在上面的代码中,我们在useEffect挂钩中传递了一个回调函数,并在该回调函数内创建了另一个异步函数fetchData()并调用了该异步函数。这是因为不允许在useEffect函数中直接使用async。
您可能还注意到,我们将一个空数组([])作为第二个参数传递给useEffect。这是为什么?这是因为,默认情况下,
每当安装或更新组件时,都会运行useEffect回调。
那么,这是什么问题呢?抓住了。使用这种方法,我们陷入了一个棘手的循环。因为我们是在安装组件时获取数据,然后更新数据,所以在更新数据时,组件再次重新渲染,触发了useEffect回调,因此陷入了永远的循环。
为了解决这个问题,我们将数组作为第二个参数传递,以避免在组件更新时将其激活。您可以在文档中向下滚动到最后一个突出显示的注释,以了解更多信息。
虽然,似乎一切都可以按预期工作,但是上面的代码不会重新渲染组件,这是因为我们没有更改组件的状态。我们需要明确告诉反应组件的状态已更改。为此,我们需要使用useState
钩子。
我们可以像这样使用它来存储我们的用户数据
const [user, setUser] = useState({});
让我们分解一下
在useState
方法内部,我们可以添加要存储的用户变量的初始值,它可以是对象,数组,布尔值,字符串,任何数字。
该useState
方法返回一个由两部分组成的数组,首先是变量本身的值,其次是可用于更改该变量值的回调函数。
因此,与其user=dev_data
在上面的代码中使用,setUser
不如在useEffect中调用方法来更新用户数据。通过这两个更改,我们上面的代码将变为
const [user, setUser] = useState({});
useEffect(() => {
async function fetchData() {
let username="ishandeveloper"; // You can write your username here
// Retrieves json data from DEV API
let dev_data = await fetch(`https://dev.to/api/users/by_username?url=${username}`)
.then((res) => res.json())
.then((data) => data);
setUser(dev_data); // Sets the user data
}
fetchData(); // Calls the above function
}, [] );
完美,我们快完成了!🎊
现在我们有了数据,让我们将其传递到我们的JSX代码中。在JSX中,每当我们想在html外观标记中使用JavaScript代码时,都会将该JavaScript代码括在大括号中{}
。
根据API端点(如上所述)发送的属性,这是我们如何在jsx代码中格式化该数据。
return (
<div className="card">
<div className="user-image">
<img src={user.profile_image} alt="User Profile"></img>
</div>
<div className="user-info">
<div className="name">{user.name}</div>
<div className="handle">@{user.username}</div>
<div className="summary">{user.summary}</div>
</div>
<div className="location">{user.location}</div>
</div>
);
这样,您card.js中的整个代码应如下所示
import React, {useState, useEffect} from 'react';
function Card() {
const [user, setUser] = useState({});
useEffect(() => {
async function fetchData() {
let username="ishandeveloper"; // You can write your username here
let dev_data = await fetch(`https://dev.to/api/users/by_username?url=${username}`)
.then((res) => res.json())
.then((data) => data);
setUser(dev_data);
}
fetchData();
}, [] );
return (
<div className="card">
<div className="user-image">
<img src={user.profile_image} alt="User Profile"></img>
</div>
<div className="user-info">
<div className="name">{user.name}</div>
<div className="handle">@{user.username}</div>
<div className="summary">{user.summary}</div>
</div>
<div className="location">{user.location}</div>
</div>
);
}
export default Card;
完成此操作后,您应该能够在浏览器中看到类似的内容。
祝贺您,并为此感到自豪!你真的应该拍拍背🤙
但是我们还没有完成。
4.重复使用组件
我认为这是React最好的东西之一。记得?我们最初的目标是创建与此类似的东西。
在上面的可视化中,我们用三张卡片展示了三个不同的配置文件,而不是一个。那么,我们该怎么做呢?实际上,这很简单。
让我们打开App.js
文件。这是当前的样子,对吗?
import React from "react";
import Card from "./card";
function App(){
return (
<div class="wrapper">
<Card />
</div>
);
}
export default App;
您可以观察到我们已经<Card />
在此处编写了一个标签来创建Card Component。我们可以重复两次,以获取此Card Component的3个实例。
另外,我们还可以在此标记标记中传递自定义属性,这些属性称为props,让我们将不同DEV用户的用户名作为username
属性传递。
import React from "react";
import Card from "./card";
function App(){
return (
<div class="wrapper">
<Card username="ben"/>
<Card username="ishandeveloper"/>
<Card username="graciegregory"/>
</div>
);
}
export default App;
点击保存,让我们在浏览器中查看更改。
等等,有些奇怪。
所有这些看起来都不一样吗?
是的,他们有。因为尽管我们在卡片中传递了用户名属性,但并未使用它。
让我们解决这个问题。card.js
在编辑器中打开文件。
- 我们需要做的第一件事是
username
在我们的功能组件中接受那些道具。
让我们通过props
在函数中添加一个参数来做到这一点。这样我们的功能就变成这样
function Card(props) {
...........
}
现在,我们需要使用该用户名属性替换我们的硬编码用户名。它很容易,只需更换let username="ishandeveloper"
与let username=props.username
useEffect(() => {
async function fetchData() {
let username=props.username;
...........
点击保存,仅此而已。您已经成功完成了整个项目!🎊
这是card.js的全部源代码
万一你需要
import React, {useState, useEffect} from 'react';
function Card(props) {
const [user, setUser] = useState({});
useEffect(() => {
async function fetchData() {
let username=props.username; // You can write your username here
let dev_data = await fetch(`https://dev.to/api/users/by_username?url=${username}`)
.then((res) => res.json())
.then((data) => data);
setUser(dev_data);
}
fetchData();
}, [] );
return (
<div className="card">
<div className="user-image">
<img src={user.profile_image} alt="User Profile"></img>
</div>
<div className="user-info">
<div className="name">{user.name}</div>
<div className="handle">@{user.username}</div>
<div className="summary">{user.summary}</div>
</div>
<div className="location">{user.location}</div>
</div>
);
}
export default Card;
我们可以在其他文章中讨论一些更高级的主题,例如Redux,Context API等。希望您喜欢这一点,我们将不胜感激。
这篇文章是我的“入门”系列的一部分,在该系列中,我将向初学者友好地介绍一些最引人入胜的技术,工具和框架。
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » 初学者教程系列:React入门[面向初学者]
常见问题FAQ
- 没有金币/金币不足 怎么办?
- 本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
- 所有资源普通会员都能下载吗?
- 本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。