React 学习笔记总结(一)

1. React 简介


React用于构建用户界面的JavaScript库。

在这里插入图片描述

React由FaceBook开发的,并且已经开源。

在这里插入图片描述

react的原理:
在这里插入图片描述

在这里插入图片描述

2. React的核心工具库


babel的作用:

  • 将ES6语法转成ES5。
  • jsx格式转成js格式。

在这里插入图片描述

react.development.js 和 react-dom.development.js文件的作用:
在这里插入图片描述

3. 实现一个React的实例


1.引入react的三个核心文件

  • 注意:下面的顺序问题!

2.创建虚拟DOM,将虚拟DOM渲染到页面。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>hello_react</title>

</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="test"></div>

    <!-- fixme 引入是有顺序的! -->
    <!-- 1. 引入react核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>

    <!-- 2. 引入react-dom,用于支持react操作DOM -->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>

    <!-- 3. 引入babel,用于将jsx转为js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <!-- fixme 注意:这里的type不声明默认就是js类型,但是因为react写的是jsx,因此类型必须设置为babel。也就是这里面要写jsx的内容。 -->
    <script type="text/babel">

        // 1.创建虚拟dom
        const VDOM = <h1>Hello,React</h1>

        // 2.渲染虚拟dom到页面
        // ReactDOM是react-dom.development.js中的
        // ReactDOM.render有两个参数:虚拟DOM 和 容器
        ReactDOM.render(VDOM,document.getElementById('test'))

    </script>
</body>
</html>

在这里插入图片描述

重复指定容器的情况:
在这里插入图片描述

常见错误:
在这里插入图片描述
在这里插入图片描述

4. React 两种创建虚拟DOM的方式


document.createElement(tagName[, options]) 这是创建真实dom。

React.createElement(标签名,标签属性,标签内容) 这是创建虚拟dom。

第一种:js方式,通过React.createElement的方式创建虚拟dom。

在这里插入图片描述

第二种:jsx方式,通过babel将jsx转换成React.createElement的形式进而创建虚拟dom。

在这里插入图片描述

5. 虚拟DOM 与 真实DOM的对比


js判断一个数据的类型方式如下几种:

// js判断一个不认识的元素类型方式:
// 1.直接打印
console.log('虚拟dom',VDOM)
// 2.typeof来输出该元素类型
console.log(typeof VDOM)
// 3.使用instanceof来一个个进行判断
console.log(VDOM instanceof Object)

虚拟DOM:

  • 本质是个Object类型的对象。
  • 虚拟DOM比较轻,真实DOM比较重。原因:虚拟DOM是React内部再用,无需真实DOM上那么多的属性。
  • 虚拟DOM最终会被React转化为真实DOM,呈现在页面上。
    在这里插入图片描述
    在这里插入图片描述

6. jsx语法规则


1.定义虚拟DOM时,不要写引号。

const VDOM = (
    <h2 id="itholmes">
        <span>hello,react</span>
    </h2>
)
ReactDOM.render(VDOM,document.getElementById('test'))

2.标签中混入JS表达式时要用{}。

  • 注意是js表达式,不是js语句。

在这里插入图片描述

const myId = 'IthoLmes111'
const myData = 'Hello,React'
const VDOM = (
	// 这里将上面转换为了小写。
    <h2 id={
    
    myId.toLowerCase()}>
        <span>{
    
    myData.toLowerCase()}</span>
    </h2>
)

3.虚拟DOM没有class,样式的类名指定要用className来指定样式。

<style>
    .title{
    
    
        background-color: red;
    }
</style>

<!-- 准备好一个容器 -->
<div id="test"></div>

<script type="text/babel">
	const myId = 'Itholmes111'
	const myData = 'Hello,React'
	// 虚拟DOM没有class,通过className来指定样式。
	const VDOM = (
	    <h2 id={
    
    myId.toLowerCase()} className="title">
	        <span>{
    
    myData.toLowerCase()}</span>
	    </h2>
	)
</script>

在这里插入图片描述

4.内联样式,要用style={ {key:value}}的形式去写。

  • 解释一下虚拟DOM的{ {}}的用法,最外层{}是让里面的内容成为js格式,最里面的{}是一个对象。
  • 对于像font-size这样的可以通过驼峰的方式来写。
const VDOM = (
    <h2 id={
    
    myId.toLowerCase()} className="title">
        <span style={
    
    {
    
    color:'white',fontSize:'30px'}}>{
    
    myData.toLowerCase()}</span>
    </h2>
)

5.jsx的虚拟DOM只能有一个根标签。

在这里插入图片描述
6.所有的标签必须闭合!

  • <xxx><xxx/> 或者 <xxx/>

7.React的标签首字母。

  • 1). 若小写字母开头,则将改标签转html中同名元素,若html中无该标签对应的同名元素,则报错。
  • 2). 若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。
  • 所以说,小写字母开头的都去找html元素;大写字母开头的都是自己定义的组件。

7. jsx 实战练习


将一个data数组中的数据渲染到页面上面:

<!-- 准备好一个容器 -->
<div id="test"></div>

<!-- fixme 引入是有顺序的! -->
<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>

<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>

<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>

<script type="text/babel">

    // 将data数据渲染到页面
    const data = ['Angular','React','Vue']

    const VDOM = (
        <div>
            <h1>前端js框架列表</h1>
            <ul>
                {
    
     
                	// {} 只能写js表达式。
                    data.map((item,index)=>{
    
    
                        return <li key={
    
    index}>{
    
    item}</li>
                    })
                }
            </ul>
        </div>
    )

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

</script>

8. React开发者工具 安装


React调试工具:
在这里插入图片描述

在这里插入图片描述

9. React 函数式组件


我们写出的jsx文件,可以去babel官方转换成react:
在这里插入图片描述


函数式组件编程如下:

ReactDOM.render(<函数式组件名称/>…)的 执行过程:(重要!!)

  • 首先,React解析组件标签,找到MyComponent(函数式组件名称)组件。
  • 之后,发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。
    在这里插入图片描述

注意:

  • 自己定义的组件名首字母必须大写。
  • 渲染组件到页面,要用闭合标签的形式。
<!-- 准备好一个容器 -->
<div id="test"></div>

<!-- fixme 引入是有顺序的! -->
<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>

<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>

<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>

<script type="text/babel">
    // 1.创建函数式组件
    function Demo(){
    
    
        // 此处的this是undefined,因为babel编译后开启了es5的严格模式。
        console.log(this)
         return <h2>我是用函数定义的组件(适用于简单组件的定义)</h2>
    }
    // 2.渲染组件到页面
    // 注意jsx语法,自定义的组件首字母必须大写!!
    ReactDOM.render(<Demo/>,document.getElementById('test'))
</script>

在这里插入图片描述

10. js的类 相关知识


1.类的构造函数 和 普通方法

  • 构造器方法中的this指向的是 创建出来的实例对象,这一点要牢记!
<script type="text/javascript">
    // 创建一个person类
    class Person{
    
    
        //构造器方法
        constructor(name,age) {
    
    
            // 构造器中的this是谁? - 类的实例对象就是下面的p1和p2。
            this.name = name
            this.age = age
        }
        // 一般方法 speak方法放在了哪里?- 类的原型对象上,供实例使用。
        speak(){
    
    
            // 通过Person实例调用speak时,speak中的this就是Person的实例(p1,p2)。
            console.log(`我叫${
      
      this.name},我的年龄是${
      
      this.age}`)
        }
    }
    // 创建一个Person的实例对象
    const p1 = new Person('tom',18)
    const p2 = new Person('jerry',19);

    p1.speak()
    p2.speak()
</script>

2.类的继承

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>类的基本知识</title>
</head>
<body>
    <script type="text/javascript">
        // 创建一个person类
        class Person{
    
    
            //构造器方法
            constructor(name,age) {
    
    
                // 构造器中的this是谁? - 类的实例对象就是下面的p1和p2。
                this.name = name
                this.age = age
            }
            // 一般方法 speak方法放在了哪里?- 类的原型对象上,供实例使用。
            speak(){
    
    
                // 通过Person实例调用speak时,speak中的this就是Person的实例(p1,p2)。
                console.log(`我叫${
      
      this.name},我的年龄是${
      
      this.age}`)
            }
        }

        class Student extends Person{
    
    

            // Student默认是继承Person的构造函数
            // 如果,Student也可以自己实现构造函数,顺序最好与父类相同!
            constructor(name,age,grade) {
    
    
                // 必须实现super()方法 ,并且super()必须最开始调用!
                super(name,age);
                this.grade = grade
            }

            spark(){
    
    
                console.log(`我叫${
      
      this.name},我的年龄是${
      
      this.age},我的年级是${
      
      this.grade}`)
            }

        }

        const s1 = new Student('小张',18)
        console.log(s1)
    </script>
</body>
</html>

3.通过实体类原型可以看到当前实体类对应的一系列类的信息:(包括构造方法、普通方法等等)
在这里插入图片描述

4.原型链查找方法,是一层层找,找到了就调用。
在这里插入图片描述

5.在类中可以直接写赋值语句,相当于给Car添加了属性(例如:a = 1 ,名为a,值为1)
在这里插入图片描述


js的class类 和 对象的误区:
在这里插入图片描述

在这里插入图片描述


小总结:
在这里插入图片描述

11. React 类式组件


React的类式组件满足以下几个条件:

  • 类必须继承React.Component这个类!!
  • 类必须实现render函数!
  • render函数必须要有返回值!
<!-- 准备好一个容器 -->
<div id="test"></div>

<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>

<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>

<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>

<script type="text/babel">
    // 1.创建类式组件 必须继承React.Component这个类!!
    class MyComponent extends React.Component{
    
    
        // 2.必须实现render函数
        render(){
    
    
            // 3.render函数必须要有返回值!!
            return <h2>我是用类定义的组件(适用于[复杂组件]的定义)</h2>
        }
    }
    ReactDOM.render(<MyComponent/>,document.getElementById('test'))
</script>

类式组件编程如下:

ReactDOM.render(<类式组件名称/>…)的 执行过程:(重要!!)

  • 首先,React解析组件标签,找到了MyComponent(类式组件名称)组件。
  • 之后,发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
  • 最后,将render返回的虚拟DOM转为真实DOM,随后呈现到页面上面。

在这里插入图片描述

注意:类式组件其实是React内部创建了实例对象的,通过该实例对象调用render方法。


可以在render里面打印一下this查看一下实例对象:
在这里插入图片描述

12. 组件实例对象的三大核心属性 之 state 状态


在这区分一下,简单组件和复杂组件,无状态的组件是简单组件;有状态的就是复杂组件。

这里的状态其实就是实现React.Component类的实例对象上的state。注意:并不是React.Component类上面的,而是实例对象上的!


官方给出 简单组件 和 有状态组件 :
在这里插入图片描述
在这里插入图片描述


对state状态的简单操作:

<script type="text/babel">
   // 1.创建组件
   class Weather extends React.Component{
    
    
   		// 必须创建构造器以及参数prop
       constructor(prop) {
    
    
           super(prop);
           // 初始化状态
           this.state = {
    
    isHot:true}
       }
       render() {
    
    
           console.log(this)
           // 读取状态,通过解构方式来展示。
           const {
    
    isHot} = this.state
           return (
               <div>
                   <h1>
                       今天天气很{
    
    isHot ? '炎热' : '凉爽'}
                   </h1>
               </div>
           );
       }
   }
   // 2.渲染组件到页面
   ReactDOM.render(<Weather />,document.getElementById('test'))
</script>

13. React中的 事件绑定


注意以下几点:

1.onClick中间的字母C必须大写。
2.这里的方法demo不能添加括号,会将demo函数执行一边的返回值返回给onClick。
3.onClick要的是这个demo函数!!!

<script type="text/babel">
    // 1.创建组件
    class Weather extends React.Component{
    
    
        constructor(prop) {
    
    
            super(prop);
            this.state = {
    
    isHot:true}
        }
        render() {
    
    
            console.log(this)
            // 通过解构方式来展示。
            const {
    
    isHot} = this.state
            return (
                // 1.onClick中间的字母C必须大写。
                // 2.这里的方法demo不能添加括号,会将demo函数执行一边的返回值返回给onClick。
                // 3.onClick要的是这个demo函数!!!
                <h1 onClick={
    
    demo}>
                    今天天气很{
    
    isHot ? '炎热' : '凉爽'}
                </h1>
            );
        }
    }

    function demo(){
    
    
        console.log('标题被点击了。')
    }

    // 2.渲染组件到页面
    ReactDOM.render(<Weather />,document.getElementById('test'))
</script>

14. js和React类方法的 this指向问题(重点!!)


js的严格模式:

  • 严格模式声明在函数内部,那么只在函数内使用严格模式。换言之就是对应作用域内具有严格模式。
  • 一定要能清楚 直接调用和实例调用!在严格模式下,直接调用的this是undefined!
<script type="text/javascript">

    // 当前的 demo和demo2 是全局window的一个函数。
    function demo(){
    
    
        // 开启严格模式。只在函数内使用严格模式
        'use strict'
        console.log(this)
    }
    function demo2(){
    
    
        // 没有开启严格模式。
        console.log(this)
    }

    // 因为开启了局部严格模式,所以外界调用会显示undefined。
    demo()

    // 没有开启严格模式,就可以直接调用! 打印出来是全局window对象。
    demo2()

</script>

再者如下案例:

<script type="text/javascript">
    class Person{
    
    
        demo2(){
    
    
            console.log(this)
        }
    }

    let p = new Person()
    p.demo2() // 打印Person{}对象

    // 类中的方法默认是开启严格模式的!因此,这里的p2直接调用是不可以的!
    let p2 = p.demo2
    // p2调用的话是直接调用,并不是实例调用!
    p2() // 打印undefined
</script>

严格模式的限制:

  • 不允许使用未声明的变量。
  • 不允许删除变量或对象。
  • 不允许删除函数。
  • 不能使用八进制,不能使用转义字符。
  • 不能对只读属性赋值。
  • … 等等见https://www.runoob.com/js/js-strict.html

最重要重要的一点,严格模式的this指向:

function f(){
    
    
    return !this;
} 
// 返回false,因为"this"指向全局对象,"!this"就是false

function f(){
    
     
    "use strict";
    return !this;
} 
// 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。
function f(){
    
    
    "use strict";
    this.a = 1;
};
f();// 报错,this未定义

React的事件调用完全复刻了上面的操作,所以才会出现事件绑定后调用方法this为undefined的问题!

类中的方法默认是开启了严格模式的。
在这里插入图片描述

15. 解决类中this的指向问题


通过调用bind方法来解决方法this的指针问题。

constructor(prop) {
    
    
   super(prop);
    this.state = {
    
    isHot:true}
    // 这里相当于给当前实例对象添加了一个经过bind方法加工后的changeWeather方法
    this.changeWeather = this.changeWeather.bind(this)
}

在这里插入图片描述

注意下图,绑定前的方法是哪里的方法。
在这里插入图片描述


js的bind方法使用:

  • bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
<script type="text/javascript">
    function demo(){
    
    
        console.log(this)
    }
    // bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
    // bind的作用:就是将demo函数复刻成一个新函数,并且将this替换成了指定的内容。
    // x的this就变成了{a:1,b:2}。
    const x = demo.bind({
    
    a:1,b:2})
    console.log(x)
    x()
</script>

所以就通过了bind方法来解决这个react类的this指向问题:

<!-- 准备好一个容器 -->
<div id="test"></div>

<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>

<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>

<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>

<script type="text/babel">
    // 1.创建组件
    class Weather extends React.Component{
    
    
        constructor(prop) {
    
    
            super(prop);
            this.state = {
    
    isHot:true}
            // 这里相当于给当前实例对象添加了一个经过bind方法加工后的changeWeather方法
            this.changeWeather = this.changeWeather.bind(this)
        }
        render() {
    
    
            const {
    
    isHot} = this.state
            return (
                <h1 onClick={
    
    this.changeWeather}>
                    今天天气很{
    
    isHot ? '炎热' : '凉爽'}
                </h1>
            );
        }
        changeWeather(){
    
    
            console.log(this)
            this.state.isHot = !this.state.isHot
        }
    }

    // 2.渲染组件到页面
    ReactDOM.render(<Weather />,document.getElementById('test'))
</script>

15. setState的使用


注意:状态state不可以直接更改,要借助一个内置的API去更改。

在React.Component类原型上面有一个setState方法。

必须通过setState进行修改更新。此外,setState的参数会合并到state,并不会替换,就不会影响其他属性。

<!-- 准备好一个容器 -->
<div id="test"></div>

<!-- 1. 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>

<!-- 2. 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>

<!-- 3. 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>

<script type="text/babel">
    // 1.创建组件
    class Weather extends React.Component{
    
    
        constructor(prop) {
    
    
            super(prop);
            this.state = {
    
    isHot:true,wind:'微风'}
            // 这里相当于给当前实例对象添加了一个经过bind方法加工后的changeWeather方法
            this.changeWeather = this.changeWeather.bind(this)
        }
        render() {
    
    
            const {
    
    isHot,wind} = this.state
            return (
                <h1 onClick={
    
    this.changeWeather}>
                    今天天气很{
    
    isHot ? '炎热' : '凉爽'}{
    
    wind}
                </h1>
            );
        }
        changeWeather(){
    
    
            let {
    
    isHot} = this.state
            // 必须通过setState进行修改更新。此外,这里的参数会合并到state,并不会替换,就不会影响其他属性。
            this.setState({
    
    isHot:!isHot})
        }
    }

    // 2.渲染组件到页面
    ReactDOM.render(<Weather />,document.getElementById('test'))
</script>

16. React类式组件的 构造器 、render以及方法调用次数


在这里插入图片描述

总结起来:

  • constructor构造器:初始化数据状态,解决类方法this指向问题。
  • render方法:渲染页面。
  • 普通方法:提供事件方法等。

17. React的 state简写方式


因为类可以直接写赋值语句。所以我们就可以直接写成赋值语句来简写。

注意:函数赋值必须要使用箭头函数,使其this指向实例对象。

通过这种方式就没必要创建constructor构造器了。

<script type="text/babel">
    // 1.创建组件
    class Weather extends React.Component{
    
    
        // 类中可以直接写赋值语句,转为当前this的属性。
        state = {
    
    isHot:true,wind:'微风'}
        // 这里必须要使用箭头函数,让this指向外侧的this,也就是实例对象!
        changeWeather =  () => {
    
    
            let {
    
    isHot} = this.state
            this.setState({
    
    isHot:!isHot})
        }
        render() {
    
    
            const {
    
    isHot,wind} = this.state
            return (
                <h1 onClick={
    
    this.changeWeather}>
                    今天天气很{
    
    isHot ? '炎热' : '凉爽'}{
    
    wind}
                </h1>
            );
        }
    }

    // 2.渲染组件到页面
    ReactDOM.render(<Weather />,document.getElementById('test'))
</script>

猜你喜欢

转载自blog.csdn.net/IT_Holmes/article/details/126781108