React.js 学习笔记

https://reactjs.org/

React.js --第一天

1、React简介

React起源于Facebook的内部项目,因为该公司对市场上所有Javascript MVC框架都不满意,就决定自己写一套,用来架构Instagram(照片交友)的网站。做出来之后,发现这套东西很好用,就在2013年5月开源了;
Angular 2009年(谷歌);
由于React的设计思想独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它肯是将来web开发的主流工具;

清楚两个概念:
library(库):小而巧的库,只提供了特定的API,优点就是可以很方便的从一个库切换到另一个库,但是代码几乎不会改变;
Framework(框架):大而全的是框架;框架提供了一整套的解决方案,如果在项目中间,想切换到另外的框架,是比较困难的;

2、前端三大主流框架

(三大框架一大抄)
1、Angular.js :出来最早的前端框架,学习曲线比较陡,NG1学习起来比较麻烦,2~5开始,进行了一系列的改革,也提供了组件化开发的概念;从NG2开始,也支持使用TS(Typescript)进行编程;
2、Vue.js:**最火(关注的人比较多)**的一门前端框架,它是中国人开发的,对我们来说,文档要友好一些;
3、React.js:**最流行(用的人比较多)**的一门框架,因为它的设计很优秀;

3、从组件化方面对比React与Vue

1、什么是模块化:是从代码的角度进行分析的,把一些可复用的代码,抽离为单个的模块,便于项目的维护和开发;
2、什么是组件化:是从UI界面的角度来进行分析的,把一些可复用的UI元素,抽离为单独的组件;
3、组件化的好处:随着项目规模的增大,手里的组件越来越多,很方便就能把现有的组件,拼接为一个完整的页面;
4、Vue是如何实现组件化的:通过.vue文件,来创建对应的组件;
5、React是如何实现组件化的:React中有组件化的概念,但是,并没有像vue这样的组件模板文件,React中,一切都是以JS来表现的,因此,要学习React,JS要合格;ES6和ES7(async 和 await)要会用;

4、从其他角度对比React与Vue

1、开发团队方面
React是由FaceBook前端官方团队进行维护和更新的;因此,React的维护开发团队,技术实力比较雄厚;
Vue:第一版,主要是由作者尤雨溪专门进行维护的,当Vue更新到2.x版本后,也有了一个以尤雨溪为主导的开源小团队,进行相关的开发和维护;

2、社区方面
在社区方面,React由于诞生的较早,所以社区比较强大,一些常见的问题,坑,最优解决方案,文档,博客在社区中都是可以很方便就能找到的;
Vue是近几年才火起来的,所以,它的社区相对于React来说,要小一些,可能有的一些坑,别人没有踩过;

3、移动APP开发体验方面
Vue,结合Weex这门技术,提供了迁移到移动端App开发的经验,目前只是一个小的玩具,并没有很成功的案例;
React,结合ReactNative,也提供了无缝迁移到移动App的开发体验(RN用的最多,也是最火最流行的);

5、为什么要学习React

1、和Angular1相比,React设计很优秀,一切基于JS并且实现了组件化开发的思想;
2、开发团队实例强悍,不必担心断更的情况;
3、社区强大,很多问题都能找到对应的解决方案;
4、提供了无缝转到ReactNative上的开发体验,让我们技术能力得到了拓展;增强了核心竞争力;
5、很多企业中,前端项目的技术选型采用的是React.js;

6、React 中的几个核心概念

6.1 虚拟DOM(Virtual Document Object Model)

(1)DOM的本质是什么:浏览器中的概念,用JS对象来表示页面上的元素,并提供了操作DOM对象的API;
(2)什么是React中的虚拟DOM:是框架中的概念,是程序员 用JS对象来模拟页面上的DOM和DOM嵌套;
(3)为什么要实现虚拟DOM(虚拟DOM的目的):为了实现页面中,DOM元素的高效更新;
(4)DOM和虚拟DOM的区别:
        DOM:浏览器中提供了的概念;用JS对象来表示页面上的元素,并提供了操作元素的API;
        虚拟DOM:是框架中的概念;是开发框架的程序员,手动用JS对象来模拟DOM元素和嵌套关系;
              本质:用JS对象,来模拟DOM元素和嵌套关系;
              目的:就是为了实现页面元素的高效更新;
(5)DOM树的概念:
      一个网页呈现的过程

(a)浏览器请求服务器获取页面HTML代码;
(b)浏览器要先在内存中,解析DOM结构,并在浏览器内存中,渲染出一颗DOM树;
(c)浏览器把DOM树,呈现到页面上;

在这里插入图片描述

在这里插入图片描述
用JS对象的形式,模拟页面上DOM嵌套关系
在这里插入图片描述

6.2 Diff算法(different)

tree diff:新旧两棵DOM树,逐层对比的过程,就是Tree Diff;当整颗DOM逐层对比完毕,则所有需要被按需更新的元素,必然能找到;

component diff:在进行Tree Diff的时候,每一层中,组件级别的对比,叫做Component Diff;
       如果对比前后,组件的类型相同,则暂时认为此组件不需要被更新;
       如果对比前后,组件类型不同,则需要移除旧组件,创建新组件,并追加到页面上;

**element diff:**在进行组件对比的时候,如果两个组件类型相同,则需要进行元素级别的对比,这叫做Element Diff;
在这里插入图片描述

7、创建基本的webpack 4.x项目

1、运行npm init -y 快速初始化项目;
2、在项目根目录下创建src 源代码目录和 dist产品目录;
3、在src目录下创建index.html;
4、使用cnpm安装webpack,运行cnpm i webpack webpack-cli -D;
      全局运行安装cnpm:npm i cnpm -g
5、注意:webpack 4.x提供了约定大于配置的概念;目的是为了尽量减少配置文件的体积;
      默认约定了:
            (1)打包的入口是src->index.js;
            (2)打包的输出文件是dist->main.js
            (3)4.x新增了mode选项,可选的值为:production、development

7.1 webpack-dev-server工具的基本配置

在这里插入图片描述

7.2 配置html-webpack-plugin插件

(1)html-webpack-plugin插件帮我们把页面生成到内存中去;
(2)自动帮我们把打包好的main.js文件追加到页面中去;
在这里插入图片描述

8、关于Node和Chrome之间的关系

哪些特性node支持呢?Chrome支持哪些node就支持哪些;

9、使用React渲染最基本的虚拟DOM到页面上

1、运行cnpm install react react-dom -S(-S表示项目从开发到上线都要用到这个包,工具都是-D)
react :专门用于创建组件和虚拟DOM的,同时组件的生命周期都在这个包中;
react-dom:专门进行DOM操作的,最主要的应用场景,就是ReactDOM.render();

2、在index.html页面中,创建容器:

 <!-- 创建一个容器,将来渲染的虚拟DOM,会放到容器内显示 -->
    <div id="app"> </div>

3、导入包:

// 1、这两个导入的时候,接收的成员名称,必须这么写
import React from 'react' // 创建组件,虚拟DOM元素,生命周期
import ReactDOM from 'react-dom' // 把创建好的组件和虚拟DOM放到页面上展示的

4、创建虚拟DOM元素:

// 2、创建虚拟DOM元素
// 参数1:创建的元素类型,字符串,表示元素的名称
// 参数2:是一个对象或null,表示当前这个DOM元素的属性;
// 参数3:子节点(包括其他虚拟DOM获取文本子节点)
// 参数n:其他子节点
const myh1 = React.createElement('h1',{id:"h1",title:"这是h1元素"},'这是一个大大的h1');

5、渲染

// 3、使用ReactDom把虚拟DOM渲染到页面上
// 参数1:要渲染的那个虚拟DOM元素
// 参数2:指定页面上的DOM元素作为一个容器
ReactDOM.render(myh1,document.getElementById("app"));

10、使用React.createElement实现虚拟DOM嵌套

在这里插入图片描述

11、在React项目中启用JSX语法

什么是JSX语法:就是符合XML规范的JS语法;(语法格式相对来说,要比HTML严谨很多);

1、如何启用JSX语法?

安装babel插件:
    运行:npm i babel-core babel-loader babel-plugin-transform-runtime -D
    运行:npm i babel-preset-env babel-preset-stage-0 -D
    安装能够识别转换jsx语法的包 babel-preset-react
    运行 npm i babel-preset-react -D

添加.babelrc 配置文件:

{
    "presets": [
        "env",
        "stage-0",
        "react"
    ],
    "plugins": [
        "transform-runtime"
    ]
}

在webpack.config.js配置文件中添加babel-loader配置项:

module: { // 所有第三方模块的配置规则
        rules:[
            {test:/\.js|jsx$/,use:'babel-loader',exclude:/node_modules/} // 千万别忘记添加exclude排除项
        ]
     }
}


2、jsx语法的本质:
并不是直接把jsx渲染到页面上,而是内部先转换成了createElement形式,再渲染的;



3、在jsx中混合写入js表达式:
在jsx语法中,要把js代码写到{}中
渲染数字;
渲染字符串;
渲染布尔值;
为属性绑定值;
渲染jsx元素;
渲染jsx元素数组;
将普通字符串数组转为jsx数组并渲染到页面上【两种方案】;
在这里插入图片描述



4、在jsx中写注释:
推荐使用{/*这是注释*/}

5、为jsx中的元素添加class类名:
需要使用className来代替class;htmlFor替换label的for属性;

6、在JSX创建DOM的时候,所有的节点,必须有唯一的根元素进行包裹;

7、在JSX语法中,标签必须成对出现,如果是单标签,则必须自闭!

当编译引擎,在编译JSX代码的时候,如果遇到了<那么就把它当作HTML代码去编译,如果遇到了{}就把花括号内部的代码当作普通JS代码去编译;

12、React中创建组件

注意:组件的名称首字母必须大写

12.1 创建组件的第一种方式

使用构造函数来创建组件,如果要接收外界传递的数据,需要在构造函数的参数列表中使用props来接收;
必须要向外界return一个合法的JSX创建的虚拟DOM;

创建组件

// 第一种创建组件的方式
function Hello() {
    return <div>这是hello组件---</div>
}

为组件传递数据:

// 使用组件并为组件传递props数据
<Hello name={dog.name}></Hello>

// 在构造函数中,使用props形成,接收外界传递过来的数据
function Hello(props) {
    console.log(props);
    // 无论是Vue还是React,组件中的props永远是只读的,不能被重新赋值
    return <div>这是hello组件---{props.name}</div>
}
(1)使用ES6的展开运算符简化传递props数据的过程

在这里插入图片描述

(2)将组件抽离为单独的.jsx文件

Hello.jsx文件:

import React from 'react'

// 第一种创建组件的方式
function Hello(props) {
    // 如果在一个组件中return一个null,那表示此组件是空的,什么都不会渲染
    // 在组件中,必须返回一个JSX合法的虚拟DOM元素
    console.log(props);
    // 无论是Vue还是React,组件中的props永远是只读的,不能被重新赋值
    return <div>这是hello组件---{props.name}</div>
}

// 把组件暴露出去
export default Hello

index.js中导入组件:

// 导入Hello组件
// 默认,如果不做单独的配置的话,不能省略.jsx后缀名
import Hello from "./components/Hello.jsx"
(3)配置webpack从而在导入组件的时候,省略.jsx后缀名

webpack.config.js中新增一个resolve节点:

resolve:{
        //  表示这几个文件的后缀名可以省略不写
         extensions: ['.js','.jsx','.json']
     }
(4) 配置webpack设置根目录
import Hello from "@/components/Hello"

webpack.config.js中配置如下:

resolve:{
        //  表示这几个文件的后缀名可以省略不写
         extensions: ['.js','.jsx','.json'],
         alias:{  // 表示别名
             '@':path.join(__dirname,'./src')  // 这样@符号就表示项目根目录中src的这一层路径
         }
     }
12.2 创建组件的第二种方式

使用class关键字创建组件;
ES6中class关键字,是实现面向对象编程的新形式;

(1)class 关键字的基本使用

// 注意1:在class的{}中只能写构造器、静态方法、静态属性和实例方法
// 注意2:class关键字内部,还是用原来的配方实现的,所以说,我们把class关键字,称作语法糖;

class Animal {
    // 这是类中的构造器
    // 每一个类中,都有一个构造器,如果我们程序员没有手动指定构造器,那么,可以认为类内部有个隐性的,看不见的 空构造器,类似于constructor(){}
    constructor(name,age) {
        this.name = name;
        this.age = age;
    }

    // 在class内部,通过static修饰的属性,就是静态属性
    static info = 'eee';  // 今后用的不多

    eat() { // 实例方法
        console.log("这是动物的实例方法:吃");
    }

    // 这是动物类的静态方法【今后使用不多】
    static show() {
        console.log("这是静态方法");
    }
}

// 通过new出来的实例,访问到的属性,叫做实例属性
// 【静态属性】通过构造函数,直接访问到的属性,叫做静态属性
const rabbit = new Animal("大黄",3);
console.log(rabbit.name); // 实例属性
console.log(rabbit.age);  // 实例属性

console.log(Animal.info); // info 是Animal 的静态属性
(2)使用extends关键字实现子类继承父类
class Person {
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    
    eat() {
        console.log("everybody can eat");
    }
}

class American extends Person {

}

const jack = new American("Jack",20);
console.log(jack);
jack.eat()
// console.log();

class Chinese extends Person {
}
const zhangsan = new Chinese("zhangsan",20);
console.log(zhangsan);
// 子类访问父类上的实例方法
zhangsan.eat()
(3)constructor构造器中super函数的使用
    问题1:为什么一定要在constructor中调用super
    答:因为如果一个子类通过extends关键字继承了父类,那么在子类的constructor构造函数中,必须优先调用一下super()
    问题2:super是什么?
    答:super是一个函数,而且,它是父类的构造器,子类中的super,其实就是父类中constructor构造器的一个引用
    问题3:为什么调用了super()之后,实例的name和age都变成了undefined了?
    答:因为没有传参数啊啊啊啊

在这里插入图片描述
语法规范:在子类中,this只能放到super之后使用;
在这里插入图片描述

(4)使用class关键字创建组件

最基本的组件结构:

// 如果要使用class定义组件,必须让自己的组件,继承自React.Component
class Login extends React.Component {

    // 在组件内部,必须有render函数,作用:渲染当前组件对应的虚拟DOM结构
    render() {
        // render函数中,必须返回合法的JSX虚拟DOM结构
        return <div>这是class创建的组件</div>
    }
}
(5)为class创建的组件传递props参数并直接使用this.props来访问

在class关键字创建的组件中,如果想使用外界传递过来的props参数,不需接收,直接通过this.props.***访问即可

// 1、导入包
import React from 'react'
import ReactDOM from 'react-dom'

// 如果要使用class定义组件,必须让自己的组件,继承自React.Component
class Login extends React.Component {

    // 在组件内部,必须有render函数,作用:渲染当前组件对应的虚拟DOM结构
    render() {
        // render函数中,必须返回合法的JSX虚拟DOM结构
        // 在class关键字创建的组件中,如果想使用外界传递过来的props参数,不需接收,直接通过this.props.***访问即可
        return <div>这是class创建的组件 ---{this.props.name}---{this.props.age}
            {/* 注意:在class组件内部,this表示当前组件的实例对象 */}
        </div>
    }
}

const user = {
    name:'zhangsan',
    age:20
}
// 3、调用render函数渲染    jsx xml 比html严格很多
ReactDOM.render(
    <div>
        123
        {/*这是注释:直接把组件的名称,以标签的形式,丢到页面上即可*/}
        {/* 这里的Login标签,其实就是Login类的一个实例对象 */}
       <Login name={user.name} age={user.age}></Login>
    </div>,
    document.getElementById("app")
);

在这里插入图片描述

12.3 两种创建组件方式的对比

注意:使用class关键字创建的组件,有自己的私有数据(this.state)和生命周期函数;
但是使用function创建的组件, 只有props,没有自己的私有数据和生命周期函数;

1、用构造函数创建出来的组件:叫做“无状态组件”;
2、用class关键字创建出来的组件:叫做“有状态组件”;
3、什么情况下使用有状态组件?什么情况下使用无状态组件?
   如果一个组件需要有自己的私有数据,则推荐使用:有状态组件;
   如果一个组件不需要有私有的数据,则推荐使用:无状态组件;
   React官方说:无状态组件,由于没有自己的state和生命周期函数,所以运行效率会比有状态组件稍微高一些;

有状态组件和无状态组件之间的本质区别就是:有无state属性 和 有无生命周期函数!
在这里插入图片描述
4、组件中的props和state/data之间的区别
(1)props中的数据都是外界传递过来的;
(2)state/data中的数据,是组件私有的;(通过Ajax获取回来的数据,一般都是私有数据);
(3)props中的数据都是只读的,不能重新赋值;
(4)state/data中的数据,都是可读可写的;

React.js --第二天

一、样式

1、在组件中使用style行内样式并封装样式对象

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、使用css样式表美化组件

在这里插入图片描述

在这里插入图片描述

3、React中使用普通css样式表的作用域冲突问题

样式表导入之后,默认是在全局上,整个项目都生效的;

思考:Vue组件中的样式表,有没有冲突的问题?
答:有,但是可以使用<style scoped></style> 来解决;

疑问:React 中,有没有类似于 scoped这样的指令?
答:没有;因为在React中, 根本就没有指令的概念;但是可以为普通样式表通过modules参数启用模块化来解决;


4、为普通样式表通过modules参数启用模块化

可以在css-loader之后,通过?追加参数,其中,有个固定的参数,叫做modules,表示为普通的css样式表启用模块化;

module: { // 所有第三方模块的配置规则
        rules:[
            {test:/\.js|jsx$/,use:'babel-loader',exclude:/node_modules/},// 千万别忘记添加exclude排除项
            {test:/\.html$/,use:'html-loader'},
            // 可以在css-loader之后,通过?追加参数
            // 其中,有个固定的参数,叫做modules,表示为普通的css样式表启用模块化
            {test:/\.css$/,use:['style-loader', 'css-loader?modules']} 
        ]
     },

在这里插入图片描述

在这里插入图片描述

启用css-modules:
1、修改webpack.config.js这个配置文件,为css-loader添加参数:

  module: { // 所有第三方模块的配置规则
        rules:[
            {test:/\.js|jsx$/,use:'babel-loader',exclude:/node_modules/},// 千万别忘记添加exclude排除项
            {test:/\.html$/,use:'html-loader'},
            // 可以在css-loader之后,通过?追加参数
            // 其中,有个固定的参数,叫做modules,表示为普通的css样式表启用模块化
            {test:/\.css$/,use:['style-loader', 'css-loader?modules']} 
        ]
     },

2、在需要的组件中,import导入样式表,并接收模块化的CSS样式对象:

import cssObj from '../css/styles.css'

3、在需要的HTML标签上,使用className指定模块化的样式:

<h1 className={cssObj.title}>这是评论列表</h1>
5、使用localIdentName自定义生成的类名格式,可选的参数有:

[path]表示样式表相对于项目根目录所在路径;
[name]表示样式表文件名称;
[local]表示样式的类名定义名称;
[hash:length]表示32位的hash值;

    {test:/\.css$/,use:['style-loader', 'css-loader?modules&localIdentName=[path]-[name]-[local]-[hash:5]']} 
6、使用:local():global()

:local()包裹的类名,是被模块化的类名,只能通过className={cssObj.类名}来使用;同时,:local()默认可以不写,这样,默认在样式表中定义的类名,都是被模块化的类名;
:global()包裹的类名,是全局生效的,不会被css-modules控制,定义的类名是什么,就是使用定义的类名className="类名";

7、注意:只有.title这样的类样式选择器,才会被模块化控制,类似于body这样的标签选择器,是不会被模块化控制;
8、在项目中启用模块化并同时使用bootstrap

1、把自己的样式表,定义为.scss文件;
2、第三方的样式表,还是以.css结尾;
3、我们只需要为自己的.scss文件,启用模块化即可;
4、运行npm install sass-loader node-sass -D安装能够解析scss文件的loader;

二、事件

1、在React中为按钮绑定点击事件

1、事件的名称都是React提供的,因此名称的首字母必须大写onClick、onMouseOver
2、为事件提供的处理函数,必须是如下格式:

onClick = {function}

3、用的最多的事件绑定形式为:

<button onClick={()=>this.show("传参")}>按钮</button>

// 事件的处理函数,需要定义一个箭头函数,然后赋值给函数名称
show = (arg1)=> {
     console.log('show方法'+arg1);
}

4、在React 中,如果想要修改state中的数据,推荐使用this.setState({})
使用this.setState({})注意点:
(1)在setState,只会把对应的state状态更新,而不会覆盖其他的state状态;
(2)this.setSate方法的执行,是异步的;如果大家再调用完this.setSate之后,又想立即拿到最新的state值,需要使用this.setState({},callback)

在这里插入图片描述
在这里插入图片描述

2、在React中绑定文本框与state中的值(单向数据流)

1、在Vue中,默认提供了v-model指令,可以很方便的实现数据双向绑定;
2、但是,在React中,默认只是单向数据流,也就是只能把state上的数据绑定到页面,无法把页面中的数据的边自动同步回state;如果需要把页面上数据的变化,保存到state,则需要程序员手动监听onChange事件,拿到最新的数据,手动调用this.setState({})更改回去;
在这里插入图片描述

3、使用ref获取DOM元素引用(在React中绑定文本框与state中的值(单向数据流))

和Vue中差不多,vue为页面上的元素提供了ref的属性,如果想要获取元素引用,则需要使用this.$refs.引用名称;
在React中,也有ref,如果要获取元素的引用this.refs.引用名称

在这里插入图片描述

三、拓展

1、Vue中实例的生命周期

参见:Vue.js 学习笔记里面的;

2、React的组件生命周期函数图

在这里插入图片描述

后记

1、组件懒加载
导入懒加载 lazy组件、懒加载模式(看官网),并不是每个组件都需要加suspend,在顶级组件加
2、

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
React 18是React的最新版本,它引入了一些新的功能和改进。在学习React 18时,你可以关注以下几个方面: 1. React组件:React组件是构建用户界面的基本单元。你可以使用React.createElement()函数或JSX语法来创建React元素和组件。React元素是不可变的,而React组件是可复用的。\[1\] 2. react-dom.development.jsreact-dom/client模块:这些模块提供了处理真实DOM的功能,包括Diff算法和渲染成真实DOM的过程。你可以在HTML文件中引入这些模块,并使用ReactDOM.createRoot()方法来渲染React的DOM。\[2\] 3. Hook:Hook是React中的特殊函数,它允许你在函数组件中添加状态和其他特性。例如,useState是一个Hook,它可以让你在函数组件中添加状态。你可以使用useState来定义和更新状态,并在组件中使用它们。\[3\] 在学习React 18时,你可以通过阅读官方文档、参考教程和实践项目来深入了解这些概念和用法。同时,你也可以与其他开发者交流和分享经验,加深对React的理解。 #### 引用[.reference_title] - *1* *2* *3* [2023年React18笔记【慕课网imooc】【尚硅谷】【Vue3+React18 + TS4考勤系统】](https://blog.csdn.net/qq_28838891/article/details/124598439)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值