第一章:JavaScript复习
1.变量
//1.三种声明方式中 定义优先使用的是const 如果希望有变量被改变则使用let 至于var最好不要在代码中出现
/*
*
* var:
* --没有快作用域
*
* let:
* --有快作用域
*
* const
* --和let类似 具有快级作用域 但是它只能赋值一次
* --使用场景 就是对一些常量可以使用这个关键字
* 对函数,对象使用这个声明 就可以保证函数(对象)不会被修改
* */
{
var a=20//这个时候会报错 a没有快作用域
}
var a=20
function fn(){
var b=90
}
{
// 使用let
let b=190
}
for (var i = 0; i < 10; i++) {
console.log("在循环内部可以访问",i)
}
console.log("在循环外面访问",i)
//const
const PI=3.14
console.log(PI*45.878)
const obj={
name:"孙悟空",
age:'12'
}
console.log(obj.name)
const fn1=function (x,y) {
return x+y
}
console.log(fn1(2,2));
console.log(typeof fn1())
2.解构赋值
//1.解构赋值
let a,b;
let arr=['吴邪','张启山','解雨臣','张起灵','越想越','赵子龙']
a=arr[0]
b=arr[1]
console.log(a,b);
//使用解构赋值
[a,b]=arr;
console.log(a,b)
const [x,y]=arr;//声明的同时在赋值
function fn(){
return ['吴邪','黑瞎子']
}
console.log(fn());
//剩余参数
const [l,k,...c]=arr;//这个三个点 就是表示把数组中的元素全部赋值过去
console.log(l,k,c)
//对象的解构
const obj={
name:'吴邪',
age:19,
gender:'男'
};
let u,i,o;
//传统赋值--
u=obj.name;
i=obj.age;
o=obj.name;
console.log(u,i,o);
//对象解构
({name:u,age:i,gender: o}=obj)//将name赋值给u 将age赋值给i
console.log(u,i,o);
//变量名和属性名一致
const {name,gender,age}=obj
console.log(name,age,gender);
//利用数组的解构交换变量的位置
let v=10;
let s=90;
[v,s]=[s,v];
console.log("交换后:",v,s)
3.展开
function f(a,b,c) {
return a+b+c;
}
const arr=[1,2,3];
//计算数组中三个数字的和
let result=f(arr[0],arr[1],arr[2]);
console.log(result)
//进阶:把数组展开
let result2=f(...arr);//这个就是一次性把数组里面的元素累加
console.log(result2);
/*
* ----因此可以通过三个点来展开数组 ,只要是数组
*
*
*
* */
const arr2=[...arr];//相当于将arr浅复制给arr2
console.log(arr2);
//因此:可以这样
const arr3=[12,3,4,5,6,...arr,23,45]
console.log("浅复制",arr3)
//对象也是如此:
const obj={name:'吴邪',
age:19,
gender:'男'
};
const obj2={...obj};//将obj在新的对象中展开 相当于浅复制
console.log(obj2)
const obj3={...obj,address:'吴山居'}
console.log(obj3)
3.箭头函数
/*
* 箭头函数:
* --只有一个参数的函数
* 语法: 参数=>返回值
* --如果没有参数或者多个参数 需要使用括号来括起来
* 语法:()=>返回值
* (a,b,c,.....)=>返回值
*
*
* 箭头函数后边的值就是函数的返回值:
* 返回值必须是一个表达式(有返回值的语句)
* 如果返回值是对象 则必须加括号 加以区分
*
* 如果需要在箭头函数中定义逻辑 则可以直接在箭头后跟一个代码块
* 代码块中的代码跟普通语句一样
*
* */
//--普通函数:
const fn=function (a){
return 'hello 计算机科学与技术'
};
// --箭头函数 只有一个参数的
const fn2=a=>'hello 计算机科学与技术学院';
console.log(fn(),fn2())
//有返回值:
const sum=(a,b)=>a+b;
let v=sum(123,456)
console.log(v)
const j=()=>console.log("计算机科学与技术")
console.log(j());
4.箭头函数的区别
function f() {
//arguments:用来保存函数的实参
console.log(arguments.length);
}
console.log(f(1,2,3))
const fn2=()=>{
//箭头函数中没有这个 因此这个会报错
console.log(arguments);
}
const fn3=(...a)=>{
console.log(a)
}
console.log(fn3())
//2.箭头函数中没有this 就是自己的this
const obj={
hello:fn=()=>{
console.log(this)
}
}
obj.hello();//很明显 箭头函数的this是外层作用域的this
const obj2={
hello:function () {
const test=()=>{
console.log(this)
};
test();
}
}
obj2.hello()
//3.箭头函数中的thus无法通过call() apply() bind()去修改
//4.箭头函数无法作为构造函数使用
5.模块化
const c=10;
const b=100;
/* 作为一个模块 我们不希望模块内所有的内容都暴露
* 作为导入方 也不希望导入无用的变量
*
* export(导出) 用来决定一个模块中那些内容可以被外部查看
* 导出分为两种:
* 1.默认导出
* ---export default xxx;
* 注意:一个模块中只能有一个默认导出
* 2.命名导出
*
* import(导入)
* --导入用来将外部模块中的内容导入到当前模块中
* --导入默认的模块:import a from './1.变量'
* 导入默认模块时 变量名可以自主命名 无需和模块中的变量名对应
* 在网页中导入模块时 模块的路径必须写完整(./或../开头 扩展名也得写上)
*
* 导入指定内容:
* import {变量b,变量c} from './m1.js' 必须保证m1.js里面有变量b和变量c
* */
//默认导出:
// export default c;//这个就是将变量a作为默认导出
//导入
import a from './1.变量.js'
//默认情况下:script不能使用import 如果想让其支持模块化 必须设置script的type属性为module
console.log(a)
//2.命名导出
export const k=200;//命名导出k
6.类
/*
*
* 类:类是对象的模板 类决定了一个对象中有哪些属性和方法
* --使用class关键字来定义一个类
* ---
*
*
*
* */
class Person{
// 类里面有属性
// 可以在类里面定义属性
name='吴邪';
age=10;
gender='男'
// 也可以在类里面定义方法
//定义了实例方法
run(){
console.log("跑起来!")
}
// 构造函数:
constructor(name,age) {
// 这个方法是固定的 当我们通过new创建对象时 实际上就是在调用类的构造函数
console.log("我执行了~~")
// 在构造函数中我们可以通过this来引用当前的对象
this.name=name;
this.age=age
}
}
const prson=new Person();
console.log(prson);
console.log(prson.age);
console.log(prson.run());
const p2=new Person('解雨臣',18)
console.log(p2);
7.类的this
class Myclass{
/*类中的所有代码都会在严格模式下执行
----其中:严格模式下的特点 函数的this不在是window
*
*
* 在类中方法的this表示固定的 以方法的形式调用时 this就是当前的实例
* 以函数形式调用时 this是undefined的
* 在开发时 在有些情况下 我们希望方法中的this就是固定的 不会因调用方法的不同而改变
* 如果有这种需求 我们可以使用箭头函数来定义类中的方法
* ---如果类中的方法是以箭头函数定义的 则方法中的this永远为当前实例 不会改变
*
*/
fn(){
console.log(this)
}
}
const a=new Myclass();
// console.log(a.fn());
const test=a.fn();
// console.log(test())
8.类的继承
class Dog{
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("你好")
}
}
//以上定义了两个类
// 将多个类中的重复代码提取出来 通过继承可以使得类中拥有其他类中的属性和方法
class y extends Dog{
// 当我们在子类中重写父类构造函数的时候 必须在子类构造函数中第一时间调用构造函数 负责会报错
constructor(name,age,legngth) {
super(name,age);//这个就是第一时间调用父类的构造函数 这个永远要在第一行
// 之后在单独赋值
this.length=legngth
}
// y继承了Dog类中的所有属性 使用extends来继承一个类 继承后就相当于将该类的代码复制到了当前类中
//当我们使用继承后: 被继承的类就是父类 继承父类的类称为子类
// 子类继承父类后 将继承父类中的属性和方法
// 也可以创建同名的属性或方法来对父类进行重写
sayHello=()=>{
//进行方法的重写
console.log("那好 我是继承的子类")
}
}
const c=new y('吴邪',19);
console.log(c.name)
console.log(c.sayHello());
9.静态属性和方法
/*
* --直接通过类调用的属性和方法被称为静态属性和静态方法
*
*
*
* */
class Myclass{
name='计算机科学与技术'
fn=()=>{
console.log("你好 计算机科学与技术学院")
}
}
//以上的方法和属性是实例方法和实例属性 必须通过new来实例化转之后才可以调用
const x=new Myclass();
console.log(x.fn())
/*因此使用静态属性和静态方法*/
class Myclass2{
// 在属性名和方法名前面添加一个关键字static就是静态方法和静态属性
static name='计算机科学与技术 静态属性'
static fn=()=>{
console.log("我是静态方法")
}
}
//使用static开头的属性是静态属性 使用static开头的方法是静态方法
//因此可以直接通过类名来调用 不需要实例化
Myclass2.fn()//这样子就不会报错了
//注意:静态方法this表示实例对象而是当前的类对象
10.数组方法复习
/*
* ----数组方法
*
*
* */
const arr=[1,2,3,4,5,6];
//1.map() 可以根据原有数组返回一个新数组 需要一个回调函数作为参数 回调函数中的返回值会成为新数组中的元素
// ---回调函数中有三个参数 参数一:当前元素 参数二:当前元素的索引 参数三:当前数组
let result=arr.map((item,index,array)=>item+1)
console.log(result);
const arr2=['吴邪','解雨臣','黑瞎子'];
let result2=arr2.map(item=>"<item>+item+</item>")
console.log(result2)
/* --2.filter() 可以从一个数组中获得符合条件的元素 也就是过滤
* --会根据回调函数的结果 是否保留元素 true保留 false不保留
* --会根据回调函数的结果来决定是否保留元素 TRUE保留 false不保留
*
*
* ---3.find()
* --可以从一个数组中获得符合条件的元素
*
* */
let result3=arr.filter(item=>item%2===0);
console.log(result3)
/*
* ---3.求和 reduce() 可以用来合并数组中元素 需要两个参数
* 回调函数 指定运算规则
* 四个参数:prev 上一次的运算结果
* curr 当前值
* index 当前索引
* arr当前数组
*
*
* 初始值:用来指定第一次运算时的prev 如果不指定则直接从第二个元素开始计算
* */
let result4=arr.reduce((prev,curr)=>{prev+curr},0);
console.log(result4)
第二章:React概述
1.React介绍
React是一个用于构建用户界面的JavaScript库 用来为现代的网络构建用户界面
React的特点:
--虚拟DOM
--声明式
--支持服务器端渲染
--快速 简单 易学
---基于组件
2.HelloWord
1.使用React开发web项目:
---1.引入React文件 下载完成后继续下一步
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HelloWord</title>
<script>
/* --1.React
*
*
* */
</script>
<div id="root"></div>
<!-- 1.引入React的核心库-->
<script src="3.React教程/React/react.development.js"></script>
<!-- 2.引入react的DOM库-->
<script src="3.React教程/React/react-dom.development.js"></script>
</head>
<body>
<script>
<!-- 通过React向页面中添加一个div-->
const div=React.createElement('div',{},'我是react的div');//创建一个React元素
/*
* React.createElement()来创建一个React元素
* ---参数
* 1.元素名(组件名)
* 2.元素中的属性
* 3.元素的子元素(内容)
* */
//获取根元素对应的React元素
const root= ReactDOM.createRoot(document.getElementById('root'));//用来创建根元素 需要一个DOM元素作为参数
//将div渲染到根元素中
root.render(div)
</script>
<!--<script>-->
<!--<!– 操作DOM–>-->
<!--// 通过DOM向网页中添加一个div-->
<!--const div=document.createElement('div')-->
<!--//向div中设置内容-->
<!--div.innerText='我是计算机科学与技术'-->
<!--//获取root-->
<!--const root=document.getElementById('root')-->
<!--//将div添加到页面中-->
<!--root.appendChild(div)-->
<!--</script>-->
</body>
</html>
3.三个API之一
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 1.引入react核心库-->
<script src="react.development.js"></script>
<!-- 2.引入react的dom库-->
<script src="react-dom.development.js"></script>
</head>
<body>
<!--3.创建一个根标签-->
<div id="root"></div>
<script>
<!-- 创建一个React元素-->
const button=React.createElement('button',{id:btn,onClick:()=>{
alert("你好 计算机科学与技术")
}},'确定');
//获取根元素
const root=ReactDOM.createRoot(document.getElementById('root'));
//将元素在根元素里面渲染
root.render(button)//这个读作把button放在root里面渲染
/*
* React.createElement('button',{},'确定')
* ---用来创建一个React元素
* 参数:
* 参数1.元素的名称(html标签必须小写)
* 参数2.标签中的属性 指定id 类型 类选择器
* ----在设置事件的时候 要采用驼峰命名法
* ---class属性需要使用className来设置
* 参数3:元素的内容(子元素)
* 注意点:React元素最终会通过虚拟don转换为真实的DOM元素
* React元素一旦创建就无法修改
* 只能使用新创建的元素去进行转换
*
*
*
* */
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 1.引入React核心库-->
<script src="react.development.js"></script>
<!-- 2.引入React的DOM库-->
<script src="react-dom.development.js"></script>
</head>
<body>
<div id="root"></div>
<script>
<!-- 1.创建React根元素 div-->
const div=React.createElement('div',{},'我是一个div',button)
//2.获取根元素 传递一个根元素 根元素就是React元素要插入的位置
const root=ReactDOM.createRoot(document.getElementById('root'))
//3.将元素放在根元素中显示 render()通过根元素去调用 用来将React元素渲染到根元素中 根元素中所有的内容都会被删除 被React元素替换
// ----当重复调用render()时 React会将两次渲染结果进行比较
// ----他会只修改那些发生变化的元素 对DOM做最少的修改
root.render(div)
</script>
</body>
</html>
4.jsx介绍
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSX</title>
<script src="react.development.js"></script>
<script src="react-dom.development.js"></script>
<!-- 引入babel 以创建jsx-->
<script src="babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<!-- 设置js代码能被babel识别-->
<script type="text/babel">
<!-- 创建一个React元素-->
//命令式编程:
// const button=React.createElement('button',{},'我是计算机科学与技术学院');
// 声明式编程:结果导向的编程 在React中可以通过jsx来创建React元素 jsx就是js的扩展 jsx需要翻译为js代码 才能React执行
//要在React中使用jsx中 必须在React中引入babel
const button= <button >我是按钮</button>
const root=ReactDOM.createRoot(document.getElementById('root'))
root.render(button)
//jsx就是React.createElement()的语法糖 jsx在执行之前都会被babel转换为js代码
</script>
</body>
</html>
5.jsx的注意事项
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSX的注意事项</title>
<script src="react.development.js"></script>
<script src="react-dom.development.js"></script>
<!-- 引入babel 以创建jsx-->
<script src="babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<!-- 设置js代码能被babel识别-->
<script type="text/babel">
/* 1.jsx的注意事项:
* ---1.jsx不是字符串 不要加引号
* ----2.jsx中标签的应该小写开头 React的组件用大写开头
* ---3.jsx中可以使用大括号{}来嵌入表达式 --有返回值的语句急速表达式
* ---4.jsx中只能有一个根标签
* ---5.jsx的标签必须正确结束 自结束标签也是这样
*
* 6.如果表达式是null 布尔值 undefined这些值 就不会显示
* 7.在jsx中 属性可以直接在标签中设置
* 注意:class需要使用className代替
* style中必须使用对象设置
* */
const name='吴邪';
const fn=()=>{
return "hello 计算机科学技术学院!"
}
//通过花括号啦表现出变量值
const div=<div
style={{backgroundColor:"yellowgreen"}}
>我是一个div <hr/> {name} <hr/> {9+1} <hr/>
{fn()}</div>;
const root=ReactDOM.createRoot(document.getElementById('root'))
root.render(div)
</script>
</body>
</html>
6.渲染列表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>渲染列表</title>
<script src="react.development.js"></script>
<script src="react-dom.development.js"></script>
<!-- 引入babel 以创建jsx-->
<script src="babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const name='吴邪'
/* {}只能用来放js表达式 而不能放语句 if for语句不能放入
* 在语句中是可以去操作jsx
* <ul>
*
* <li><>/li
* <li></li>
* ....
* </>ul>
*
*
* */
const arr=['吴邪','解雨臣','二月红','黎簇','王胖子','黑瞎子']
//将arr渲染为一个列表在网页中显示 jsx中自动将数组中的元素在页面中显示
const list=<div>
<li>{arr[0]}</li> <hr/>
<li>{arr[1]}</li> <hr/>
<li>{arr[2]}</li> <hr/>
</div>
const root=ReactDOM.createRoot(document.getElementById('root'))
root.render(list)
</script>
</body>
</html>
7.虚拟DOM
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>虚拟DOM</title>
<!-- 1.分别引入三个包-->
<script src="react.development.js"></script>
<script src="react-dom.development.js"></script>
<script src="babel.min.js"></script>
</head>
<body>
<div id="root"> </div>
<script type="text/babel">
<!-- 创建一个数据-->
const data=['吴邪','解雨臣','黑瞎子','王胖子']
//创建列表
const list=<ul>
{data.map(item=><li>{item}</li>)}
</ul>
// 获取根元素
const root=ReactDOM.createRoot(document.getElementById('root'));
//渲染元素
root.render(list)
/*
* 在React我们操作的元素被称为React元素 并不是真正的原生dom元素
* React通过虚拟DOM 将React元素和原生DOM进行映射 虽然操作的React元素 但是这些操作最终都会通过虚拟DOM
* 在真实DOM上显示出来
* 虚拟DOM的好处 --1.降低API复杂度
* ---2.解决兼容问题
* ---3.提高了性能 减少DOM不必要的操作
*
* 每当我们调用root.render()时 页面是会发生重新的渲染
* React会通过diff算法 将新的元素和旧的元素进行比较 并且只对发生变化的元素进行修改 没有发生变化的元素不予处理
*
* 在比较两次数据时 React会先比较父元素 父元素如果不同 追所有元素全部替换
* 父元素一致 在去逐个比较子元素 直到找到所有发生变化的元素为止
*
* 当我们在jsx中显示数组时 数组中的每一个元素都需要设置唯一的key 否则控制台会显示红色警告
* 重新渲染页面时 React会按照顺序依次比较对应的元素 当我们去渲染一个列表时 默认情况下 我们不去指定这个key
* 同样也会按照顺序进行比较
*
* 如果列表的顺序永远不会发生变化 这么做当然不会有问题 都是如果列表的顺序会发生变化 这个可能会导致性能问题
*
* 上例中:在列表的最后添加了一个新元素 并没有改变其他元素的顺序 所以这种操作不会带来性能问题
*
* 为了解决这个问题:React为列表设计了一个key属性
* key的作用相对于ID 只是无法在页面中查看 当设置key以后在比较元素 就会比较相同key的元素 而不是按照顺序进行比较
*
*
* 在渲染一个列表时 通常会给列表项设置唯一一个key 来避免上述问题 这个key在当前列表中唯一即可
*
* 注意:开发过程中 一般会采用数据的id作为key 尽量不要使用元素的索引作为key
* 索引会跟着元素的顺序的改变而改变 所以使用索引作为key根没有key是一样的
* 唯一不同就是警告没有了
*
* 当元素的顺序不会变 时 用索引作为key也没有声明问题
*
* */
</script>
</body>
</html>
第三章:React项目创建
1.手动创建React项目
创建项目:目录结构如下:
public
---index.html(添加标签 <div id="root"></div>)
--src
-App.js
-index.js
步骤:进入项目所在目录:
项目初始化 终端执行:npm init -y (yarn init -y)
安装项目依赖:npm add react react-dom react-scripts
或者 npm install react react-dom react-scripts
// src/index.js是js的入口文件
//1.引入ReactDOM
import ReactDOM from 'react-dom/client';
//2.创建一个jsx
const App=<div>
<h1>这个是react项目</h1>
<h2>计算机科学与技术学院</h2>
</div>;
// 3.获取根容器
const root=ReactDOM.createRoot(document.getElementById('root'));
//4.将App渲染到根容器
root.render(App)
//4.打包 终端输入:npx react-scripts build 或者 npx react-scripts start (推荐)
22.定义练习的结构