尚硅谷React学习笔记

本文档为视频学习笔记、需结合哔哩哔哩尚硅谷react教程视频阅读使用

react简介

react是干什么的

react是用于构建界面的js库——只关注视图

以往展示信息的步骤

  1. 发送请求获取数据

  2. 处理数据

  3. 操作dom进行渲染

react只关注第三步。前两部还需要之前的知识去做,react只帮忙操作dom。

——react是一个将数据渲染为html视图开源js库

react的好处

原生js的痛点

  1. 原生js操作domfan所、效率低(通过dom-api操作ui)

  2. 使用js直接操作dom,浏览器会进行大量的重绘重排

  3. 原生js没有组件化的编码方案,代码复用率低

react的特点

  1. 采用组件化模式、声明式编码,提高开发效率以及组件复用率。

    以前用的是命令式编程,也就是每一步都要自己做(获取dom——改变颜色),但是声明式编码只需要说明这个dom应该是什么颜色。

  2. react native中可以使用react语法进行移动端开发

  3. 使用虚拟DOM+优秀的Diffing算法,尽量减少与真实DOM的交互。

    虚拟dom存放在内存中。

    react使得数据变化时,浏览器只需要更新变化的部分,不需要整个重绘

    diffing算法是用来进行虚拟DOM比较的

学习react之前要掌握的js基础知识

1.判断this指向

2.Class类

3.Es6语法规范

4.Npm包管理器

5.原型、原型链

6.数组常用方法

7.模块化

hello_react案例

react中js文件作用

  1. babel.js用于es6转es5,在react时用于jsx转js

  2. react.development.js是react核心库

  3. react-dom.development.js是react的扩展库。用于操作dom

通过脚手架搭建一个react项目

通过引入js文件搭建一个新的react项目

  1. 新建一个文件夹hello_react。用vscode打开

  2. 在hello_react新建一个js文件夹,将babel.js、react.development.js、react-dom.development.js拖拽到这个js文件夹下面。

注意点

1.

先引入react,再引入react-dom

3. //1.创建虚拟dom

const VDOM=

Hello,React

//不写引号,因为不是字符串

虚拟dom不写引号,相当于直接放进去

4. ReactDOM.render(VDOM,document.getElementById('test'))

Reder语法

虚拟DOM的两种创建方式

  1. 用jsx创建虚拟dom

    const VDOM=

    Hello,React

    //不写引号,因为不是字符串

  2. 原生js创建虚拟dom

  3. 原生的js不需要引入babel

所以script type也回归text/javascript

babel经过翻译之后,默认开启严格模式,严格模式下,Demo里面的this不指向window。是个undifined

执行ReactDOM.render( , …….)之后发生了什么

  1. React解析组件标签,找到Demo组件

② 发现组件是使用函数定义的,随后调用该函数,把返回的虚拟dom转换成真实DOM渲染到页面上

复习类的相关知识

1.基本创建

1.用class创建关键字

  1. 用构造函数实例化类

  2. 输出结果为:

image.png
前面的Person表示的是这个类由谁实例化出来的。

后面的{ }就是我们的p1,打印出的对象p1

2.构造器方法constructor()。该函数中的this指向实例对象

输出结果:

image.png

3.类的一般方法(除了构造器方法以外的方法)

  1. 类里面的一般方法的前面不写function关键字

    1. 方法中的this指向的是对象

      1. 类的一般方法,放在原型对象上。供实例使用

      2. 通过person实例调用speak时,speak中的this指向就是person的实例对象

注意这里的名字输出出来是ppp不是make

4.原型链

当调用了属性不存在的属性或者方法,会沿着原型链去找,看他的原型链上有没有谁有这个属性或者方法。

比如这里,p1和p2的speak都是原型上的方法。

所以在proto里面去找

image.png

类的继承

  1. 什么时候不用写构造器?

    当构造方法与父类一致的时候

  2. 什么时候要写构造器

    与父类不一致,或者有新的东西要添加的时候

  3. 必须调用super

    定义一个类child继承parent的时候,并且要在child里面写构造函数的时候,必须调用super

    例如:

class Person{

//构造器方法

constructor(name,age){

this.name=name;

this.age=age;

}

//一般方法

speak(){

console.log(我的名字是${name},我的年龄是${this.age})

}

};

//创建一个Student类集成Person

class Student extends Person{

constructor(name,age,grade){

this.name=name

this.age=age

this.grade=grade

}

}

会报错说你没使用super。、

image.png

正确写法:

class Student extends Person{

constructor(name,age,grade){

super(name,age)

this.grade=grade

}

}

也就是说supre相当于调用父类的构造函数。

注意:super要放在最前面

  1. 原型链的查找

    在上面的例子中,实例化一个sd并调用sd.speak()方法,会发现调用成功。

const sd=new Student("张三","15","高一");

sd.speak();

image.png
image.png

其查找逻辑为:

首先sd这个对象它自己没有speak方法,所以要找它的原型也就是Student类。Student类也没有speak方法,所以只能继续沿着原型链向上找,直到找到Person

  1. 子类重写从父类继承的方法

//创建一个Student类集成Person

class Student extends Person{

constructor(name,age,grade){

super(name,age)

this.grade=grade

}

speak(){

console.log(我的名字是${this.name},我的年龄是${this.age},我正在读${this.grade})

}

}

const sd=new Student("张三","15","高一");

sd.speak();

这里会直接调用Student里面的speak()函数

总结

  1. 类中的构造器不是必须写的。要对实例进行一些初始化的操作,如添加指定属性时才写。

  2. 如果Child类继承了Parent类。而且Child类中写了构造器,那么Child类构造器中必须要调用super

  3. 类中所定义的方法,都是放在类的原型对象上。供实例使用。

11类式组件(适用于复杂组件的定义)

创建类式组件

函数式组件中函数名就是组件名

类式组件中类名就是组件

1.必须继承React.Component

2.内部必须有render()

//创建类式组件

class MyComponent extends React.Component{

render(){

return

我是类定义的组件

}

}

//渲染类式组件

ReactDOM.render(,document.getElementById("content"))

3. 执行ReactDOM.render( , …….)之后发生了什么

①React解析组件标签,找到MyComponent组件

②发现组件是类定义的,随后new出该类的实例对象,并通过该实例调用原型上的render()方法。

③将render()返回的虚拟DOM转化成真实DOM渲染到页面上。

④render中的this指向的是React帮忙创建的这个实例对象——MyComponent组件实例对象

12.对state的理解——组件实例的三大核心属性之一

什么是简单组件。什么是复杂组件:

有state(状态)的是复杂组件,没有state的是简单组件。

组件的状态state驱动什么:

组件的状态里面存着数据,数据的变化驱动着页面展示的改变。

State在组件的实例上

所以只有class可以有。函数式组件都没有实例。另外两大核心属性也是一样

13.初始化state

想对类的实例对象进行衣蛾写初始化的操作,比如增加一个属性或者修改一个属性的值,就需要借助类里面的构造器了。

14.react中的事件绑定

1.原生事件绑定

1.addEventListener

  1. onclick

  2. 内嵌事件函数

2.react中的事件绑定

建议使用内嵌事件函数

①首先onclick要写成onClick

②首先不能用引号

render(){

const {isHot}=this.state;

return

今天天气很{isHot?"炎热":"凉爽"}

}

这是错的

然后不能加小括号,因为时把btn()返回值给onclick了,为undefined

render(){

const {isHot}=this.state;

return

今天天气很{isHot?"炎热":"凉爽"}

}

这也是错的

以下这样才正确:

render(){

const {isHot}=this.state;

return

今天天气很{isHot?"炎热":"凉爽"}

}

15.类中的方法中的this

class MyComponent extends React.Component{

constructor(props){

super(props)

this.state={

isHot:false

}

}

render(){

const {isHot}=this.state;

return

今天天气很{isHot?"炎热":"凉爽"}

}

btn(){

console.log(this)

}

}

打印:undefined

①btn()定义在类中,也即是放在MyComponent的原型对象上。供实例使用

②由于btn时作为onClick的回调,也就是说只是见到那的赋值给了onClick。所以这时再使用onclick已经不是通过实例对象调用,而是直接对存放在堆里面的方法btn进行调用。所以this应该指向window

③但是,但是,由于类里面的方法默认开启严格模式,严格模式的代码块中,this禁止指向window。所以this为undefined

16.解决类中的this的指向问题、

Render()中的this指向是组件的实例对象。

在构造函数中:

constructor(props){

super(props)

this.state={isHot:false}

this.btn=this.btn.bind(this)

}

①先看右边。构造器中的this指向的是实例对象,找实例对象的btn()方法;

②但是函数挂载在原型对象上,所以实例对象中此时此刻还没btn()函数,顺着原型链找到原型对象的btn()函数。通过bind函数传递进去this。

③这个this指向谁呢?还是那句话,构造器中的this指向的是实例对象。所以这个bind会返回一个和btn()函数一样的函数,区别只在于函数内部的this指向了实例对象

④看左边,赋值给了挂载在实例对象上的btn()函数。如此一来,每次通过实例对象调用的函数btn()是直接调用的函数左边的这个。找到了,自然也不会去原型链里面找了。

本文档为视频学习笔记、需结合哔哩哔哩尚硅谷react教程视频阅读使用

17.setState的使用

状态state不能直接更改,而是要使用一个api明教setState进行更改,React才会认可,才会帮我们刷新页面

18.简写方法

1.构造方法的简写

类里面可以直接写赋值语句,例如:

class MyComponent extends React.Component{

a=1

}

前面不用写let之类的,直接写赋值语句

含义为:在该类的实例对象上追加一个属性,属性名为a,值为1

注意:是实例对象,而不是原型对象,这个变量实际挂载在实例对象身上,原型对象身上没有

但是传递进来的数据需要构造器来接

类里面可以写的东西有:构造器、render()、一般方法、赋值语句

2.bind函数的省略

//创建类式组件

class MyComponent extends React.Component{

constructor(props){

super(props)

this.state={isHot:false}

}

render(){

const {isHot}=this.state;

return

今天天气很{isHot?"炎热":"凉爽"}

}

btn=()=>{

const isHot=this.state.isHot;

this.setState({isHot:!isHot});

}

}

//渲染类式组件

ReactDOM.render(,document.getElementById("content"))

注意这一部分:

btn=()=>{

const isHot=this.state.isHot;

this.setState({isHot:!isHot});

}

①首先这个btn不再是一个声明函数,而是一个赋值语句。根据上面一小节我们知道,类里面的赋值语句的含义是,给实例对象追加一个属性btn,它的内容是一个函数

②也就是说这个btn是挂载在实例对象身上的

③btn是一个箭头函数,箭头函数内部没哟自己的this,从上下文捕获this。

④btn追加在实例对象上,所以这个this指向的是实例对象。

⑤所以之前的bind函数就可以省略掉了,btn()函数此时不会丢失this了。效果不变

3.总结:

类的经典格式:

class MyComponent extends React.Component{

state={isHot:false}

render(){

const {isHot}=this.state;

return

今天天气很{isHot?"炎热":"凉爽"}

}

btn=()=>{

const isHot=this.state.isHot;

this.setState({isHot:!isHot});

}

}

初始化状态state={}

不用放在构造器中,直接直接写state={isHot:false}作为代替

类中的一般属性都要写成

赋值语句+箭头函数的形式

19.state总结:

①state的值是对象,包含多个key:value

②组件被称为状态机,通过更新组件的state来更新与渲染对应组件

③组件中的render的方法中的this指向实例对象

组件中自定义的一般方法中的this为undefined

解决方法:

1.强制绑定bind

2.赋值语句+箭头函数

⑤状态数据必须用setState

20.props的基本使用

如何传递

ReactDOM.render(,document.getElementById("content"))

以这种形式书写,react会直接把name和123作为key:value对 传给组件的实例对象,(注意类比原生html的属性书写方法),存放在它的props里面。

在render中打印出this,如图可以看到props里面已经有了


image.png

如何拿到并使用

class Child extends React.Component{

render(){

console.log(this);

return(

  • 姓名{this.props.name}
  • 性别{this.props.sex}
  • 年龄{this.props.age}

)

}

}

ReactDOM.render(,document.getElementById("content"))

直接用this.props.name

简化一下:

render(){

console.log(this);

const {name,sex,age}=this.props

return(

  • 姓名{name}
  • 性别{sex}
  • 年龄{age}

)

}

21.批量传递props(批量传递标签属性)

不定参数的方法:

const p={name:'1773',sex:'***',age:'+++'}

ReactDOM.render(,document.getElementById("content"))

要求同名

展开运算符…的知识复习:

1.对数组使用——展开数组

将数组按展开

let arr1=[1,3,5,7,9]

console.log(...arr1)

console.log(arr1)

image.png

2.最数组使用——链接两个数组

let arr1=[1,3,5,7,9]

let arr2=[2,4,6,8,10]

let arr3=[...arr1,...arr2]

console.log(arr3)

相当于把arr1和arr2展开放在一起,然后赋值给arr3


image.png

3.函数传参——不定参数

4.不能展开对象——babel+react可以

原生情况下展开运算符不允许展开对象

React+babel中,可以展开对象———但是只能用于标签属性的传参

5.知识复习——如何复制一个对象

let person={name:'123',age:'456'}

let person2=person

这种形式只是一个引用的传递,而不是复制对象的本身。

当person内部的值变化的时候,通过person2获取到的值也变化了。

应该这样:

let person={name:'123',age:'456'}

let person2={...person}

如此一来,person2只是初始值和person一样。之后就各是各的了

注意一定外面要加{},因为原生状态下展开运算符不能展开对象,这里是在构建对象字面量

6.构建对象字面量的同时修改其属性值

let person={name:'123',age:'456'}

let person2={...person}

let person3={...person2,name:"老王",address:"隔壁"}

console.log(person2)

console.log(person3)

image.png

22.为React添加props的规则限制

使用propsTypes

class Child extends React.Component{

render(){

console.log(this);

const {name,sex,age}=this.props

return(

  • 姓名{name}
  • 性别{sex}
  • 年龄{age}

)

}

}

Child.propTypes={

name:PropTypes.string

}

const p={name:789798798,sex:'***',age:'+++'}

ReactDOM.render(,document.getElementById("content"))

①首先,porpTypes要写在类的外面,否则报错(这个在下一节会处理)

②严格按照这个格式来写:

Child.propTypes={

name:PropTypes.string

}

外面Child.propTypes的p小写,里面PropTypes.string的p大写,string这里的s也要小写。

③前面要引入prop-type.js

④react的版不能太旧。

isRequired

限制名字为String且为必填项:

Child.propTypes={

name:PropTypes.string.isRequired

}

defaultProps

限制性别为String型,且默认值为“不男不女”

没填性别的话,性别就默认为 不男不女

Child.propTypes={

sex:PropTypes.string

}

Child.defaultProps={

sex:"不男不女"

}

传一个函数:

Child.propTypes={

sex:PropTypes.string,

speak:PropTypes.func

}

注意这里要写func,不能写function

23.props简写

Props是只读的

不能修改

把propTypes放到class内部里面去

class Child extends React.Component{

static propTypes={

sex:PropTypes.string,

speak:PropTypes.func

}

static defaultProps={

sex:"不男不女"

}

render(){

console.log(this);

const {name,sex,age}=this.props

return(

  • 姓名{name}
  • 性别{sex}
  • 年龄{age}

)

}

}

注意要在前面加一个static

因为下面这种写法是给类的实例对象添加属性

class Child extends React.Component{

propTypes={

sex:PropTypes.string,

speak:PropTypes.func

}

defaultProps={

sex:"不男不女"

}

}

必须要加上static才能把属性直接加载原型对象上。

24.类组件中的构造器与props

①构造函数完全可以不写

②如果要写构造器函数,要接props,并且调用super(props)

形如:

constructor(props){

super(props)

}

否则构造器内部的this.props为undifined。无法通过this.的形式找到props

一般来说用不到。构造器能省就省略

25.函数式组件使用props

function Child(props){

const {name,sex,age}=props

return(

  • 姓名{name}
  • 性别{sex}
  • 年龄{age}

)

}

const p={name:"8",age:'+++',speak:p}

ReactDOM.render(,document.getElementById("content"))

传进来的值会默认被收集成一个对象,并将这个对象作为函数组件的参数传进去 func Child(props){

给函数式组件设置propType

Child.propTypes={

sex:PropTypes.string

}

Child.defaultProps={

sex:"不男不女"

}

直接写在函数的外面。

你可能感兴趣的:(尚硅谷React学习笔记)