前端基础知识
块级作用域之var与let与const
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
{
let a=10;
var as=10;
}
// console.log(a);
console.log(as);
for(let aindex=0; aindex<10 ;aindex++){
console.log("let循环"+aindex);
}
// console.log(aindex);
for(var asindex=0; asindex<10 ;asindex++){
console.log("var循环"+asindex);
}
console.log(asindex);
</script>
</html>
var 无区级快,let有区级快,const有区级快只能赋值一次。
赋值
//解析赋值
// const name=["孙悟空","猪八戒"];
// let [a,b]=name;
// console.log(a);
// let [,bs]=name;
// console.log(bs);
// const nameList=["小红","小明","小刚","小王"];
// let [a,b,...c]=nameList;//剩余数组必须是最后一个 [a,...b,c]会出现错误
// console.log(a);
// console.log(b);
// console.log(c);
obj={
Name:"岳阳大学",
Age:"40",
Address:"湖南岳阳"
}
let a,b,c;
// ({Name:a,Age:b,Address:c}=obj)//不能去掉()
// console.log(a,b,c);
//第二种
// const {Name,Age,Address}=obj;
// console.log(Name,Age,Address);
//交换值
a=10;
b=20;
[a,b]=[b,a];
console.log(a+"he"+b);
展开
function addition (a,b,c){
return a+b+c;
}
const umber=[1,1,3];
let sum=addition(...umber);
console.log(sum);
const copyNum=[2,3,...umber];
console.log(copyNum);
const obj={
Name:"岳阳大学",
Age:"40",
Address:"湖南岳阳"
}
let objCopy={Name:"民族大学",...obj}
let objCopys={...obj,Name:"民族大学"}
console.log("展开前"+objCopy.Name);
console.log("展开后"+objCopys.Name);//如果名称一样后面的值将会覆盖之前的值
箭头函数
/*
箭头函数没有arguments
箭头函数中没有自己的this
他的this总是外层作用域的this
箭头函数中的this无法通过call()、apply()、bind()修改
箭头函数无法作为构造函数
*/
let sum=a=>console.log(a);
console.log(sum(12));
//arguments arguments 是一个对应于传递给函数的参数的类数组对象
function Hanshu(){
console.log(arguments.length);
}
let hanshu=(...arg)=>{
//console.log(arguments.length);//系统将会出现错误
//index箭头函数.html:29 Uncaught ReferenceError: arguments is not defined
};
//this指向
function pointToThis(){
console.log("函数");
console.log(this);
}
let Pointhis=()=>{
console.log("箭头函数");
console.log(this);
};
let obj={
Point:function(){
let Pointhis=()=>{
console.log("嵌入函数中的箭头函数");
console.log(this);
};
console.log("嵌入函数本身");
console.log(this);
Pointhis();
}
}
pointToThis();Pointhis();obj.Point();
模快化
export default 默认
import a from "./路径" 路径一定要带./
类
类的基本使用
/*
类
constructor构造函数
*/
class Person{
Name='';
Age=0;
constructor(name,age){
this.Name=name;//此时this指向person
this.Age=age;
}
run(){
console.log("我是person方法");
}
}
const personObj=new Person("小明",18);
console.log(personObj.Name);
personObj.run();
类的this
//"use strict";
/*
this指向
"use strict";严格模式
class默认为严格模式
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
this指向不稳定
*/
class Person{
Name="";
Age=0;
// fu(){ console.log(this);}
fu=()=>{console.log(this);}
}
const per=new Person();
per.fu();
const fus=per.fu;
fus();
类的继承
/*
类的继承
继承的关键词 extends
重写方法
1、重写方法直接重新输入名称
2、但是在参数的时候需要注意
1、用constructor构造函数必须将super()放在首句
*/
class Animal {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello = () => {
console.log("动物叫声");
}
}
class Dog extends Animal {
constructor(name,age,length){
super(name,age);
this.legth=length
}
sayHello = () => {
console.log("汪汪汪");
}
}
class Snake extends Animal {
sayHello = () => {
console.log("嘶嘶嘶");
}
}
new Dog().sayHello();
new Snake().sayHello();
const dogobj=new Dog("晓玲",12,24);
console.log(dogobj.name,dogobj.age,dogobj.legth);
类的静态属性
class Person{
static name="ok";
static fu=()=>{
console.log(this);
}
}
console.log(Person.name);
Person.fu();
React使用
初始react
在以下都是18.版本的使用
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React demo</title>
<script src="https://cdn.staticfile.org/react/18.0.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/18.0.0/umd/react-dom.development.js"></script>
</head>
<body>
<div id="app">
</div>
</body>
<!-- <script>
const biaoqian=document.createElement("div");
biaoqian.innerText="Hello Word!"
const ids=document.getElementById("app");
ids.after(biaoqian);
</script> -->
<script>
//这是18.0用的方法
const button=React.createElement('button',{},'我是按钮');
const root=ReactDOM.createRoot(document.getElementById('app'));
root.render(button);
// ReactDOM.render(
// <div>Hello Word!</div>,
// document.getElementById('app'));
</script>
</html>
jsx文件
使用的是声明式开发。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React demo</title>
<script src="https://cdn.staticfile.org/react/18.0.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/18.0.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="app">
</div>
</body>
<!-- <script>
const biaoqian=document.createElement("div");
biaoqian.innerText="Hello Word!"
const ids=document.getElementById("app");
ids.after(biaoqian);
</script> -->
<script type="text/babel">//这就是jsx的含义如果不加这个text/babel 与相应的js应用将会是失败就无法使用声明式编程标签
//创建一个<button>我是按钮</button>
//命令编程
// const button=React.createElement('button',{},'我是按钮');
//声明式编程
const button=<button>react開始</button>;
const root=ReactDOM.createRoot(document.getElementById('app'));
root.render(button);
</script>
</html>
jsx文件补充
- jsx不是字符串不要加引号
- jsx中的html标签要小写,大写是组件
- jsx有且只有一个根标签
- jsx中的标签必须也得正确
- 在jsx中使用{}嵌入表达式
- -必须写有值的语句就是表达式
- 如果表达式是空值、布尔值、undefined这些值将不会显示
- 在jsx中,属性可以直接在标签中使用 ***class要写为className、style中必须用对象设置不能用style=“background-color:red”,在这个对象中带-的属性必须用驼峰式命名
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React demo</title>
<script src="https://cdn.staticfile.org/react/18.0.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/18.0.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="app">
</div>
</body>
<script type="text/babel">
/*
jsx注意事项
1.jsx不是字符串不要加引号
2.jsx中的html标签要小写,大写是组件
3.jsx有且只有一个根标签
4.jsx中的标签必须也得正确
5.在jsx中使用{}嵌入表达式
-必须写有值的语句就是表达式
6.如果表达式是空值、布尔值、undefined这些值将不会显示
7.在jsx中,属性可以直接在标签中使用 ***class要写为className、style中必须用对象设置不能用style="background-color:red",在这个对象中带-的属性必须用驼峰式命名****
*/
const name = "小明";
const div = <div>
我的名字叫做{name}
<button id="btn" onClick={()=>{alert("5")}} className="box1" style={{backgroundColor:"red"}}>点击原地</button>
</div>;
const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(div);
</script>
</html>
渲染列表数据
简单数据渲染
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React demo</title>
<script src="https://cdn.staticfile.org/react/18.0.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/18.0.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="app">
</div>
</body>
<script type="text/babel">
/*
简单数据渲染
*/
const data = ['Item 1', 'Item 2', 'Item 3'];
const datas=data.map(((item,index)=>{
return <li key={index}>{item}</li>
}));
const ul = <ul>
{datas}
</ul>;
const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(ul);
</script>
</html>
脚手架react.js
命令行
- npx react-create-app react-basic react-basic 为项目名称
- mkdir 创建文件夹
- rmdir 删除文件夹
- echo ‘写入内容’>文件名
- cd… 返回上一级
- npm uninstall 包名
Jsx中js使用
CRA项目SRC目录
方法与变量识别
- 使用引导转递字符串
- 使用JavaScript变量
- 函数调用和方法调用
- 使用JavaScript
App.js
const message="这还是一句话";
const getHappiness=()=>{
return "幸福这东西,如果不放弃些什么,就无法得到它";
}
function App() {
return (
<div className="App">
这是一句话<br/>
{/*1.使用引号传递字符串 */}
{'这也是一句话'}<br/>
{/* 2.使用JavaScript变量 */}
{message}<br/>
{/* 函数调用和方法调用 */}
{getHappiness()}<br/>
{new Date().getDate()}
{/* 使用js对象 */}
<div style={{color:"red"}}>这是红色的</div>
</div>
);
}
export default App;
数据渲染
- {/* 列表渲染 */}
- {/* map 循环那个结构 return结构 */}
- {/* 注意事项:加上一个独一无二的key 字符串或者number id */}
- {/* key的作用:React框架内部使用 提升更新性能的 */}
const list = [
{ id: 1001, name: "Vue" },
{ id: 1002, name: "React" },
{ id: 1003, name: "Angular" },
];
function App() {
return <div className="App">
{/* 列表渲染 */}
{/* map 循环那个结构 return结构 */}
{/* 注意事项:加上一个独一无二的key 字符串或者number id */}
{/* key的作用:React框架内部使用 提升更新性能的 */}
<ul>
{list.map(item=><li key={item.id}>{item.name}</li>)}
</ul>
</div>;
}
export default App;
数据条件判断
- 第一种&& {yesno&&我从没觉得孤独,说的浪漫些,我完全自由}
- 第二种? {yesno?夕阳总会落在你身上,你也会快乐一场。:直到遇见你那一刻 我的星河才亮了起来.}
- 第三种自己定义 ()=>{}
const yesno=true;
const thems=1;
let themList=(them)=>{
if(them===0){
return <span>蜀道之难,难于上青天!</span>
}
else if(them===1){
return <span>蚕丛及鱼凫,开国何茫然!</span>
}
else if(them===2){
return <span>上有六龙回日之高标,下有冲波逆折之回川。</span>
}
};
function App() {
return <div className="App">
{yesno&&<span>我从没觉得孤独,说的浪漫些,我完全自由</span>}<br/>
{yesno?<span>夕阳总会落在你身上,你也会快乐一场。</span>:<span>直到遇见你那一刻 我的星河才亮了起来.</span>}<br/>
{themList(thems)}
</div>;
}
export default App;
前端事件
- 事件一般是驼峰式
- 事件获取可以通过{(e)=>{方法名(e)}}的方式
const GetName=()=>{
console.log("东海龙王");
}
const GetEOrName=(e,Name)=>{
console.log(e,"我的名字是",Name);
}
function App() {
return <div className="App">
<button onClick={(e)=>{GetEOrName(e,"北海龙王")}}>点我</button>
</div>;
}
export default App;
React组件
一个组件时页面的一部分,组件之间可以重复嵌套,也可以重复多次使用
必须大写
const GetName=()=>{
console.log("东海龙王");
}
const Buttons=()=>{
return <button onClick={GetName}>点我</button>
}
function App() {
return <div className="App">
{/* 闭合式 */}
<Buttons/>
{/* 双标签 */}
<Buttons></Buttons>
</div>;
}
export default App;
useState组件使用
useState是一个可以改变数据还可以使ui视图发生改变
对于复杂的类型处理 useState({name:“ss”}); setCout({…count,naem:“dd”});
只能在顶层或者自定义Hook中使用使用不能在if和for中
import {useState} from "react"
function App() {
let [count,setCount]=useState(0);
ojoi
const setCounts=()=>{
count++;
consle.log(count);
setCount(count+1);
}
return <div className="App">
<button onClick={setCounts}>{count}</button>
</div>;
}
export default App;
样式控制
- 第一种直接在dom元素使用{{color:“aqua”}}
- 第二种在外面使用对象数据来进行元素编辑,const styles={color:red}
- 第三种在外部创建css文件,后使用import “./css文件名.css”,在需要样式的文件上附上值
import { useState } from "react"
import "./index.css"
const styles={
color:"red"
}
const App=()=>{
const [count,setCount]=useState({name:"58"});
const SetCounts=()=>{
setCount({...count,name:"88"});
}
const Buttons=()=>{
return<div>
<button className="pri" onClick={SetCounts}>{count.name}</button>
<p style={styles}>sss</p>
<p style={{color:"aqua"}}>ddddd</p>
</div>
}
return <div id="App">
<Buttons />
</div>
}
export default App
lodash使用
Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。
- 输入 npm i --save lodash
- 利用useState组件里面的set来刷新变量和ui
import { useState } from "react";
import _ from "lodash";
function App() {
//用户信息
const User = {
Userid: "0304",
Name: "花开花落",
};
//书籍
let Namelist = [
{ id: 1, Name: "林立", Userid: "03014" },
{ id: 52, Name: "监视", Userid: "03014" },
{ id: 3, Name: "云霄", Userid: "03404" },
{ id: 64, Name: "不糊", Userid: "03044" },
{ id: 5, Name: "逍遥", Userid: "0304" },
];
//排序方式
let orderObjList = [
{
Labe: "升序",
Value: "asc",
},
{
Labe: "|",
Value: "",
},
{
Labe: "降序",
Value: "desc",
},
];
let [orders, Setoreder] = useState(orderObjList);
let [type, Settype] = useState("");
let [Names, SetNames] = useState("");
let [Namelists, SetNamelist] = useState(Namelist);
const SetNameListFunction = () => {
//添加数据
let idNum = Namelists.length + 1;
Namelists.push({ id: idNum, Name: Names, Userid: "0304" });
SetNamelist(Namelists);
console.log(Namelists);
SetNames("");
};
//删除
const DeleteNameList = (id) => {
const updatedNamelist = Namelists.filter((item) => item.id !== id);
SetNamelist(updatedNamelist); // 更新名字列表
};
//lodsah 排序
const orderyfunction = (types) => {
Settype(types);
SetNamelist(_.orderBy(Namelists, ["id"], types !== "" ? types : "asc"));
};
return (
<div className="App">
<div>
<input
type="text"
value={Names}
onChange={(e) => SetNames(e.target.value)}
></input>
<button onClick={SetNameListFunction}>添加书籍</button>
</div>
<br />
<div>
{orders.map((item) => (
<span
key={item.Value}
onClick={() => orderyfunction(item.Value)}
style={type === item.Value ? { color: "red" } : {}}
>
{item.Labe}
</span>
))}
</div>
<h1>喜欢书籍类型</h1>
<ul>
{Namelists.map((item) => (
<li key={item.id}>
{item.Name}
{item.Userid === User.Userid && (
<button
onClick={() => DeleteNameList(item.id)}
style={{ color: "red" }}
>
删除
</button>
)}
</li>
))}
</ul>
</div>
);
}
export default App;
input数据赋值
- 通过e的方式来获得数据,
e.target
表示触发事件的 DOM 元素
import { useState } from "react";
const App=()=>{
let[Names,SetNames]=useState("s");
return (
<div id="App">
123
<input type="text" value={Names} onChange={(e)=>{SetNames(e.target.value)}}/>
</div>
)
}
export default App
获取dom元素进行聚焦
- 首先将useRef导入
- 实列化useRef
- 再将ref=实例化useRef组件的值的参数名称放入dom元素中
- useRef参数名.current为Dom元素,.current后面接入.value为Dom元素的值
onsole.log()
主要用于输出文本信息,而console.dir()
则更适合用于显示对象的详细结构。
import { useRef } from "react";
//onsole.log() 主要用于输出文本信息,而 console.dir() 则更适合用于显示对象的详细结构。
const App=()=>{
const inputRef=useRef(null);
const clickHarvest=()=>{
console.dir(inputRef.current);
console.log(inputRef.current.value);
}
return (
<div id="App">
<input type="text" ref={inputRef} />
<button onClick={clickHarvest}>点击获取Dom元素</button>
</div>
)
}
export default App
import { useRef, useState } from "react";
//onsole.log() 主要用于输出文本信息,而 console.dir() 则更适合用于显示对象的详细结构。
const App=()=>{
let [values,setValues]=useState("");
const inputRef=useRef(null);
const clickHarvest=()=>{
console.dir(inputRef.current);
console.log(inputRef.current.value);
//进行值清空
setValues("");
//进行聚焦
inputRef.current.focus();
}
return (
<div id="App">
<input type="text" ref={inputRef} value={values} onChange={(e)=>{setValues(e.target.value)}} />
<button onClick={clickHarvest}>点击获取Dom元素</button>
</div>
)
}
export default App
插件day.js与uuid.js
安装 | Day.js中文网 (fenxianglu.cn)
import { useState } from "react";
import _ from "lodash";
import { v4 as uuidv4 } from 'uuid';
import dayjs from 'dayjs';
function App() {
//用户信息
const User = {
Userid: "0304",
Name: "花开花落",
};
//书籍
let Namelist = [
{ id: 1, Name: "林立", Userid: "03014",dateTime:"03-11 14:24"},
{ id: 52, Name: "监视", Userid: "03014",dateTime:"03-11 14:24" },
{ id: 3, Name: "云霄", Userid: "03404" ,dateTime:"03-11 14:24"},
{ id: 64, Name: "不糊", Userid: "03044" ,dateTime:"03-11 14:24"},
{ id: 5, Name: "逍遥", Userid: "0304" ,dateTime:"03-11 14:24"},
];
//排序方式
let orderObjList = [
{
Labe: "升序",
Value: "asc",
},
{
Labe: "|",
Value: "",
},
{
Labe: "降序",
Value: "desc",
},
];
let [orders, Setoreder] = useState(orderObjList);
let [type, Settype] = useState("");
let [Names, SetNames] = useState("");
let [Namelists, SetNamelist] = useState(_.orderBy(Namelist,['id'],"asc"));
const SetNameListFunction = () => {
//添加数据
let idNum = uuidv4();
let datetime=dayjs().format("MM-DD HH:mm");
Namelists.push({ id: idNum, Name: Names, Userid: "0304",dateTime:datetime });
SetNamelist(Namelists);
console.log(Namelists);
SetNames("");
};
//
//删除
const DeleteNameList = (id) => {
const updatedNamelist = Namelists.filter((item) => item.id !== id);
SetNamelist(updatedNamelist); // 更新名字列表
};
//lodsah 排序
const orderyfunction = (types) => {
Settype(types);
SetNamelist(_.orderBy(Namelists, ["id"], types !== "" ? types : "asc"));
};
return (
<div className="App">
<div>
<input
type="text"
value={Names}
onChange={(e) => SetNames(e.target.value)}
></input>
<button onClick={SetNameListFunction}>添加书籍</button>
</div>
<br />
<div>
{orders.map((item) => (
<span
key={item.Value}
onClick={() => orderyfunction(item.Value)}
style={type === item.Value ? { color: "red" } : {}}
>
{item.Labe}
</span>
))}
</div>
<h1>喜欢书籍类型</h1>
<ul>
{Namelists.map((item) => (
<li key={item.id}>
{item.Name}
{item.dateTime}
{item.Userid === User.Userid && (
<button
onClick={() => DeleteNameList(item.id)}
style={{ color: "red" }}
>
删除
</button>
)}
</li>
))}
</ul>
</div>
);
}
export default App;
组件之间的通信
父传子
- 使用name={}传递给子组件
- 子组件用props接受
- props可以接受任意类型数据
- 在父组件中用子组件然后包裹一个标签会自动变为子组件的子组件
//父传子
//1、使用name={}传递给子组件
//2、子组件用props接受
//3、props可以接受任意类型数据
//4、在父组件中用子组件然后包裹一个标签会自动变为子组件的子组件
const Part=(props)=>{
return (
<div>
<p>this{props.names}
{props.children}</p>
</div>
);
}
const App=()=>{
const Names="这是父组件里面的";
return (
<div id="App">
<Part names={Names}><span>孙子</span></Part>
</div>
)
}
export default App
子传父
- 核心:在子组件中调用父组件中的函数并传递实参
//子传父
//核心:在子组件中调用父组件中的函数并传递实参
import { useState } from "react";
const APPSon=({onPropsFunction})=>{
const Name="儿子";
return(
<div>
<button onClick={()=>{onPropsFunction(Name)}}>点击传递</button>
</div>
);
}
const App=()=>{
let [Name,setName]= useState("")
const getName=(Names)=>{
console.log(Names);
setName(Names);
};
return (
<div id="App">
{Name}
<APPSon onPropsFunction={getName}></APPSon>
</div>
)
}
export default App
兄弟之间传递参数
- 先将A中参数传递给父组件
- 再将父组件参数传递给B就完成了A到B中数据传递
//兄弟之间传递参数
//先将A中参数传递给父组件
//再将父组件参数传递给B就完成了A到B中数据传递
import { useState } from "react";
const A=({onPropsFunction})=>{
const Name="我是A,B是我的好朋友我要送她个礼物。"
return(
<div>
this is A comments;
<button onClick={()=>{onPropsFunction(Name)}}>点击</button>
</div>
);
}
const B=(props)=>{
return(
<div>
this is B comments;{props.name}
</div>
);
}
const App=()=>{
let [Name,setName]= useState("")
const getName=(Names)=>{
console.log(Names);
setName(Names);
};
return (
<div id="App">
this is App comment;
<A onPropsFunction={getName}></A>
<B name={Name}></B>
</div>
)
}
export default App
跨层传递参数
- 列如A到C中间有个B这种就叫做跨层
- 使用createContext方法创建一个上下文对象Ctx
- 在顶层组件(App)中通过Ctx.Provider组件提供数据
- 在底层组件(B)中通过useContext钩子函数获取消费数据
- 他不局限于底层和高层之间也可以是父子之间
//兄弟之间传递参数
//先将A中参数传递给父组件
//再将父组件参数传递给B就完成了A到B中数据传递
import { createContext, useContext } from "react";
const usercontextobj=createContext();
const A=()=>{
return(
<div>
this is A comments;
<B></B>
</div>
);
}
const B=()=>{
const Name=useContext(usercontextobj);
return(
<div>
this is B comments;{Name}
</div>
);
}
const App=()=>{
//注册useContext函数
const Name="我是从App里来";
return (
<div id="App">
<usercontextobj.Provider value={Name}>
this is App comment;
<A ></A>
</usercontextobj.Provider>
</div>
)
}
export default App
useEffect组件
- http://geek.itheima.net/v1_0/channels
- 列句
- useEffect(()=>{ },[]);第一个参数为当前要执行事件,第二个事件为执行时机
- 当[]为空的时候时机为组件初始渲染和组件更新时执行
- 当为[]的时候时机为旨在初始渲染的时候执行一次
- 当[]添加特殊依赖项时机为组件初始渲染和特定的依赖变化时执行
- 副作用执行时机是在组件卸载时自动执行return()=>{}
简单的useEffect使用
import { useEffect, useState } from "react"
const URL="http://geek.itheima.net/v1_0/channels"
const App=()=>{
let [list,setList]=useState([]);
useEffect(()=>{
//额外参数,获取频道
async function getList(){
const res=await fetch(URL);
const json =await res.json();
console.log(json);
setList(json.data.channels);
};
getList();
},[]);
return (
<div id="App">
this is App;
<ul>
{list.map((item)=>{
return <li key={item.id}>{item.name}</li>
})}
</ul>
</div>
)
}
export default App
当为空的时候
import { useEffect, useState } from "react"
const App=()=>{
const [Name,setName]=useState(0);
useEffect(()=>{
console.log("已经执行");
});
return (
<div id="App">
<button onClick={()=>{setName(Name+1)}}>{Name}</button>
</div>
)
}
export default App
当为[]的时候
import { useEffect, useState } from "react"
const App=()=>{
const [Name,setName]=useState(0);
useEffect(()=>{
console.log("已经执行");
},[]);
return (
<div id="App">
<button onClick={()=>{setName(Name+1)}}>{Name}</button>
</div>
)
}
export default App
当[]添加特殊数据
import { useEffect, useState } from "react"
const App=()=>{
const [Name,setName]=useState(0);
useEffect(()=>{
console.log("已经执行");
},[Name]);
return (
<div id="App">
<button onClick={()=>{setName(Name+1)}}>{Name}</button>
</div>
)
}
export default App
副作用
import { useEffect,useState } from "react"
const Aop=()=>{
useEffect(()=>{
const timer=setInterval(()=>{
console.log("计时器");
},1000);
return()=>{
clearInterval(timer);
};
},[]);
return(
<div>
<span>this is Aop</span>
</div>
);
}
const App=()=>{
const [app,setApp]=useState(true)
return (
<div id="App">
this is App
{app&&<Aop/>}
<button onClick={()=>{setApp(false)}}>点击卸载程序</button>
</div>
)
}
export default App
自定义hook
分装自定义hook思路
- 申明一个use打头的函数
- 在函数体内封装可复用的逻辑
- 把组件中用到的状态或者回调retrun出去
- 在那个组件中用到这个逻辑,就执行这个函数,解析出来状态和回调进行使用
import {useState} from "react"
const useShowOrHide=()=>{
const [state,setState]=useState(true);
const setStatefunction=()=>{
const statecopy=!state;
setState(statecopy);
}
return{
state,
setStatefunction
};
};
//比如用按钮控制一个div显示隐藏
const App=()=>{
const {state,setStatefunction}=useShowOrHide();
return (
<div id="App">
{state&&<div>this is App</div>}
<button onClick={()=>{setStatefunction()}}>点击</button>
</div>
)
}
export default App
json-server模拟服务
- 先在react的项目中加入一个json文件放入数据
- 然后安装npm install json-server -D
- 最后可以配置命令行json-server ./serve/data.json --port 8888或者直接执行,db为你当前json文件名字
- 执行后看到一个表情就执行成功了
- 然后新建一个终端,安装axios npm install axios
- 然后调用与使用axios.get(“url”)
import { useState,useEffect } from "react";
import { useRef } from "react";
import _ from "lodash";
import { v4 as uuidv4 } from 'uuid';
import dayjs from 'dayjs';
import axios from 'axios';
//封装初始数据hook
function useGetList(){
let [Namelists, SetNamelist] = useState([]);
useEffect(()=>{
async function getDate(){
const res=await axios.get("http://localhost:3004/list");
SetNamelist(res.data);
};
getDate();
},[])
return{
Namelists, SetNamelist
};
}
//封装 item
const BookItems=({item,Ondel,User})=>{
return<li key={item.id}>
名称:
{item.Name},
时间:
{item.dateTime}
{item.Userid === User.Userid && (
<button
onClick={() => Ondel(item.id)}
style={{ color: "red" }}
>
删除
</button>
)}
</li>;
}
function App() {
//用户信息
const User = {
Userid: "0304",
Name: "花开花落",
};
//书籍
// let Namelist = [
// { id: 1, Name: "林立", Userid: "03014",dateTime:"03-11 14:24"},
// { id: 52, Name: "监视", Userid: "03014",dateTime:"03-11 14:24" },
// { id: 3, Name: "云霄", Userid: "03404" ,dateTime:"03-11 14:24"},
// { id: 64, Name: "不糊", Userid: "03044" ,dateTime:"03-11 14:24"},
// { id: 5, Name: "逍遥", Userid: "0304" ,dateTime:"03-11 14:24"},
// ];
//获取dom元素进行聚焦
const userefObj=useRef(null);
//排序方式
let orderObjList = [
{
Labe: "升序",
Value: "asc",
},
{
Labe: "|",
Value: "",
},
{
Labe: "降序",
Value: "desc",
},
];
let [orders, Setoreder] = useState(orderObjList);
let [type, Settype] = useState("");
let [Names, SetNames] = useState("");
//let [Namelists, SetNamelist] = useState(_.orderBy(Namelist,['id'],"asc"));
//数据展示
let {Namelists, SetNamelist}=useGetList();
const SetNameListFunction = () => {
//添加数据
let idNum = uuidv4();
let datetime=dayjs().format("MM-DD HH:mm");
Namelists.push({ id: idNum, Name: Names, Userid: "0304",dateTime:datetime });
SetNamelist(Namelists);
console.log(Namelists);
//重新将input框值变为空
SetNames("");
//重新聚焦focus();
userefObj.current.focus();
};
//
//删除
const DeleteNameList = (id) => {
const updatedNamelist = Namelists.filter((item) => item.id !== id);
SetNamelist(updatedNamelist); // 更新名字列表
};
//lodsah 排序
const orderyfunction = (types) => {
Settype(types);
SetNamelist(_.orderBy(Namelists, ["id"], types !== "" ? types : "asc"));
};
return (
<div className="App">
<div>
<input
type="text"
value={Names}
ref={userefObj}
onChange={(e) => SetNames(e.target.value)}
></input>
<button onClick={SetNameListFunction}>添加书籍</button>
</div>
<br />
<div>
{orders.map((item) => (
<span
key={item.Value}
onClick={() => orderyfunction(item.Value)}
style={type === item.Value ? { color: "red" } : {}}
>
{item.Labe}
</span>
))}
</div>
<h1>喜欢书籍类型</h1>
<ul>
{Namelists.map((item) =>
<BookItems key={item.id} item={item} Ondel={DeleteNameList} User={User} />
)}
</ul>
</div>
);
}
export default App;
Redux快速上手
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width= , initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="decrement">-</button>
<span id="count">0</span>
<button id="increment">+</button>
</body>
<script src="./redux.min.js"></script>
<script>
//1、定义reducer函数
//作用:根据不同的action对象,返回不同新的state
//state:管理数据初始状态
//action:对象type标记当前想要做什么修改
function reducer(state = { count: 0 }, action) {
//数据不可变:基于原始状态生成一个新的状态
if (action.type === "INCRENT") {
return { count: state.count + 1 };
}
if (action.type == "DELETE") {
return { count: state.count - 1 };
}
return state;
};
//2、使用reducer函数生成store实例
const store=Redux.createStore(reducer);
//3、通过store实例的subscribe订阅数量变化
//回调函数可以在每次state发生变化时自动执行
store.subscribe(()=>{
console.log("state变化了",store.getState());
document.getElementById("count").innerText=store.getState().count;
});
//4、通过store实例的dispatch函数提交action更改状态
const inBtn=document.getElementById('increment');
inBtn.addEventListener("click",()=>{
//增
store.dispatch({
type:"INCRENT"
})
});
const Btn=document.getElementById('decrement');
Btn.addEventListener("click",()=>{
//增
store.dispatch({
type:"DELETE"
})
});
</script>
</html>
Redux与react
-
先输入命令行 npm i @reduxjs/toolkit react-redux
-
在src目录下面创建store然后接着创建modules和index.js,最后在modules加入相应的js模块(仓库)
-
第一步先将仓库模块在(modeules)文件夹下创建好(createSlice)注册好仓库名称(name)、仓库物品(initialState)、仓库物品作用(reducers)。
-
第二步注册好仓库在网上(configureStore),在注册网站(reducer)取好名字和对应仓库位置( counter:counterStore)
-
第三步开始使用首先在(react/index.js),网上找到仓库并打开(),然后拿到需要用到的地方(App.js)用到需要展示的物品用(useSelector)展示(useDispatch)用于针对物品操作
-
用action的payload属性获取他的方法传入的值。
-
//账单列表相关的store import { createSlice } from "@reduxjs/toolkit"; import axios from "axios"; const BillStore=createSlice({ name:"billstore", initialState:{ billList:[] }, reducers:{ //同步修改方法 setBillList(state,action){ state.billList=action.payload; }, //新增方法 addBill(state,action){ state.billList.push(action.payload); }, } }) const {setBillList,addBill}=BillStore.actions; const fillBillList=()=>{ return async(dispatch)=>{ const res=await axios.get("http://localhost:8888/ka"); dispatch(setBillList(res.data)); } } const addBillList=(data)=>{ return async(dispatch)=>{ const res=await axios.post("http://localhost:8888/ka",data); dispatch(addBill(res.data)); } } export {fillBillList,addBillList}; const reducer=BillStore.reducer; export default reducer;
import { configureStore } from "@reduxjs/toolkit"; import billrequred from "./Moudules/billStore" const store=configureStore({ reducer:{ bill:billrequred } }); export default store;
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import { RouterProvider } from 'react-router-dom'; import Roter from './Router'; import "./theme.css" import { Provider } from 'react-redux'; import store from './Store'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <Provider store={store}> <RouterProvider router={Roter} /> </Provider> );
Router 路由
什么是前端路由
-
npm i react-router-dom
-
导入createBrowserRouter和RouterProvider
-
写入path属性和element属性
文件跳转
- 第一种使用Link,import {Link} from “react-router-dom”
- 跳转
- 第二种使用useNavigate,import {useNavigate} from “react-router-dom”
- const navigate=useNavigate()
- <button Onclick=(()=>{navigate(“/跳转页面path”)})>跳转
import { Link,useNavigate } from "react-router-dom";
const Login=()=>{
const navigate=useNavigate();
return (
<div id="login">我是登录页面
<Link to="/article">跳转到文章页面</Link>
<button onClick={()=>{navigate("/article")}}>跳转</button>
</div>
);
}
export default Login
获取跳转参数
- 第一种方法useSearchParams,import { useSearchParams} from “react-router-dom”;
- 在执行跳转的页面写"/article?id=1&name=纳米"
- 在被跳转的页面写const SearchParams=useSearchParams(); const[params]=SearchParams.get(“参数”)
- 第二种useParams,import { useParams } from “react-router-dom”;
- 在执行跳转的页面写"/article/1001/Nami"
- const params=useParams();console.log(“name”,params.name,“,id”,params.id)
import { useSearchParams,useParams } from "react-router-dom";
const Article=()=>{
//第一种方法
// const [params]=useSearchParams();
// const id=params.get("id");
// const name=params.get("name");
// console.log(id);
// console.log(name);
//第二种方法
const params=useParams();
console.log("name",params.name,",id",params.id)
return (
<div id="Article">文章页面</div>
);
}
export default Article
路由嵌套
-
在做router配置的时候在路由属性中加入children
-
然后用Outlet来渲染嵌套的路由
import { Outlet,Link } from "react-router-dom"; const indexs=()=>{ return (<div> 我是indexs页面 <Link to="/about">关于</Link>|| <Link to="/details">详情</Link> <Outlet></Outlet> </div>); } export default indexs;
二级路由默认嵌套
-
将children中的path改为index设为true
-
将link中的to=“/demo"改为to=”
antD-mobile主题定制
分为局部与全局
- 局部用类名来进行css编写如.className{–add-color-primary:颜色}
- 全局:root:root{–add-color-primary:颜色}
:root:root{
--adm-color-primary:rgba(105,174,120);
}
/* .puple{
--adm-color-primary:#a062d4;
} */
配置@别名路径
比如路径开始"…/page"有了@就可以"@/page"
-
npm i @craco/craco
-
安装成功后创建craco.config.js文件
-
写入
-
const path=require("path"); module.exports={ webpack:{ alias: { '@':path.resolve(__dirname,'src') } } }
-
修改package.json里面scrpts内容
-
"scripts": { "start": "craco start", "build": "craco build", "test": "craco test", "eject": "react-scripts eject" }
-
然后加入jsconfig.json文件
-
{ "compilerOptions": { "baseUrl": "./", "paths": { "@/*":[ "src/*" ] } } }
高阶封装组件
//封装高价组件
//核心条款:有token正常跳转无token去登录
import { getToken } from "@/utils";
import { Navigate } from "react-router-dom";
export function AuthRoute({children}){
const token=getToken();
if(token){
return <>{children}</>
}
else{
return <Navigate to={'/'}></Navigate>
}
}
useMemo
-
useMemo用于处理复杂计算机
-
import { useMemo, useState } from 'react' function fib (n) { console.log('计算函数执行了') if (n < 3) return 1 return fib(n - 2) + fib(n - 1) } function App() { const [count, setCount] = useState(0) // 计算斐波那契之和 const sum = fib(count) // 通过useMemo缓存计算结果,只有count发生变化时才重新计算 // const sum = useMemo(() => { // return fib(count) // }, [count]) const [num, setNum] = useState(0) return ( <> {sum} <button onClick={() => setCount(count + 1)}>+count:{count}</button> <button onClick={() => setNum(num + 1)}>+num:{num}</button> </> ) } export default App
memo方法
-
memo方法用于限制因为usestate数据变化造成的子组件刷新问题
-
import { memo, useMemo, useState } from 'react' const MenoSon=memo( function Son(){ console.log("我是子组件,我重新渲染了"); return <div>thi is Son</div> } ) function Son(){ console.log("我是子组件,我重新渲染了"); return <div>thi is Son</div> } function App() { const [count,setCount]=useState(0); return ( <> <button onClick={()=>setCount(count+1)}>+</button> <Son></Son> {/* <MenoSon></MenoSon> */} </> ) } export default App
useCallBack组件
-
用于阻止事件重新渲染
-
import { memo, useCallback, useMemo, useState } from 'react' const MenoSon=memo( function Son({count}){ console.log("子组件重新渲染 "); return <input type='text' onChange={(e)=>{count(e.target.value)}}></input> } ) function App() { const [count,setCount]=useState(0); const valueSet=useCallback((value)=>{ console.log(value); },[]); return ( <> <button onClick={()=>setCount(count+1)}>+</button> <MenoSon count={valueSet}></MenoSon> </> ) } export default App
useReducre
-
const [state,dispatch]=useReducre(reducre,0);
-
主要是针对与复杂的赋值
-
import { useReducer } from "react"; function reducerl(state, action) { switch (action.type) { case "INC": return state + 1; case "DEC": return state - 1; default: return state; } } function App() { const [state, dispatclh] = useReducer(reducerl, 0); return ( <div className="App"> <button onClick={()=>dispatclh({type:"DEC"})}>-</button> this APP is {state} <button onClick={()=>dispatclh({type:"INC"})}>+</button> </div> ); } export default App;
props的比较机制
-
对于props的比较,进行的是‘浅比较’,底层使用
Object.is
进行比较,针对于对象数据类型,只会对比俩次的引用是否相等,如果不相等就会重新渲染,React并不关心对象中的具体属性 -
import { memo, useMemo, useState } from 'react' const MenoSon=memo( function Son({count}){ console.log("我是子组件,我重新渲染了"); return <div>thi is Son {count}</div> } ) function App() { const [count,setCount]=useState(0); // const [list,setList]=useState([0]); ///const listcopy=[1,2,3]; const list=useMemo(()=>{ return [1,2,3]; },[]) return ( <> <button onClick={()=>setCount(count+1)}>+</button> <MenoSon count={list}></MenoSon> </> ) } export default App
useImperativeHandle与forwardRef
-
将子节点的方法暴露给父节点
-
import { forwardRef, useImperativeHandle, useRef, useState } from 'react' //子组件 const Son=forwardRef((props,ref)=>{ const inputRef=useRef(null); const forcusHandler=()=>{ inputRef.current.focus() } //把聚焦方法暴露出去 useImperativeHandle(ref,()=>{ return { //暴露方法 forcusHandler } }) return <input type='text' ref={inputRef}></input> }) function App() { const sonRef=useRef(null); const focusHandle=()=>{ console.log(sonRef.current); sonRef.current.forcusHandler(); } return ( <> <Son ref={sonRef}></Son> <button onClick={focusHandle}>focus</button> </> ) } export default App
useRef与forwardRef
-
允许组件使用ref将一个DOM节点暴露给父组件
-
import { forwardRef, useRef } from "react"; const Son = forwardRef((props, ref) => { return <input type="text" ref={ref}></input>; }); function App() { const sonRef = useRef(null); const showRef = () => { console.log(sonRef); sonRef.current.focus(); }; return ( <> <button onClick={showRef}>+</button> <Son ref={sonRef}></Son> </> ); } export default App;
Scss文件
- 安装npm i -d sass
- 然后进行绑定就行了
normalize.css
- Normalize.css简介及详解、使用-CSDN博客
- npm install normalize.css 安装指令
- 在入口文件index.js导入import “normalize.css”
useLocation
获取当前路由名称
LocalStorage
用于存储数据不被页面刷新
Antd组件
- 组件总览 - Ant Design
- npm i antd -save
打包优化
配置路由懒加载
路由懒加载主要是优化项目首次打开时间
- 导入lazy函数
- 在内置react使用suspense组件
包体积分析
- 先安装包 npm i source-map-explorer
- 在package.json里面配置"analyze":“source-map-explorer ‘build/static/js/*.js’”
类组件
简单示例
import { Component, forwardRef, useImperativeHandle, useRef, useState } from 'react'
class Counts extends Component{
state={
count:0
};
setCount=()=>{
this.setState({
count:this.state.count+1
})
}
render(){
return <button onClick={this.setCount}>{this.state.count}</button>
}
}
function App() {
return (
<>
<Counts></Counts>
</>
)
}
export default App
生命周期
import { Component, forwardRef, useImperativeHandle, useRef, useState } from 'react'
class Counts extends Component{
//声明周期函数
//组件渲染完毕执行一次 发送网络请求
componentDidMount(){
console.log("组件渲染完毕 开始发送请求");
//定时器开始运行
this.timer=setInterval(()=>{
console.log('定时器运行中');
},1000);
}
//组件卸载时执行
//一般用于清理定时器和事件绑定
componentWillUnmount(){
console.log("组件被卸载了");
clearInterval(this.timer);
}
state={
count:0
};
setCount=()=>{
this.setState({
count:this.state.count+1
})
}
render(){
return <button onClick={this.setCount}>{this.state.count}</button>
}
}
function App() {
const [show,setShow]=useState(true);
return (
<>
{show&&<Counts></Counts>}
<button onClick={()=>setShow(!show)}>摧毁</button>
</>
)
}
export default App
父子通讯
-
子组件向父组件传值用函数赋值的方法
-
父组件向子组件传值直接传prop
-
import { Component, forwardRef, useImperativeHandle, useRef, useState } from 'react' //父组件定义 class Father extends Component{ state={ message:"this a exmal from you father" } FromFatherFunction=(fromSonValue)=>{ console.log("这是fromfatherfunction","fromSonValue的值",fromSonValue); }; render(){ return <><p>我来自父组件</p><Son msd={this.state.message} OnMsg={this.FromFatherFunction}></Son></> } } //子组件定义 class Son extends Component{ render(){ return <><p>我来自子组件</p>{this.props.msd} <button onClick={()=>{this.props.OnMsg("i am Son")}}>点击</button></> } } function App() { return ( <> <Father></Father> </> ) } export default App
zustand
简单使用
-
安装 yarn add zustand
-
import {create} from "zustand" const useStore=create((set)=>{ return{ count:0, inc:()=>{ set((state)=>({count:state.count+1})) } } }); function App() { const {count,inc}=useStore(); return ( <> <button onClick={inc}>{count}</button> </> ) } export default App
异步使用
import {create} from "zustand"
import {useEffect} from "react"
const URL='http://geek.itheima.net/v1_0/channels';
const CreateCountStore=(set)=>{
return {
count:0,
inc:()=>{
set((state)=>({count:state.count+1}))
}
}
}
const CreateChannelsStore=(set)=>{
return{
channlesList:[],
fetchGetList:async()=>{
const res=await fetch(URL);
const jsonRes=await res.json();
console.log(jsonRes);
set({channlesList:jsonRes.data.channels});
}
}
}
const useStore=create((...a)=>{
return{
...CreateChannelsStore(...a),
...CreateCountStore(...a)
}
});
function App() {
const {count,inc,fetchGetList,channlesList}=useStore();
useEffect(()=>{
fetchGetList();
},[fetchGetList]);
return (
<>
<button onClick={inc}>{count}</button>
<ul>
{channlesList.map((item)=>{return <li >{item.name}</li>})}
</ul>
</>
)
}
export default App
切片编程
分成与redux一样的结构
vite+react+ts
前言
vite在线文档:开始 | Vite 官方中文文档 (vitejs.cn)
vite创建项目指令:npm create vite@latest react-vite-demo – --template react-ts
romFatherFunction=(fromSonValue)=>{
console.log(“这是fromfatherfunction”,“fromSonValue的值”,fromSonValue);
};
render(){
return <>
我来自父组件
</>}
}
//子组件定义
class Son extends Component{
render(){
return <><p>我来自子组件</p>{this.props.msd}
<button onClick={()=>{this.props.OnMsg("i am Son")}}>点击</button></>
}
}
function App() {
return (
<>
<Father></Father>
</>
)
}
export default App
## zustand
#### 简单使用
1. 安装 yarn add zustand
2. ```js
import {create} from "zustand"
const useStore=create((set)=>{
return{
count:0,
inc:()=>{
set((state)=>({count:state.count+1}))
}
}
});
function App() {
const {count,inc}=useStore();
return (
<>
<button onClick={inc}>{count}</button>
</>
)
}
export default App
异步使用
import {create} from "zustand"
import {useEffect} from "react"
const URL='http://geek.itheima.net/v1_0/channels';
const CreateCountStore=(set)=>{
return {
count:0,
inc:()=>{
set((state)=>({count:state.count+1}))
}
}
}
const CreateChannelsStore=(set)=>{
return{
channlesList:[],
fetchGetList:async()=>{
const res=await fetch(URL);
const jsonRes=await res.json();
console.log(jsonRes);
set({channlesList:jsonRes.data.channels});
}
}
}
const useStore=create((...a)=>{
return{
...CreateChannelsStore(...a),
...CreateCountStore(...a)
}
});
function App() {
const {count,inc,fetchGetList,channlesList}=useStore();
useEffect(()=>{
fetchGetList();
},[fetchGetList]);
return (
<>
<button onClick={inc}>{count}</button>
<ul>
{channlesList.map((item)=>{return <li >{item.name}</li>})}
</ul>
</>
)
}
export default App
切片编程
分成与redux一样的结构
[外链图片转存中…(img-1NPG0lDF-1723444851992)]
vite+react+ts
前言
vite在线文档:开始 | Vite 官方中文文档 (vitejs.cn)
vite创建项目指令:npm create vite@latest react-vite-demo – --template react-ts