提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
本文为react学习笔记,自用。
一、React入门介绍
1.React是什么
React是用于构建用户界面的 JavaScript 库;是一个将数据渲染为HTML视图的开源 JavaScript 库。
2.React特点
声明式编码、组件化编码、React Native编写原生应用、高效(优秀的 Diffing 算法)。
3.React 高效的原因
(1)使用了虚拟(virtual)DOM,不总是直接操作页面真实 DOM。(而且在操作真是dom之前,会比较两个不同的虚拟dom,比较出有差异的那一部分再去更新页面)
(2)DOM Diffing 算法,最小化页面重绘。
二、配置环境
1.安装react.js(npm)
(1)国内使用 npm 速度很慢,菜鸟建议我们使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:
打开“命令提示符”,输入 :
npm install -g cnpm --registry=https://registry.npmmirror.com
这样是安装成功。
(2)接下来切换到镜像:
npm config set registry https://registry.npmmirror.com
切换成功。
2.搭建react框架
(1)安装 create-react-app
Create React App是React 提供的一个官方工具,用于快速搭建 React 项目;create-react-app 自动创建的项目是基于 Webpack + ES6。
打开“命令提示符”,输入 :
cnpm install -g create-react-app
这样create-react-app就安装成功了。
(2)新建react项目
在你喜欢的位置新建一个文件夹,我的文件夹名字叫react_start,在文件夹内右键,以管理员身份运行,输入:
create-react-app my-app
创建成功。
打开刚刚创建好的项目:
cd my-app/
打开成功。
运行项目:
npm start
是否要在另一个端口上运行应用程序? 选-y
运行成功。
3.用vsCode打开react项目
找到项目所在的文件夹,右键点击“通过Code打开”。(前提是电脑要有vsCode)
4.下载插件(个人喜好)
Code Spell Checker:检查是否有拼写错误
Fitten Code : AI 编程助手,它可以自动生成代码,提升开发效率,调试 Bug。
Simple React Snippets:可以通过缩写来触发代码片段,该插件会自动帮你补全,用于快速生成React组件结构。
插件根据自己需要进行安装,网上也有很多好用便捷的。
三、基本使用
1.hello react
打开文件,App.js是主组件文件,定义了一个基础的 React 组件。
在App.js写入下面代码:
import "./App.css";
function App() {
return (
<div className="App">
<header className="App-header">
<p>hello react.</p>
</header>
</div>
);
}
export default App;
查看刚刚在浏览器运行的页面:
2.State响应式
State即组件要用的数据,react和vue的这类框架的核心就是把请求的来的数据展示在页面上,数据更新后也需要响应式的展示新数据。
React中的state就类似于vue的data,用来做响应式的数据。
新建在src
目录中新建一个文件夹components,在components文件夹里新建test1.jsx和test2.jsx文件。(写js的话 .js文件也没问题)
test1:
//函数组件(组件的首字母必须大写)
import { react ,useState } from "react";
function Test1(){
let [ objA , setA ]= useState({
a: 123
})
let b= "我是b";
return(
<div>
<p>{objA.a}</p>
<p>{b}</p>
</div>
)
}
//暴露 Test1
export default Test1;
test2:
//class组件(要继承React的components)
import React from "react";//引入React
class Test2 extends React.Component {
//写一个构造函数
constructor(prop){
super(prop)
this.state = {
//响应式数据
a: 111,
arr: [1,2,3,4,5]
}
}
render(){
return(
<div>
<h1>Test2</h1>
<p>{this.state.a}</p>
</div>
)
}
}
export default Test2;
App.js:
import Test1 from "./components/test1"; //引入Test1
import Test2 from "./components/test2"; //引入Test2
import "./App.css";
function App() {
return (
<div className="App">
{/* 在页面上注册Test1、Test2组件 */}
<Test1></Test1>
<hr></hr>
<Test2></Test2>
</div>
);
}
export default App;
页面展示:
3.State的特点
直接修改数据是无效的,必须通过对应的方法修改state才能触发视图更新;
State得修改是一个浅合并得过程,是与原state对象合并的过程。
test1 修改方式:
function Test1(){
let [ objA , setA ]= useState({
a: 123
})
let b= "我是b";
setTimeout(() => {
setA({
a: 44225456434 //修改objA的值
})
}, 3000);
return(
<div>
<p>{objA.a}</p>
<p>{b}</p>
</div>
)
}
test2 修改方式:(修改单个数据、数组、对象)
//class组件(要继承React的components)
import React from "react";//引入React
class Test2 extends React.Component {
//写一个构造函数
constructor(prop){
super(prop)
this.state = {
a: 111, //单个数据
arr: [1,2,3,4,5], //数组数据
obj: {name: "张三", age: 25} //对象数据
}
}
render(){
setTimeout(() => {
let brr = this.state.arr;
brr.push(9);
let _obj = this.state.obj;
_obj.age = 66;
this.setState({
a: 222, //异步更新单个数据
//arr: [6,7,8,9,10,11], //创建了一个新的数组给它覆盖了
arr: brr, //在原数组上新增,注意每隔三秒都会新增一个元素
obj:_obj //更新了对象中的age属性
})
}, 3000)
return(
<div>
<h1>Test2</h1>
<p>{this.state.a}</p>
<p>{this.state.arr.join(",")}</p>
<p>姓名:{this.state.obj.name}</p>
<p>年龄:{this.state.obj.age}</p>
</div>
)
}
}
export default Test2;
3秒后页面变化: 修改成功
4.循环渲染
(1)forEach: 全部在 test2中修改
this.state = {
arr: [
{title: "标题1", content: "内容1"},
{title: "标题2", content: "内容2"},
{title: "标题3", content: "内容3"},
{title: "标题4", content: "内容4"},
{title: "标题5", content: "内容5"},]
} //存入数组对象
render(){
let arr = [];
this.state.arr.forEach((item, index) => { //forEach遍历数组,但要把结果存起来
let _item = <div key={index}>
<h2 style={{color: "red"}}>{item.title}</h2>
<p style={{color: "red"}}>{item.content}</p>
</div>
arr.push (_item);
})
return(
<div>
{ arr }
</div>
)
}
(2)map:
render(){
return(
<div>
{
//map会把数组中的每一项映射成一个新的数组
this.state.arr.map((item, index) => {
return (
<div key={index}>
<h2 style={{color: "red"}}>{item.title}</h2>
<p style={{color: "red"}}>{item.content}</p>
</div>
)
})
}
</div>
)
}
(3)函数:
createArrList(){
let arr = [];
this.state.arr.forEach((item, index) => { //forEach遍历数组,但要把结果存起来
let _item = <div key={index}>
<h2 style={{color: "red"}}>{item.title}</h2>
<p style={{color: "red"}}>{item.content}</p>
</div>
arr.push (_item);
})
return arr;
}
render(){
return(
<div>
{this.createArrList()}
</div>
)
}
页面展示:
5.条件渲染
在test1中修改:(这样写是整个<div>板块被换掉)
//函数组件(组件的首字母必须大写)
import { react ,useState } from "react";
function Test1(){
let [ objA , setA ]= useState({
a: 123
})
let[show,changeShow]=useState(0);
function showType(){
if(show===0){
return <div color="blue" >我是showType,show=0</div>
}else if(show===1){
return <div color="blue" >我是showType,show=1</div>
}else{
return <div color="blue" >{show}</div>
}
}
let b= "我是b";
setTimeout(() => {
setA({
a: 44225456434 //修改objA的值
})
}, 3000);
return(
<div>
<p>{objA.a}</p>
<p>{b}</p>
{showType()}
<button onClick={()=>changeShow(show+1)}>点击切换</button>
</div>
)
}
//暴露 Test1
export default Test1;
页面展示:
6.事件绑定
其实上面带了一个click事件了,就是click={ },注意一定要写花括号。
事件传参的话用.bind(this, ); 传参的过程中会把事件本身带回去,也就是下面代码中的“e”。
let[show,changeShow]=useState(0);
function changeDiv(num,e){
console.log(num);
console.log(e);
let _show = !show;
changeShow(_show);
}
function showType(){
if(show){
return <div color="blue" >show存在</div>
}
}
return(
<div>
{showType()}
<button onClick={changeDiv.bind(this,111)}>{show? "隐藏":"显示"}</button>
</div>
)
页面展示:
我这里遇到了一些问题,我想查看输出内容时,浏览器显示Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools。
我用的谷歌,查了一下是需要下载react-devtools调试工具。
下载方法:点击链接React Developer Tools - Chrome 应用商店-Chrome插件下载-收藏猫插件 (pictureknow.com)
点击“下载插件手动安装”。下载好后解压,按照下图步骤添加扩展。
这样点击按钮后就能在控制台看到传过去的参数和打印出来的e
7.综合制作列表效果
代码如下:综合上述所学。在components文件夹下新建tableList.jsx
import React from "react";
class TableList extends React.Component {
constructor(prop) {
super(prop);
this.state = {
type: 0,
equipment: [
{ name: "电视", price: 10000 },
{ name: "空调", price: 20000 },
{ name: "冰箱", price: 30000 }
],
trappings: [
{ name: "牛仔裤", price: 500 },
{ name: "连衣裙", price: 1500 }
]
};
}
changeTap(item) {
this.setState({ type: item });
}
showZero() {
let _equipment = (
<div>
{this.state.equipment.map((item) => {
return (
<div>
<span key={item.name}>{item.name}:</span>
<span key={item.price}>{item.price}</span>
<button
style={{ marginLeft: 10, backgroundColor: "pink" }}
onClick={this.deleteItem.bind(this, item.name)}
>
删除
</button>
</div>
);
})}
</div>
);
return _equipment;
}
showOne() {
let _trappings = (
<div>
{this.state.trappings.map((item) => {
return (
<div>
<span key={item.name}>{item.name}:</span>
<span key={item.price}>{item.price}</span>
</div>
);
})}
</div>
);
return _trappings;
}
deleteItem(name) {
// let _equipment = this.state.equipment.filter((item) => item.name !== name);
let _equipment = [];
this.state.equipment.forEach((item) => {
if (item.name !== name) {
_equipment.push(item);
}
});
this.setState({ equipment: _equipment });
}
showContent() {
return this.state.type === 0 ? this.showZero() : this.showOne();
}
render() {
return (
<div>
<button onClick={this.changeTap.bind(this, 0)}>设备列表</button>
<button onClick={this.changeTap.bind(this, 1)}>服饰列表</button>
{this.showContent()}
</div>
);
}
}
export default TableList;
8.样式操作
(1)在标签中加className = " " ,可以直接在App.css里面写样式。
(2)外联样式,一经加载将全局有效,所以类名在命名的时候要特别注意,避免全局污染,在components文件夹下新建tableList.css:
tableList.jsx:
import "./tableList.css";
<div className="table-list">
<button onClick={this.changeTap.bind(this, 0)}>设备列表</button>
<button onClick={this.changeTap.bind(this, 1)}>服饰列表</button>
{this.showContent()}
</div>
tableList.css:
.table-list {
position: absolute;
margin-top: 5%;
margin-left: 30%;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
background-color: #fff; /* 背景颜色 */
border-radius: 8px; /* 圆角 */
padding: 20px; /* 内边距 */
width: 80%; /* 宽度 */
max-width: 600px; /* 最大宽度 */
overflow: hidden; /* 隐藏溢出内容 */
transition: transform 0.3s; /* 添加过渡效果 */
}
页面展示:
(3)CSS Modules模块化
这种方式是webpack的方案,所有css只作用于当前组件,不会影响当前组件的后代组件,样式之间不会有冲突。
如果要用这个方式,那么tableList.css的命名要写成tableList.module.css,且.css文件要与对应的.js文件放在同一个文件夹里。tableList.js修改的代码如下:
import style from "./tableList.module.css";
<div className={style["table-list"]}>
9.生命周期
引用一下B站大佬的图:
(1)Mounting(挂载):已插入真实 DOM
(2)Updating(更新):正在被重新渲染
(3)Unmounting(卸载):已移出真实 DOM
总结
未完待续,持续更新