1.复习js中的三种变量声明
三种声明方式:第一种:首先使用的const 如果希望变量被改变则使用let关键字 至于var关键字最好报在代码中出现
Title
解构赋值
展开:
//展开:
function fn(a,b,c) {
return a+b+c;
}
const arr=[1,2,3];
//计算数组中三个数的和
/*let result=fn(arr[0],arr[1],arr[2]);
console.log(result)*/
//可以通过 ...来展开一个数组
let result=fn(...arr)
console.log(result)
//2.相当于将arr复制
const arr2=[...arr,4,5,6];
console.log(arr2);
//3.对象的展开 相当于一个复制
const obj={
name:'解雨臣',
age:'23',
sex:'男'
};
const obj2={...obj,address:'吴山居'};
console.log(obj2);
//箭头函数:箭头函数是传统函数表达式的简写方式 他简化了函数的编写
//特点:箭头函数没有自己的this 不能作为构造函数来使用 无法通过call apply bind 指定函数的this
//1.箭头函数的定义:
//类型一:只有一个参数的箭头函数 参数=>返回值
const fn=function (a) {
return '我是函数';
}
//等价于:
const fn2=a =>'我是函数';
console.log(fn2(1));
//类型二:两个参数:如果没有参数 或多个参数 参数需要用()括起来
//()=>返回值 (a,b,c)=>返回值
const fn3 =(a,b,c)=>a+'我是另一个箭头函数';
console.log(fn3());
//例如:
const sum=(a,b)=>a+b;//箭头后面的值就是返回值 返回值必须是·一个表达式
let t=sum(1,2);
console.log(t);
//表达式:有返回值的语句
const vb=(m,n)=>({name:'吴邪',age:18,sex:'男'})
console.log(vb());
//如果需要在箭头函数中定义逻辑 则可以在后面书写代码块
const fn4=(a,b)=>{
if (a===b){
a+=5;
console.log(a)
}else if (a===10){
a+=10;
}
return a+b;
};
console.log(fn4(2,2))
/*
* 箭头函数:只有一个参数返回值 参数 =>返回值
* 如果没有参数 或多个参数 参数需要使用()括起来
* ()=>返回值
* (a,b,c)=>返回值
*
* 箭头后面的值就是函数的返回值
* 返回值必须是一个表达式
* 如果返回值是对象 必须加()
*
* 如果需要在箭头函数中定义逻辑 可以直接在箭头后跟一个代码块
*
*
* */
//特点:
function fn(...args){
console.log(args);
console.log(arguments.length);//表示当前函数的实参 用来保存函数的实参
}
fn();
const fn2=(...aggs)=>{
// console.log(arguments) 箭头函数没有这个
console.log(aggs);
};
fn2()
/*
* 1.箭头函数中没有argue
* 2.箭头函数中没有自己的this
* -它的this总是外边的this 也就是全局作用域的this
* 3.箭头函数中的this无法通过call() apply()来修改
*
* 4.箭头函数无法作为构造函数来使用
* */
const fn3=()=>{
console.log(this)
};
fn3()
const obj={
hello:()=>{
console.log(this)
}
}
obj.hello();
new fn();//fn是普通函数
js中的模块化:
/*js中的模块化:
*
*es中的模块化分为为:export (导出)和 import(导入)
*
* */
export const a=10;//导出a
const b=20;
const c=90;
const obj={
name:'吴邪',
age:'18'
}
const fn=()=>{
console.log('我是fn');
}
fn()
//作为一个模块,我们不希望模块中的内容都暴露给外部
//作为导入方:我们也不希望导入无用的变量
// export导出:导出用来决定模块中那些内容可以被外部查看
//导出分为两种:
//1.默认导出
//2.命名导出
//1.默认导出:语法:export default 要导出的值
export default a;//将变量a作为默认导出
/*2.导入:import 导入用来将外部模块中的内容导入当前模块中
* -import obj from '../react教程/react03' 导入模块时 变量名可以自主指定 无需和模块中的变量名对应
* */
//导入模块中的默认模块
import a from './react03';//这样写不会成功
/*
* 默认情况下script标签不能使用import语句:如果想让其支持模块化 必须设置script属性为module
*
* */
import a from '../react教程/react03'
console.log(a)
/*
* 在网页中导入模块时 模块的路径必须写完整 (./或../开头 扩展名也必须写上)
* */
//导入指定的内容:import {b,c} from './react02.js'
//也可以更改变量名称:import {b as x,c} from './react02.js'
export {obj,fn};//命名导出
类(Class):类是对象的模块 类中定义了对象中包含了那些属性和方法 也可以跳过function来定义类 但是两种方式并不是完全通用
/*
* 1.类的定义:
* 类是对象的模板 类决定了一个对象有哪些属性和方法
* 使用class关键字来定义一个类
*
*
* */
class person{
//在类中可以定义属性
// 属性
name='吴邪';
//属性
age=19;
// 在类中定义方法
// 定义了一个实例化方法
run(){
console.log("我是一个实例化方法")
}
// 构造函数:当我们通过new创建对象时 实际上就是在调用类的构造函数
constructor(name,age) {
//在构造函数中我们可以跳过this来应用当前的对象
//将参数赋值给对象中的属性
this.name=name;
this.age=age;
console.log("我是构造函数")
}
}
const per=new person('吴邪','12');
console.log(per);
//类中的MyClass
class MyClass{
fn(){
console.log(this)
}
fn3=()=>{
console.log(this)
}
}
const mc=new MyClass();
console.log(mc)
mc.fn();//调用方法 和Java中的一样
const test=mc.fn;
test()//以函数的形式调用 就是未定义
//类中的所有代码斗湖在严格模式下执行 严格模式的特点就是函数的this就不是window
"use strict";
//注意:在类中方法的this不是固定的 以方法形式调用时 this就是当前的实例 以函数形式调用 this是undefined
//在开发的时候 我们希望方法中的this是固定的 不会因为调用方式不同而改变
//如果有这种需求 我们可以使用箭头函数来定义
/*如果类中的方法是以箭头函数来定义的 则方法中的this恒为当前示例 不会改变
*
* */
/*
* 类中的继承:
*
* */
class Dog{
constructor(name,age) {
this.name=name;
this.age=age;
}
sayHello=()=>{
console.log("你好")
}
}
//从以上代码可以看出:上面哟荤多重复的代码 一次我们可以吧许多共有的代码提取出来 然后使用继承
//将多个重复代码提取出来
class Animal{
constructor(name,age) {
this.name=name;
this.age=age;
}
sayHello=()=>{
console.log("吴邪")
}
}
//通过使用继承 我们可以使得其他类中的属性和方法
/*
class Snake{
constructor(name,age) {
this.name=name;
this.age=age;
}
SayHello=()=>{
console.log("你好!")
}
}*/
//使用extends来继承一个类 继承后就相当于将该类的代码赋值到了当前类
class Snake extends Animal{
//当我们在子类中重写父类构造函数时 必须在子类构造函数中第一时间调用父类构造函数 否则会报错
constructor(lenngth,anme,age) {
super(name,age);//这个就是第一时间调用
// 然后再重新定义一个length
this.len=lenngth;
}
// 很明显代码块内没有代码但是仍然可以控制台输出
}
const dog=new Snake('吴邪','12');
dog.sayHello()
console.log(dog);
//当我们使用继承后 被继承的类就称为父类 继承父类的类 称为子类
//子类继承父类后 将获得父类指定所有属性和方法
//也可以创建同名属性或方法来对父类进行重写
/*静态属性和方法:
*
* 直接通过类调用的属性和方法被称为静态属性和静态方法
*
*
*
* */
class MyClass{
name='吴邪';//属性
fn=()=>{//方法
console.log("铁三角")
}
}
//开始面向对象
const mc=new MyClass();
mc.fn()
console.log(mc.name);
//使用static关键字来定义
class MyClass1{
static name='吴邪';//属性
static fn=()=>{//方法
console.log("铁三角")
}
}
//开始面向对象
console.log(MyClass1.name);
console.log(MyClass1.fn());
/*数组的方法:
* 1.map()-根据原有数组返回一个新数组
*
* */
const arr=[1,2,3,45,6];
let map = arr.map(()=>10);//这个直接是把数组中的所有元素都变为10
console.log(map);
//需要一个回调函数作为参数 回调函数的返回值会最为数组中的元素
/*let map1 = arr.map((item)=>item+2);//这个代表把数组中的每个元素都加2
console.log(map1);*/
let map1 = arr.map((item,index)=>item+2);//这个代表把数组中的每个元素都加2
console.log(map1);
//回调函数中有三个参数:
/*
* 第一个参数:当前元素
* 第二个参数:当前元素的索引
* 第三个参数:当前数组
*
* */
const arr2=['吴邪','解雨臣','张起灵','王胖子']
let strings = arr2.map(item=>""+item+" ");
console.log(strings);
/*
*
* filter()过滤:可以从一个数组中获得符合条件的元素*/
const arr3=[1,2,3,4,5];
let numbers = arr3.filter(item=>item%2===0);
console.log(numbers);
//会根据回调函数的结果来决定是否保留元素 true保留 FALSE 不保留
//find()会从数组中找到符合条件的第一个元素
let number = arr3.find(items=>items%2===0);
console.log(number);
//reduce()用来整合数组 也就是对数组中的元素进行运算
console.log(arr.reduce((m, n) => {
console.log(m, n);
return m + n;
}),1);//指定初始值
//需要两个参数:回调函数:指定运算规则 四个参数:m上一次运算结构 n当前值 index 当前索引 arr 当前值
//初始值:用来指定第一次运算的m 如果不指定则直接从第二个元素开始计算
1.网页中是BS架构
react是一个用于构建用户界面的JavaScript库 用来为携带的网络构建用户界面 react起源于Facebook
react特点:虚拟dom 声明式 基于组件 支持服务器端渲染 快速简单 易学
2.书写第一个程序:hello world
解决了兼容性的问题
基于传统编程的命令式 react采用声明式
helloworld的书写:在入门阶段我们使用js脚本来书写:
react.js
react-dom.js
代码示例:
hello world
三个API之一:
三个API
Title
JSX
JSX的注意
注意:如果在页面中书写的代码没有在对应的网页中显示可以更改一下默认值:
更改为
渲染列表
虚拟DOM
react项目的创建使用:
步骤:
-创建根目录:
-public
-index.html
-src
-App.js
-index.js
创建完成文件后在 文件目录 进入终端输入:npm init -y
然后在终端安装依赖:输入命令:
React-project>npm install react react-dom react-scripts -S
依赖下载完成后 开始配置:
index.js文件示例:
/*src下的index.js是js的入口文件
*
* */
//引入ReactDOM
import ReactDOM from 'react-dom/client';
//创建一个jsx
const App=
计算机科学与技术学院欢迎你! 你好!
计算机科学与技术学院
;
//2.获取根容器
const root=ReactDOM.createRoot(document.getElementById('root'));
//将App渲染到根容器
root.render(App);
index.html代码示例:
react项目
package.json代码示例:
{
"name": "03_React_Project",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-scripts": "^5.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
创建public 和src文件
public下的index代码示例:
练习
src文件夹下:
index.css样式:
/*设置body的样式*/
body{
background-color: darkorange;
}
/*设置基本样式*/
*{
box-sizing: border-box;
margin: 0;
}
/*设置最外面容器的样式*/
.logs{
/*设置宽度*/
width: 800px;
/*设置居中*/
margin: 50px auto;
/*设置背景颜色*/
background-color: #0A246A;
border-radius: 10px; /*设置边框圆角*/
box-shadow: 0 0 10px rgba(0,0,0,.3);
}
/*设置item的样式
*/
.item{
/* 开启弹性盒子*/
display: flex;
/*设置了背景颜色*/
background-color: #00C1B3;
/* */
border-radius: 10px; /*设置边框圆角*/
box-shadow: 0 0 10px rgba(0,0,0,.2);
margin: 16px 0;
padding: 6px;
}
/*设置日期*/
.date{
width: 90px;
background-color: #F4F9FF;
border-radius: 10px;
font-weight: bold;
/*设置为居中*/
text-align: center;
overflow: hidden;
}
/*设置月份的效果*/
.month{
height: 25px;
background-color: #D62828;
line-height: 30px;
color: #F4F9FF;
font-size: 20px;
}
/*设置日期的效果*/
.day{
height: 60px;
line-height: 60px;
font-size: 50px;
}
/*设置日志的样式*/
.content{
/* 设置弹性盒子*/
flex: auto;
text-align: center;
}
/*设置描述内容*/
.desc{
font-size: 16px;
color: #194B49;
}
/*设置学习时间*/
.time{
color: #D91600;
}
index.js代码:
//创建完成后 通过终端开始初始化:终端输入:npm init y 开始初始化(注意一定要联网)
//安转依赖:npm install react react-dom react-scripts -S
import ReactDOM from 'react-dom/client';
//引入样式表
import './index.css'
//创建一个react元素
const App=
{/*日志项容器*/}
{/*hello 计算机科学与技术学院*/}
{/*容器的容器*/}
四月
18
{/* 日志内容的容器*/}
学习React
40分钟
四月
19
{/* 日志内容的容器*/}
学习数据结构与算法
40分钟
四月
20
{/* 日志内容的容器*/}
学习计算机组成原理
40分钟
四月
21
{/* 日志内容的容器*/}
学习JavaSpring
40分钟
//获取元素
const root=ReactDOM.createRoot(document.getElementById('root'));
//渲染元素
root.render(App)
1.在react中网页被拆分为了一个个组件 组件具有独立页面
创建src和public文件夹:
public文件夹:index.html代码示例:
练习
src文件下:
App代码示例;
/**/
const App=()=>{
return 我是学生
}
//导出
export default App;
indexdaima1:示例:
/*
* 在react中组件有两种创建方式:
* 函数式组件:函数组件就是一个返回jsx的普通函数
* --注意:组件的首字母必须大写
* 类组件:
*
*
* */
import ReactDOm from "react-dom/client"
/*
function App() {
return 计算机科学与技术学院欢迎您!
}
*/
import App from "./App"
const root=ReactDOM.createRoot(document.getElementById('root'))
//react组件可以直接通过jsx去渲染
root.render( )
创建public和src文件夹
public文件夹书写index.html
类组件
src文件夹:
App.js
import Logs from "./Components/Logs/Logs";
const App = () => {
return
};
// 导出App
export default App;
index.js文件:
import ReactDOM from "react-dom/client";
import App from "./App";
import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
// React组件可以直接通过JSX渲染
root.render( );
src下的Component:
LogItem.css文件:
/*设置item的样式*/
.item{
/*开启弹性盒*/
display: flex;
margin: 16px 0;
padding: 6px;
background-color: #FCBF49;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,.2);
}
/*设置日志内容的样式*/
.content{
flex: auto;
text-align: center;
font-weight: bold;
}
/*设置描述内容*/
.desc{
font-size: 16px;
color: #194B49;
}
/*设置学习时间*/
.time{
color: #D62828;
}
LogItem.js文件:
import React from 'react';
import MyDate from "./MyDate/MyDate";
import './LogItem.css'
const LogItem = () => {
return (
{/* 日志内容的容器 */}
学习React
40分钟
);
};
export default LogItem;
Component下的Log下的LogItem下的Mydate文件:
MyDate.css文件:
/*设置日期的样式*/
.date{
width: 90px;
background-color: #fff;
border-radius: 10px;
font-weight: bold;
text-align: center;
overflow: hidden;
}
/*设置月份效果*/
.month{
height: 30px;
line-height: 30px;
font-size: 20px;
color: #fff;
background-color: #D62828;
}
/*设置日期的效果*/
.day{
height: 60px;
line-height: 60px;
font-size: 50px;
}
MyDate.js文件:
import React from 'react';
import './MyDate.css';
const MyDate = () => {
return (
四月
19
);
};
export default MyDate;
创建public文件夹和src文件夹
1.在public文件夹下创建index.html
Title
2.在src文件夹下创建App.js
const App = () => {
const clickHandler = (event) => {
event.preventDefault(); // 取消默认行为
event.stopPropagation(); // 取消事件的冒泡
alert('我是App中的clickHandler!');
/*
* 在React中,无法通过return false取消默认行为
* return false;
*
* 事件对象
* - React事件中同样会传递事件对象,可以在响应函数中定义参数来接收事件对象
* - React中的事件对象同样不是原生的事件对象,是经过React包装后的事件对象
* - 由于对象进行过包装,所以使用过程中我们无需再去考虑兼容性问题
* */
};
return {
alert('div');
}}
style={{width: 200, height: 200, margin: '100px auto', backgroundColor:'#bfa'}}>
{/*
在React中事件需要通过元素的属性来设置,
和原生JS不同,在React中事件的属性需要使用驼峰命名法:
onclick -> onClick
onchange -> onChange
属性值不能直接执行代码,而是需要一个回调函数:
onclick="alert(123)"
onClick={()=>{alert(123)}}
*/}
超链接
};
/*
*
*
*
*
* document.getElementById('btn01').onclick = function(){};
* document.getElementById('btn01').addEventListener('click', function(){}, false);
*
*
* */
// 导出App
export default App;
3.在src文件夹下创建index.js文件
import ReactDOM from "react-dom/client";
import App from "./App";
import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
// React组件可以直接通过JSX渲染
root.render( );
需要动态的实现数据的更新
1.创建public和src文件夹
在public文件夹下创建index.html
在src文件夹下创建AApp.js index.js
src文件夹下创建Component文件夹
Component文件夹下创建 Logs文件夹 Logs文件夹下创建Logitem
Logitem文件夹下创建 Mydate文件夹 在此文件夹下创建 Mydate.css MyDate.js
在Logitem文件夹下创建Logitem.css Logitem.js
在Logs文件夹下创建 Logs.css Logs.js
index.js代码:
import ReactDOM from "react-dom/client";
import App from "./App";
import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
// React组件可以直接通过JSX渲染
root.render( );
index.css代码:
/*设置基本样式*/
*{
box-sizing: border-box;
}
/*设置body的样式*/
body{
background-color: #DFDFDF;
margin: 0;
}
App.js代码:
import Logs from "./Components/Logs/Logs";
const App = () => {
return
};
// 导出App
export default App;
Logs.js代码:
/* 日志的容器 */
import LogItem from "./LogItem/LogItem";
import './Logs.css';
const Logs = () => {
const logData=[
{
id:'001',
date:new Date(2021,1,20,18,30),
desc:'学习计算机网络',
time:30
},
{
id:'002',
date:new Date(2021,2,10,28,30),
desc:'学习前端',
time:30
},
{
id:'003',
date:new Date(2021,3,10,8,30),
desc:'学习javaWeb',
time:30
},
{
id:'004',
date:new Date(2021,9,1,8,30),
desc:'学习javaWeb',
time:80
},
];
//将数据放入jsx
const LogItemDate=
logData.map(item=> )
return
{/*在父组件中可以直接在子组件中设置属性*/}
{/*{}} />*/}
{
LogItemDate
}
};
export default Logs;
Log.css代码:
/*设置外层容器logs的样式*/
.logs{
width: 800px;
margin: 50px auto;
padding: 20px;
background-color: #EAE2B7;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,.2);
}
Logitem.css代码:
/*设置item的样式*/
.item{
/*开启弹性盒*/
display: flex;
margin: 16px 0;
padding: 6px;
background-color: #FCBF49;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,.2);
}
/*设置日志内容的样式*/
.content{
flex: auto;
text-align: center;
font-weight: bold;
}
/*设置描述内容*/
.desc{
font-size: 16px;
color: #194B49;
}
/*设置学习时间*/
.time{
color: #D62828;
}
Logitem.js代码:
import React from 'react';
import MyDate from "./MyDate/MyDate";
import './LogItem.css'
const LogItem = (props) => {
// 在函数组件中,属性就相当于是函数的参数,可以通过参数来访问
// 可以在函数组件的形参中定义一个props,props指向的是一个对象
// 它包含了父组件中传递的所有参数
// console.log(props.date);
/*
* 注意:props是只读的不能修改
*
*
*
* */
return (
{/* 日志内容的容器 */}
{/*
如果将组件中的数据全部写死,将会导致组件无法动态设置,不具有使用价值
我们希望组件数据可以由外部设置,在组件间,父组件可以通过props(属性)向子组件传递数据
*/}
{props.desc}
{props.time}分钟
);
};
export default LogItem;
Mydate.css代码:
/*设置日期的样式*/
.date{
width: 90px;
background-color: #fff;
border-radius: 10px;
font-weight: bold;
text-align: center;
overflow: hidden;
}
/*设置月份效果*/
.month{
height: 30px;
line-height: 30px;
font-size: 20px;
color: #fff;
background-color: #D62828;
}
/*设置日期的效果*/
.day{
height: 60px;
line-height: 60px;
font-size: 50px;
}
Mydate.js代码:
import React from 'react';
import './MyDate.css';
const MyDate = (props) => {
// console.log(props.date.getDate());
// 获取月份
const month = props.date.toLocaleString('zh-CN', {month:'long'});
// 获取日期
const date = props.date.getDate();
return (
{month}
{date}
);
};
export default MyDate;
import './app.css';
import {useState} from "react";
const App = () => {
console.log('函数执行了 ---> 组件创建完毕!');
/*
* 在React中,当组件渲染完毕后,再修改组件中的变量,不会使组件重新渲染
* 要使得组件可以收到变量的影响,必须在变量修改后对组件进行重新渲染
* 这里我们就需要一个特殊变量,当这个变量被修改使,组件会自动重新渲染
*
* state相当于一个变量,
* 只是这个变量在React中进行了注册,
* React会监控这个变量的变化,当state发生变化时,会自动触发组件的重新渲染
* 使得我们的修改可以在页面中呈现出来
*
* 在函数组件中,我们需要通过钩子函数,获取state
*
* 使用钩子 useState() 来创建state
* import {useState} from "react";
*
* 它需要一个值作为参数,这个值就是state的初始值
* 该函数会返回一个数组
* 数组中第一个元素,是初始值
* - 初始值只用来显示数据,直接修改不会触发组件的重新渲染
* 数组中的第二个元素,是一个函数,通常会命名为setXxx
* - 这个函数用来修改state,调用其修改state后会触发组件的重新渲染,
* 并且使用函数中的值作为新的state值
*
*
*
*
* */
const [counter, setCounter] = useState(1);
// let counter = result[0];
// let setCounter = result[1];
// const [counter, setCounter] = result;
/*
* 当点击+时,数字增大
* 点击-时,数字减少
* */
// 创建一个变量存储数字
// let counter = 2;
const addHandler = () => {
// 点击后数字+1
// alert('+1');
// counter++;
setCounter(counter + 1); // 将counter值修改为2
};
const lessHandler = () => {
// 点击后数字-1
// alert('-1');
// counter--;
setCounter(counter-1);
};
return
{counter}
;
};
// 导出App
export default App;
import './app.css';
import {useState} from "react";
const App = () => {
console.log('函数执行了 ---> 组件创建完毕!');
/*
* State:
* --state实际上就是一个react管理的变量
* 当我们通过setState()修改变量的值时 会触发组件的自动刷新
* 只有state值方式变化时 才会发生渲染
*
* 当state的值是一个对象时 修改时是使用新的镀锡去替换已有的对象
* 当通过setSate去修改state 并不会修改当前的state 它修改的是组件下一次渲染的state值
*
* setState()会触发组件的重新渲染 它是异步的
* 因此当我们调用setState()需要用到state的值时 用到要注意有可能出现计算错误的情况
* 为了避免出现这种情况 我们通过setState()传递回调函数
*
*
* */
const [user,setUser]=useState({name:'吴邪',age:18})
const [counter, setCounter] = useState(1);
const addHandler = () => {
setCounter(counter + 1); // 将counter值修改为2
setCounter(2);
setCounter(3);
setCounter(4)
// setState()中回调函数的返回值会成为新的state的值 回调函数执行时 React会将最新的值作为参数传递
};
const lessHandler = () => {
setCounter(counter-1);
};
const updateUser=()=>{
// setUser({name:'张起灵',age:20});
// user.name='张起灵';
// setUser(user)
// 如果直接修改就的state对象 由于对象还是那个对象 使用不会发生改变
// 因此要进行浅复制
const newUser=Object.assign({},user);
// console.log(newUser);
// console.log(newUser===user)//判断是不是同一个对象
newUser.name='张起灵'
setUser(newUser)
}
return
{counter}--{user.name}--{user.age}
{/**/}
;
};
// 导出App
export default App;
import './App.css';
import {useRef, useState} from "react";
let temp;
const App = () => {
/*
* 获取原生的DOM对象
* 1.可以使用传统的document来对DOM进行操作
* 2.直接从React处获取DOM对象
* 步骤:
* 1.创建一个存储DOM对象的容器
* - 使用 useRef() 钩子函数
* 钩子函数的注意事项:
* ① React中的钩子函数只能用于函数组件或自定义钩子
* ② 钩子函数只能直接在函数组件中调用
* 2.将容器设置为想要获取DOM对象元素的ref属性
* ....
* - React会自动将当前元素的DOM对象,设置为容器current属性
*
* useRef()
* - 返回的就是一个普通的JS对象
* - {current:undefined}
* - 所以我们直接创建一个js对象,也可以代替useRef()
* - 区别:
* 我们创建的对象,组件每次重新渲染都会创建一个新对象
* useRef()创建的对象,可以确保每次渲染获取到的都是同一个对象
*
* - 当你需要一个对象不会因为组件的重新渲染而改变时,就可以使用useRef()
*
* */
const h1Ref = useRef(); // 创建一个容器
const [count, setCount] = useState(1);
// const h1Ref = {current:null};
// console.log(temp === h1Ref);
// temp = h1Ref;
const clickHandler = () => {
// 通过id获取h1
const header = document.getElementById('header');
// alert(header);
// header.innerHTML = '哈哈';
console.log(h1Ref);
// alert(h1Ref.current === header);
h1Ref.current.innerText = '嘻嘻!';
};
const countAddHandler = ()=>{
setCount(prevState => prevState + 1);
};
return
我是标题{count}
;
};
// 导出App
export default App;
App.js代码:
import React from "react";
/*
* Webstrom中的快捷方式:
* rsc --> 函数组件(不带props)
* rsi --> 函数组件(带props)
* rcc --> 类组件
* */
import React, {Component} from 'react';
import './App.css';
import User from "./components/User";
class App extends Component {
render() {
return (
);
}
}
export default App;
User.js代码:
import React, {Component} from 'react';
class User extends Component {
/*
* 类组件的props是存储到类的实例对象中,
* 可以直接通过实例对象访问
* this.props
* 类组件中state统一存储到了实例对象的state属性中
* 可以通过 this.state来访问
* 通过this.setState()对其进行修改
* 当我们通过this.setState()修改state时,
* React只会修改设置了的属性
*
* 函数组件中,响应函数直接以函数的形式定义在组件中,
* 但是在类组件中,响应函数是以类的方法来定义,之前的属性都会保留
* 但是这你仅限于直接存储于state中的属性
*
* 获取DOM对象
* 1.创建一个属性,用来存储DOM对象
* divRef = React.createRef();
* 2.将这个属性设置为指定元素的ref值
* */
// 创建属性存储DOM对象
divRef = React.createRef();
// 向state中添加属性
state = {
count: 0,
test: '哈哈',
obj: {name: '孙悟空', age: 18}
};
// 为了省事,在类组件中响应函数都应该以箭头函数的形式定义
clickHandler = () => {
// this.setState({count: 10});
// this.setState(prevState => {
// return {
// count: prevState + 1
// }
// });
/*this.setState({
obj:{...this.state.obj, name:'沙和尚'}
});*/
console.log(this.divRef);
};
render() {
// console.log(this.props);
// console.log(this.divRef);
return (
{this.state.count} --- {this.state.test}
{this.state.obj.name} --- {this.state.obj.age}
- 姓名:{this.props.name}
- 年龄:{this.props.age}
- 性别:{this.props.gender}
);
}
}
export default User;
import React, {useState} from 'react';
import Card from "../UI/Card/Card";
import './LogsForm.css';
const LogsForm = () => {
/*
* 当表单项发生变化时,获取用户输入的内容
* */
// 创建三个变量,用来存储表单中的数据
// let inputDate = '';
// let inputDesc = '';
// let inputTime = 0;
const [inputDate, setInputDate] = useState('');
const [inputDesc, setInputDesc] = useState('');
const [inputTime, setInputTime] = useState('');
// 创建一个响应函数,监听日期的变化
const dateChangeHandler = (e) => {
// 获取到当前触发事件的对象
// 事件对象中保存了当前事件触发时的所有信息
// event.target 执行的是触发事件的对象(DOM对象)
//console.log(e.target.value);
setInputDate(e.target.value);
};
// 监听内容的变化
const descChangeHandler = (e) => {
// 获取到当前触发事件的对象
// 事件对象中保存了当前事件触发时的所有信息
// event.target 执行的是触发事件的对象(DOM对象)
//console.log(e.target.value);
setInputDesc(e.target.value);
};
//监听时长的变化
const timeChangeHandler = (e) => {
// 获取到当前触发事件的对象
// 事件对象中保存了当前事件触发时的所有信息
// event.target 执行的是触发事件的对象(DOM对象)
//console.log(e.target.value);
setInputTime(e.target.value);
};
// 当表单提交时,汇总表单中的数据
/*
* 在React中,通常表单不需要自行提交
* 而是要通过React提交
* */
const formSubmitHandler = (e) => {
// 取消表单的默认行为
e.preventDefault();
// 获取表单项中的数据日期、内容、时长
// 将数据拼装为一个对象
const newLog = {
date: new Date(inputDate),
desc: inputDesc,
time: +inputTime
};
// 清空表单项
setInputDate('');
setInputDesc('');
setInputTime('');
console.log(newLog);
/*
* 提交表单后如何清空表单中的旧数据
* 现在这种表单,在React我们称为非受控组件
*
* 我们可以将表单中的数据存储到state中,
* 然后将state设置为表单项value值,
* 这样当表单项发生变化,state会随之变化,
* 反之,state发生变化,表单项也会跟着改变,这种操作我们就称为双向绑定
* 这样一来,表单就成为了一个受控组件
*
*
*
* */
};
return (
);
};
export default LogsForm;
import React, {useState} from 'react';
import Card from "../UI/Card/Card";
import './LogsForm.css';
const LogsForm = () => {
//将表单数据统一到一个state中
const [formData,setFormData]=useState({
inputDate:'',
inputDesc:'',
inputTime:''
})
// 创建一个响应函数,监听日期的变化
const dateChangeHandler = (e) => {
setFormData({
...formData,
inputDate:e.target.value
})
};
// 监听内容的变化
const descChangeHandler = (e) => {
setFormData({
...formData,
inputDesc:e.target.value
})
};
//监听时长的变化
const timeChangeHandler = (e) => {
setFormData({
...formData,
inputTime:e.target.value
})
};
// 当表单提交时,汇总表单中的数据
/*
* 在React中,通常表单不需要自行提交
* 而是要通过React提交
* */
const formSubmitHandler = (e) => {
// 取消表单的默认行为
e.preventDefault();
// 获取表单项中的数据日期、内容、时长
// 将数据拼装为一个对象
const newLog = {
date: new Date(formData.inputDate),
desc: formData.inputDesc,
time: +formData.inputTime
};
// 清空表单项
setFormData({
inputDate:'',
inputDesc:'',
inputTime:''
})
console.log(newLog);
};
return (
);
};
export default LogsForm;
import Logs from "./Components/Logs/Logs";
import LogsForm from "./Components/LogsForm/LogsForm";
import './App.css';
import {useState} from "react";
const App = () => {
//数据:
const [logsData,setLogsData]=useState(
[
{
id: '001',
date: new Date(2021, 1, 20, 18, 30),
desc: '学习九阳神功',
time: 30
},
{
id: '002',
date: new Date(2022, 2, 10, 12, 30),
desc: '学习降龙十八掌',
time: 20
},
{
id: '003',
date: new Date(2022, 2, 11, 11, 30),
desc: '学习JavaScript',
time: 40
},
{
id: '004',
date: new Date(2022, 2, 15, 10, 30),
desc: '学习React',
time: 80
}
]
)
/*下一步:将logsForm中的数据传递给App组件 然后将App组件 将新的日志添加到数组中
*
*
*
* */
//定义一个函数saveLogHandler
const saveLogHandler=(newLog)=>{
// 向新的日志里面添加id
newLog.id=Date.now()+'';
console.log("App.js",newLog);
//将新的数据他就爱到数组中
// logsData.push(newLog);
setLogsData([...logsData,newLog])
};
return
{/*引入LogsFrom*/}
;
};
// 导出App
export default App;
/* 日志的容器 */
import LogItem from "./LogItem/LogItem";
import Card from "../UI/Card/Card";
import './Logs.css';
const Logs = (props) => {
/*logData是一个用来存储学习的日志
* 这个数据除了当前组件Logs需要使用外 LogsForm也需要使用
* 当遇到这种一个数据需要被多个组件使用时 我们可以将数据放入这些组件共同祖先元素中
* 这样子就可以使得多个组件都能方便的访问这个数据
* state提升
* */
// 模拟一组从服务器中加载的数据
// 将数据放入JSX中
const logItemDate = props.logsData.map(item => );
return
{
logItemDate
// logsData.map(item => )
}
};
export default Logs;
import React, {useState} from 'react';
import Card from "../UI/Card/Card";
import './LogsForm.css';
const LogsForm = (props) => {
//将表单数据统一到一个state中
console.log(props)
const [formData,setFormData]=useState({
inputDate:'',
inputDesc:'',
inputTime:''
})
// 创建一个响应函数,监听日期的变化
const dateChangeHandler = (e) => {
setFormData({
...formData,
inputDate:e.target.value
})
};
// 监听内容的变化
const descChangeHandler = (e) => {
setFormData({
...formData,
inputDesc:e.target.value
})
};
//监听时长的变化
const timeChangeHandler = (e) => {
setFormData({
...formData,
inputTime:e.target.value
})
};
// 当表单提交时,汇总表单中的数据
/*
* 在React中,通常表单不需要自行提交
* 而是要通过React提交
* */
const formSubmitHandler = (e) => {
// 取消表单的默认行为
e.preventDefault();
// 获取表单项中的数据日期、内容、时长
// 将数据拼装为一个对象
const newLog = {
date: new Date(formData.inputDate),
desc: formData.inputDesc,
time: +formData.inputTime
};
//当要添加新的日志时 调用父组件传递过来的函数
props.onSaveLogs(newLog)
// 清空表单项
setFormData({
inputDate:'',
inputDesc:'',
inputTime:''
})
console.log(newLog);
};
return (
);
};
export default LogsForm;
import React from 'react';
import MyDate from "./MyDate/MyDate";
import './LogItem.css'
import Card from "../../UI/Card/Card";
const LogItem = (props) => {
/*
* props是只读的不能修改
* */
// props.desc = '嘻嘻'; // 不能修改props中的属性
// console.log(props.desc);
//书写一个删除事件
const deleteItemHandler=()=>{
const isDel=window.confirm('确定要删除吗?')
if (isDel){
alert('删除!')
props.onDelLog();
}else {
}
// 删除当前的item 要删除item 其实就是要从数据的state移除指定的数据
}
return (
{/* 日志内容的容器 */}
{/*
如果将组件中的数据全部写死,将会导致组件无法动态设置,不具有使用价值
我们希望组件数据可以由外部设置,在组件间,父组件可以通过props(属性)向子组件传递数据
*/}
{props.desc}
{props.time}分钟
{/* 添加一个删除的按钮*/}
删除
);
};
export default LogItem;
/* 日志的容器 */
import LogItem from "./LogItem/LogItem";
import Card from "../UI/Card/Card";
import './Logs.css';
const Logs = (props) => {
/*logData是一个用来存储学习的日志
* 这个数据除了当前组件Logs需要使用外 LogsForm也需要使用
* 当遇到这种一个数据需要被多个组件使用时 我们可以将数据放入这些组件共同祖先元素中
* 这样子就可以使得多个组件都能方便的访问这个数据
* state提升
* */
// 模拟一组从服务器中加载的数据
// 将数据放入JSX中
const logItemDate = props.logsData.map((item ,index)=> props.onDelLog(index)}
key={item.id} date={item.date}
desc={item.desc}
time={item.time}/>);
return
{
logItemDate
// logsData.map(item => )
}
};
export default Logs;
import Logs from "./Components/Logs/Logs";
import LogsForm from "./Components/LogsForm/LogsForm";
import './App.css';
import {useState} from "react";
const App = () => {
//数据:
const [logsData,setLogsData]=useState(
[
{
id: '001',
date: new Date(2021, 1, 20, 18, 30),
desc: '学习九阳神功',
time: 30
},
{
id: '002',
date: new Date(2022, 2, 10, 12, 30),
desc: '学习降龙十八掌',
time: 20
},
{
id: '003',
date: new Date(2022, 2, 11, 11, 30),
desc: '学习JavaScript',
time: 40
},
{
id: '004',
date: new Date(2022, 2, 15, 10, 30),
desc: '学习React',
time: 80
}
]
)
// 定义一个函数 从数据中删除一条日志
const dellogByIndex=(index)=>{
// setLogsData(prevState=>[...prevState.slice(index,1)])
setLogsData(prevState=>{
const newLogs=[...prevState]
newLogs.splice(index,1)
return newLogs;
});
};
/*下一步:将logsForm中的数据传递给App组件 然后将App组件 将新的日志添加到数组中
*
*
*
* */
//定义一个函数saveLogHandler
const saveLogHandler=(newLog)=>{
// 向新的日志里面添加id
newLog.id=Date.now()+'';
console.log("App.js",newLog);
//将新的数据他就爱到数组中
// logsData.push(newLog);
setLogsData([...logsData,newLog])
};
return
{/*引入LogsFrom*/}
;
};
// 导出App
export default App;
/* 日志的容器 */
import LogItem from "./LogItem/LogItem";
import Card from "../UI/Card/Card";
import './Logs.css';
const Logs = (props) => {
/*logData是一个用来存储学习的日志
* 这个数据除了当前组件Logs需要使用外 LogsForm也需要使用
* 当遇到这种一个数据需要被多个组件使用时 我们可以将数据放入这些组件共同祖先元素中
* 这样子就可以使得多个组件都能方便的访问这个数据
* state提升
* */
// 模拟一组从服务器中加载的数据
// 将数据放入JSX中
const logItemDate = props.logsData.map((item ,index)=> props.onDelLog(index)}
key={item.id} date={item.date}
desc={item.desc}
time={item.time}/>);
console.log(logItemDate);
return
{
logItemDate.length!==0 ? logItemDate:没有数据了!
// logItemDate
// logsData.map(item => )
}
};
export default Logs;
import React, {useState} from 'react';
import MyDate from "./MyDate/MyDate";
import './LogItem.css'
import Card from "../../UI/Card/Card";
import ConfirmModal from "../../UI/ConfirmModal/ConfirmModal";
const LogItem = (props) => {
// 添加一个state,记录是否显示确认窗口
const [showConfirm, setShowConfirm] = useState(false);
// 删除item的响应函数
const deleteItemHandler = () => {
// 显示确认窗口
setShowConfirm(true);
};
//取消函数
const cancelHandler = () => {
setShowConfirm(false);
};
// 确认函数
const okHandler = () => {
props.onDelLog();
};
/*
* portal
* - 组件默认会作为父组件的后代渲染到页面中
* 但是有些情况下,这种方式会带来一些问题
* - 通过portal可以将组件渲染到页面中的指定位置
* - 使用方法:
* 1.在index.html添加一个新的元素
* 2.修改组件的渲染方式
* - 通过ReactDOM.createPortal()作为返回值创建元素
* - 参数:
* 1. jsx(修改前return后的代码)
* 2. 目标位置(DOM元素)
*
* */
return (
{showConfirm && }
{/* 日志内容的容器 */}
{/*
如果将组件中的数据全部写死,将会导致组件无法动态设置,不具有使用价值
我们希望组件数据可以由外部设置,在组件间,父组件可以通过props(属性)向子组件传递数据
*/}
{props.desc}
{props.time}分钟
{/* 添加一个删除按钮*/}
×
);
};
export default LogItem;
import React from 'react';
import './Backdrop.css';
import ReactDOM from "react-dom";
// 获取backdrop的根元素
const backdropRoot = document.getElementById('backdrop-root');
const Backdrop = (props) => {
return ReactDOM.createPortal(
{props.children}
, backdropRoot);
};
export default Backdrop;
学习日志
/* 日志的容器 */
import LogItem from "./LogItem/LogItem";
import Card from "../UI/Card/Card";
import './Logs.css';
import LogFilter from "./LogFilter/LogFilter";
import {useState} from "react";
const Logs = (props) => {
// 创建一个存储年份的state
const [year, setYear] = useState(2022);
// 过滤数据,只显示某一年的数据
let filterData = props.logsData.filter(item => item.date.getFullYear() === year);
// 创建一个修改年份的函数
const changeYearHandler = (year) => {
setYear(year);
};
// 将数据放入JSX中
let logItemData = filterData.map(
(item, index) => props.onDelLog(item.id)}
key={item.id}
date={item.date}
desc={item.desc}
time={item.time}/>
);
if (logItemData.length === 0) {
logItemData = 没要找到日志!
;
}
return
{/*引入年份的选择组件*/}
{logItemData}
};
export default Logs;
终端输入:npx create-react-app react-app(项目名称)
完成之后自动创建 我们就不需要手动创建那些文件
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// 这个标签与之前的不一样 这个是严格模式
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
import logo from './logo.svg';
import './App.css';
function App() {
return (
计算机科学与技术学院
Edit src/App.js
and save to reload.
Learn React
);
}
export default App;
import logo from './logo.svg';
import './App.css';
function App() {
// 方式一: 在这里书写一个CSS样式
const pStyle={
color:'red',
backgroundColor:'#bfa',
border:"blue solid 1px"
}
return (
计算机科学与技术学院
Edit src/App.js
and save to reload.
Learn React
);
}
export default App;
/*方式二:采用外部样式 这种方式只需要在使用的时引入就可以
这种全局样式:会导致全局覆盖 样式冲突 它不像函数那种有作用域 因此这种不适应大范围使用
*/
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
创建一个App.module.css样式模块文件
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
);
import React, {useState} from 'react';
import classes from './App.module.css';
import A from "./A";
const App = () => {
/*
* CSS模块
* 使用步骤:
* 1.创建一个xxx.module.css
* 2.在组件中引入css
* import classes from './App.module.css';
* 3.通过classes来设置类
* className={classes.p1}
* CSS模块可以动态的设置唯一的class值
* App_p1__9v2n6
* */
const [showBorder, setShowBorder] = useState(false);
const clickHandler = () => {
setShowBorder(true);
};
return (
);
};
export default App;