React基础入门项目实战
今天参加了一整天reactjs的培训,看邮件说该课程价值100美元,该课程覆盖了react的大部分基础内容,确实很不错。听说外企中使用reactjs较多,国内使用vue较多,想在外企工作的同学有必要了解该框架。写该博文主要是梳理React的基础知识点,可以对ReactJS的基础知识有大体了解。
写在前面
今天参加了一整天reactjs的培训,看邮件说该课程价值100美元,该课程覆盖了react的大部分基础内容,确实很不错。听说外企中使用reactjs较多,国内使用vue较多,想在外企工作的同学有必要了解该框架。写该博文主要是梳理React的基础知识点,可以对ReactJS的基础知识有大体了解。
React基础环境搭建
- 安装React脚手架(安装一次就好)
npm install -g create-react-app
- 验证脚手架是否安装完毕/查询版本
create-react-app -V
- 创建项目
create-react-app 项目名称 (js版本)
create-react-app 项目名称 --template typescript (TS版本)
-
搭建好项目后,控制台会提示输入哪些命令,我习惯cd该目录,
code .
使用vscode打开 -
启动项目
npm start
至此基础环境搭建完成,开始react的正式学习
React组件
React 是一个使用组件构建用户界面的 JavaScript 库。组件是 React 应用程序的构建块,每个组件都是独立封装的,可以在不影响应用程序其他部分的情况下重复使用和组合。
- Function 组件,以函数 的形式定义的组件称为 Function 组件,它们通常很简单,只有一个
props
参数并返回一个 virtual DOM 元素。 - Class 组件,以 ES6 class 的形式定义的组件称为 Class 组件,它们可以有自己的状态 (
state
) 和生命周期方法。 - Prop ,
props
是父组件传递给子组件的参数。在 Function 组件中,props
是函数的参数。在 Class 组件中,props
是通过this.props
访问的。
以下是一个使用props传递数据的简单的React子组件和父组件代码:
ChildComponent.js:
import React from 'react';
const ChildComponent = (props) => {
return (
<div>
<p>Child Component</p>
<p>{props.message}</p>
</div>
);
};
export default ChildComponent;
ParentComponent.js:
import React from 'react';
import ChildComponent from './ChildComponent';
class ParentComponent extends React.Component {
render() {
return (
<div>
<p>Parent Component</p>
<ChildComponent message={'Hello from parent!'} />
</div>
);
}
}
export default ParentComponent;
在app.js中使用这些组件:
import React from 'react';
import ParentComponent from './ParentComponent';
class App extends React.Component {
render() {
return (
<div>
<ParentComponent />
</div>
);
}
}
export default App;
目录结构如下
运行结果:
React Onclick
如下为创建一个button,并且随着点击递增数字的计数器示例代码:
import React, { useState } from 'react';
import './index.css';
function MyButton() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
return (
<button className="my-button" onClick={handleClick}>
{count}
</button>
);
}
export default MyButton;
其中,使用了React内置的useState Hook来存储按钮点击的次数,使用onClick属性绑定点击事件,每次点击都会调用handleClick函数,并且将count的值加1,从而实现计数器。
在App.js中引入:
import React from 'react';
import MyButton from './MyButton';
function App() {
return (
<div className="App">
<MyButton />
</div>
);
}
export default App;
同时需要在index.css中定义按钮的样式,例如:
.my-button {
width: 100px;
height: 30px;
font-size: 18px;
background-color: lightblue;
border: 1px solid lightyellow;
color: white;
cursor: pointer;
}
其中,.my-button是指定的class名称,在button标签中设置className属性即可应用该样式。
React useEffect
修改MyButton.js中的代码,来看一下useEffect的示例
import React, { useEffect, useState } from 'react';
const MyButton = () => {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
};
export default MyButton;
可以看到当点击后,浏览器的title也进行了更新,这里effect 不只执行一次。当组件第一次展示给用户以及之后的每次更新时它都会被执行。在 effect 中能触及当前的 props 和 state。
React Greeting
下面是一个使用React Greeting的示例代码,实现的是根据输入框输入的信息,获取内容并展示:
import React, { useState } from 'react';
function Greeting() {
const [name, setName] = useState('');
function handleChange(event) {
setName(event.target.value);
}
return (
<React.Fragment>
<label>
Enter your name:
<input type="text" placeholder="Your name" value={name} onChange={handleChange} />
</label>
<h1>Hello, {name.length > 0 ? name : 'Stranger'}!</h1>
</React.Fragment>
);
}
export default Greeting;
这个示例代码中,我们在函数式组件Greeting中使用了useState hook,来管理输入框中的值。使用了React Fragment来避免多余的外层标签。然后,给input元素添加了placeholder属性,在没有输入时显示“Your name”,用于提示用户输入内容。通过onChange事件,输入框中的值改变时,调用handleChange函数更新state中对应的值。最后,在页面上展示一个h1标题,来展示用户输入的文本。如果用户没有输入任何内容,则页面上展示“Hello, Stranger!”。
最后引入到app.js中:
import React from 'react';
import Greeting from './Greeting';
function App() {
return (
<div className="container">
<Greeting />
</div>
);
}
export default App;
这个示例中的App组件作为整个应用的入口组件,使用了Greeting组件,并且放置在了一个div.container中。
React Fragment的作用
React Fragment是一个组件,用于在不需要添加额外节点的情况下,将多个子元素分组。它可以用来组合一些子节点,而不会在DOM树中添加额外节点。它类似于Vue.js中的或Angular中的。
在过去,为了避免在DOM树中添加额外的DOM节点,开发人员会使用不必要的外部元素来包装多个元素。React Fragment可以使这个过程更加简单和干净。
使用React Fragment可以优化性能,因为它不会影响渲染结果,但可以优化渲染速度和内存使用。此外,React.Fragment可以被考虑成是对虚拟DOM树的一种提示,告诉React不要为它创建单独的节点。
React与BootStrap
Bootstrap是Twitter公司推出的一款开源的前端框架,它基于HTML、CSS、JavaScript开发,其中包含了丰富的CSS和JavaScript组件,用来快速构建响应式网站和Web应用程序。Bootstrap提供了一种简单的方法来快速设计页面结构、样式和交互效果,减少了开发成本,让开发者专注于网站和应用程序的功能实现。同时,Bootstrap还支持自定义构建下载,开发者可以根据自己的需求选择所需要的组件下载使用,极大地提高了开发效率。
下面是Button组件用到了bootstrap的案例:
首先,在index.html中引入Bootstrap的CSS和JS文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My React App</title>
<!-- 引入Bootstrap的CSS文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<!-- 这里是react应用的根节点 -->
<div id="root"></div>
<!-- 引入React的JS文件 -->
<script src="./app.js"></script>
<!-- 引入jQuery和Popper.js的CDN,以便引入Bootstrap的JS文件 -->
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.slim.min.js"></script>
<script src="https://cdn.bootcss.com/popper.js/1.15.0/umd/popper.min.js"></script>
<!-- 引入Bootstrap的JS文件 -->
<script src="https://cdn.bootcss.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</body>
</html>
接下来,在MyButton.js中编写MyButton组件的代码:
import React from 'react';
const MyButton = ({text, style}) => {
return (
<MyButton type="MyButton" className={`btn ${style}`}>{text}</MyButton>
);
};
export default MyButton;
MyButton组件有两个props:text和style。text表示按钮上要显示的文本,style表示按钮的样式类名。在这里我们使用了模板字符串和“${}”语法来拼接样式类名,以便动态修改按钮的样式。
最后,将MyButton组件集成到App.js中:
import React from 'react';
import MyButton from './MyButton';
const App = () => {
return (
<div className="container mt-3">
<MyButton text="Default" style="btn-primary mr-3" />
<MyButton text="Success" style="btn-success mr-3" />
<MyButton text="Danger" style="btn-danger" />
</div>
);
};
export default App;
在App组件中,我们使用了三个MyButton组件,并传入不同的props,以生成三个具有不同样式的按钮。
React与API
使用Fetch方法
以下是调用API的数据并使用列表展示的示例代码
import React, { Component } from "react";
class FetchAPI extends Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/users")
.then(response => response.json())
.then(data => {
this.setState({
data: data
});
});
}
render() {
const { data } = this.state;
const listItems = data.map(item => (
<li key={item.id}>
{item.name}, {item.email}
</li>
));
return <ul>{listItems}</ul>;
}
}
export default FetchAPI;
此代码实现了以下功能:
- 导入React库和useState和useEffect Hook。
- 创建FetchAPI组件。
- 使用constructor和state来初始化组件的状态来创建一个名为data的状态,并将其初始值设置为空数组。
- 获取json数据,发出一个HTTP GET请求并将响应转换为JSON格式。此请求完成后,setData将更新data状态并将其设置为获取的JSON数据。
- 在组件的返回值中,呈现一个标题元素和一个项目元素的列表。使用map方法遍历data状态中的所有项目,并在列表中呈现每个项目的标题。{{item.title}}.
然后在app.js中引入该组件:
import React from "react";
import FetchAPI from "./FetchAPI";
function App() {
return (
<div className="App">
<FetchAPI />
</div>
);
}
export default App;
使用Axois
Axios是一款基于Promise的HTTP客户端,可用于浏览器和Node.js中。Axios可以用于发送HTTP请求并处理响应。它支持请求和响应拦截器,可以帮助你简化代码,并使HTTP请求和响应更加灵活。Axios还提供了多种功能,例如取消请求,设置默认配置,拦截器等等。Axios被广泛应用于前端开发中,尤其在React等框架中使用广泛。
首先,需要在项目中安装axios:
npm install axios
安装后加载到package.json文件中
然后,在AxiosAPI组件中使用axios来调用接口并获取数据:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const AxiosAPI = () => {
const [data, setData] = useState({});
useEffect(() => {
axios.get('https://jsonplaceholder.typicode.com/posts/1')
.then(response => setData(response.data))
.catch(error => console.log(error));
}, []);
return (
<div>
<h1>{data.title}</h1>
<p>{data.body}</p>
</div>
);
}
export default AxiosAPI;
在上面的代码中,我们在组件中使用了useState和useEffect hooks来处理数据和获取接口数据确保实时更新。在useEffect hook中,我们使用axios调用了jsonplaceholder的API,并将响应数据保存在data中。最后,我们将数据渲染到组件中。
最后,将AxiosAPI组件集成到APP.js中:
import React from 'react';
import AxiosAPI from './AxiosAPI';
const App = () => {
return (
<div>
<AxiosAPI />
</div>
);
}
export default App;
刷新服务,结果如下:
和接口中的数据进行对比
React路由和Context
前端路由是指在单页应用(SPA)中,通过操作URL来实现页面之间的跳转和管理。它可以保证用户在跳转页面时不刷新整个页面,而只是更新部分页面内容,从而达到快速响应的效果。
前端路由通常使用浏览器的history API或hash值来在URL中记录页面状态信息,从而实现在单页应用中的页面之间的切换。常见的前端路由库包括React Router、Vue Router和Angular Router等。
前端路由的优点包括提高网站的运行速度和用户体验,减轻服务器的压力,以及方便SEO等方面的优化。同时,前端路由也可以帮助开发人员更好地进行代码结构管理,提高代码复用性和可维护性。
首先确保安装了react-router-dom
npm install react-router-dom
下面是一个示例代码,展示了如何使用BrowserRouter、Route、Link、Routes组件以及UserContext来创建一个简单的ReactJS应用程序:
import React, { createContext, useState,useContext,useEffect } from 'react';
import { BrowserRouter, Route, Link, Routes } from 'react-router-dom';
// 创建一个UserContext的上下文,用于在组件之间共享用户信息
export const UserContext = createContext();
// 创建一个简单的用户列表(实际中应从后台服务获取)
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
];
// 用户页面组件,负责显示单个用户的详细信息
const UserPage = ({ userId }) => {
const [user, setUser] = useState(null);
// 在组件挂载时,从用户列表中查找对应的用户信息并设置到本地状态
useEffect(() => {
const user = users.find(u => u.id === userId);
setUser(user);
}, [userId]);
// 判断是否已成功获取用户信息
if (!user) {
return <div>Loading...</div>;
}
// 显示用户信息
return (
<div>
<h1>{user.name}</h1>
<p>ID: {user.id}</p>
</div>
);
};
// 用户列表页面组件,负责显示所有用户的概要信息
const UsersPage = () => {
return (
<div>
<h1>Users</h1>
<ul>
{users.map(user => (
<li key={user.id}>
<Link to={`/users/${user.id}`}>{user.name}</Link>
</li>
))}
</ul>
</div>
);
};
// 应用程序启动组件
const App = () => {
const [user, setUser] = useState(null);
// 用户登录函数,将用户信息存储到上下文中
const login = ({ id, name }) => {
setUser({ id, name });
};
// 用户登出函数,将用户信息从上下文中清除
const logout = () => {
setUser(null);
};
// 渲染应用程序,包括页面导航、用户信息和路由处理
return (
<BrowserRouter>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
<UserContext.Provider value={{ user, login, logout }}>
<div>
{user ? (
<p>
Logged in as <b>{user.name}</b>. <button onClick={logout}>Logout</button>
</p>
) : (
<p>
<Link to="/login">Login</Link>
</p>
)}
<Routes>
<Route path="/" element={<h1>Welcome to My App</h1>} />
<Route path="/login" element={<LoginForm />} />
<Route path="/users" element={<UsersPage />} />
<Route path="/users/:userId" element={<UserPage />} />
</Routes>
</div>
</UserContext.Provider>
</BrowserRouter>
);
};
// 登录表单组件,负责接收用户输入并处理登录逻辑
const LoginForm = () => {
const { login } = useContext(UserContext);
const [formData, setFormData] = useState({ name: '' });
const handleChange = e => {
// ...展开语法,用于展开对象,数组,不确定参数等
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const handleSubmit = e => {
e.preventDefault();
login({ id: 123, name: formData.name });
setFormData({ name: '' });
};
return (
<div>
<h1>Login</h1>
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" name="name" value={formData.name} onChange={handleChange} />
</label>
<button type="submit">Login</button>
</form>
</div>
);
};
export default App;
在这个示例中,我们首先创建了一个UserContext上下文,用于在不同的组件之间共享用户信息。然后我们定义了两个页面组件,UsersPage和UserPage,分别用于显示用户列表和单个用户的详细信息。
在App组件中,我们也使用BrowserRouter、Route、Link和Routes组件来设置路由和页面导航。此外,我们还通过UserContext.Provider将用户信息注入整个应用程序。
最后,我们还提供了一个LoginForm组件,用于处理用户登录逻辑。在这个组件中,我们使用useContext钩子从UserContext中获取login函数,并通过useState钩子来管理登录表单中的用户输入。用户在提交表单时,我们调用login函数将用户信息存储到上下文中。然后页面会自动重新渲染,显示用户信息和导航菜单中的注销按钮。
更多推荐
所有评论(0)