2020/05/31_react01

一:react概述

二:DOM和虚拟DOM介绍

三:虚拟DOM的本质和目的

四:diff算法介绍

五:webpack4.x的基本使用【创建webpack项目】

1 新建一个文件夹 【01.webpack-base】
2 使用命令【num init -y】,快速创建一个webpack项目【快速初始化项目】,【运行后在文件夹下产生一个package.json的文件】。
3 新建一个【src】目录,存放源代码。
4 新建一个【dist】目录,存放产品打包后的文件。
5 新建首页【index.html】
6 新建js入口文件【index.js】
7 使用cnpm安装webpack【cnpm i webpack -D】
8 全局运行【npm i cnpm -g】
9 安装【cnpm-cli】,【cnpm i webpack-cli -D】
10 在【webpack.config.js】文件中配置运行环境

//向外暴露一个打包对象
module.exports = {
    mode:'development'//development production
}

11 约定的打包的入口文件为【index.js】文件,【约定大于配置的规则】
12 使用【webpack】打包,打包后在【dist】目录下生成一个【main.js】的文件。

六:webpack-dev-server的基本使用

1 问题:修改代码后,【mian.js】还是上次打包的文件,不起作用,每次都要重新打包,比较麻烦
2 实时打包编译工具:【webpack-dev-server】
3 安装:【cnpm i webpack-dev-server -D】
4 在【package.json中配置】

"dev":"webpack-dev-server" 

5 执行:【npm run dev】,即可完成修改代码后的自动编译
6 生成的【mian.js】是放在内存中的根目录下,引用内存中的【main.js】
7 配置编译后自动打开浏览器

"dev":"webpack-dev-server --open --port --host" 

七:配置html-webpack-plugin插件

1 问题:编译后没有自动跳转到首页
2 解决:配置编译后自动跳转到首页,即配置首页到内存中
3 安装【html-webpack-plugin】插件,【cnpm i html-webpack-plugin -D】
4 在【webpack.config.js】中进行配置【html-webpack-plugin】插件

//配置插件
    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin') //配置在内存中自动生成index.js的插件
 //创建一个插件的实例对象
 const htmlPlugin = new HtmlWebpackPlugin({
     template:path.join(__dirname,'./src/index.html'),
     filename:'index.html'
 })
//向外暴露一个打包对象
module.exports = {
    mode:'development',
    plugins:[
        htmlPlugin
    ]
}

总结:完成了打包后的【mian.js】文件进内存,【index.html】进内存,并且打包好的【mian.js】自动注入到【index.html】中,使用包管理工具的基本环境设置完成。

八:使用react渲染最基本的虚拟DOM对象

1 安装react依赖【cnpm i react react-dom -S】

react:专门用于创建组件和虚拟DOM元素,同时组件的生命周期在这里
react-dom:专门用于对虚拟DOM进行操作,最主要的应用场景是:【ReactDOM.render()】。

2 在【index.html】页面中,创建容器:
3 在【index.js】中导入react。

import React from 'react'
import ReactDOM from 'react-dom'

4 在【index.js】中,使用【createelement】方法,创建虚拟DOM
参数说明:
参数1:标签
参数2:标签属性
餐宿3:其他的节点或者文本内容
5 在【index.js】中,获取容器,并将虚拟DOM放入获取到的容器中,【调用render函数渲染】
参数说明:
参数1:要渲染的元素
参数2:添加到的目标容器

九:使用createelement(),实现虚拟DOM元素的嵌套

十:在react中启用jsx语法

1 将html直接定义在js代码中。这些标签代表了一个或者多个js对象。并不是标签。这种在js中混合写入html代码的形式叫做JSX。浏览器默认不识别,可以使用第三方的工具来转换为原生的react中的方法。JSX的本质:在运行的时候被转换为了createlement()。
2 第三方的转换器,使用babel转换html标签
3 安装Babel插件

运行【cnpm i babel-core babel-loader babel-plugin-transfrom-runtime -D】
运行【cnpm i babel-preset-env babel-preset-stage-0 -D】

4 安装能识别转换JSX语法的包:

运行【cnpm i babel-preset-react -D】

5 添加【.babelrc】配置

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

6 在【package.json】中加入插件的配置信息

//向外暴露一个打包对象
module.exports = {
    mode:'development',
    plugins:[
        htmlPlugin
    ],
    module:{ //所有第三方的loader的匹配规则
        rules:[
            {test:/\.js|jsx$/,use:'babel-loader',exclude:/node_modules/}
        ]
    }
}

7 通过以上的配置,babel的配置完成,我们可以使用JSX语法来创建虚拟DOM元素或者组件。

十一:在jsx中书写js代码

1 在JSX中书写js代码,使用大括号即可
2 渲染数字
3 渲染字符串
4 渲染布尔值【需要tostring()】
5 为属性绑定值
6 渲染JSX元素
7 渲染JSX元素数组【这里有一个key的概念需要注意】

8 将普通的字符数组转换为jsx数组渲染到页面上【俩种方法】

**javascript中分号的问题:

当下一行的代码是以:`[,(,+,-,/`开头的,则上一行必须以分号结尾。**

十二:将普通的字符串数组,转为jsx数组,并渲染到页面上

一:在外部循环:
1 方法一(foreach方式):
(1)创建一个普通的字符串数组
(2)创建一个新的字符串数组
(3)遍历【froeach(item => {...})】旧的字符串数组,将每一个item用jsx语法包裹后添加到新的字符串数组中
(4)将新的字符串数组添加到容器中
2 方法2(map的方式):
(1)数组的map方法:遍历数组,但是有返回值
(2)作用:对遍历的每一项进行操作后将操作后的对象作为返回值返回。
(3)返回一个数组
总结:不管是foreach的方式还是map的方式,最终都要返回一个数组
二:在内部循环
1 在大括号中写js代码,循环出jsx结果。

十三:react中key的作用

1 作用:虚拟dom元素的状态需要保持的时候要提供key值,否则业务逻辑可能会出错。
2 react中需要key加到循环控制的直接元素上。

十四:关于jsx的语法的注意事项

1 jsx中的注释:使用行内注释,
2 为jsx中的元素添加class:【className】
3 为jsx中的lable元素添加for:【htmlfor】
4 在JSX创建DOM的时候,所有的节点,必须有唯一的根元素进行包裹

十五:创建组件的第一种方式和传递propos参数

1 创建组件的第一种方式【使用构造函数创建组件】
使用构造函数创建组件:

function Hello (){//首字母大写
    ...
    return 组件;//必须返回一个合法的jsx虚拟DOM元素
}

2 使用创建的组件,以标签的方式使用组件

3 react浏览器插件
4 传递参数【在组件中接受外界定义的数据】
(1)为渲染jsx的DOM元素中绑定属性

    使用组件并传递参数。

(2)在构造函数中传入【propos】形参

(3)在组件中使用【propos】对象获取数据

(4)注意事项:propos中的所有的数据都是只读的,定义之后不能改变

十六:使用ES6的展开运算符简化传递propos数据

//使用如下语法,即可获得propos中的所有的数据
...js对象

十七::将组件抽取到单独的jsx文件中

1 新建components文件夹

2 新建hello.jsx文件

3 在jsx文件中导入react react-dom依赖

3 使用构造函数创建组件

4 向外暴露组件

> //方式1:
>
> export default Hello
> 
> //方式2:
> 
> 创建并向外暴露组件

5 使用组件【js中导入组件】

> import Hello from './components/Hello.jsx'
> 
> 【配置文件中要配置jsx后缀】

6 配置webpack在导入组件的时候,省略后缀【.jsx】后缀名

//配置插件
    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')

// //创建一个插件的实例对象
 const htmlPlugin = new HtmlWebpackPlugin({
     template:path.join(__dirname,'./src/index.html'),
    filename:'index.html'
 })

//向外暴露一个打包对象
module.exports = {
    mode:'development',
    plugins:[
        htmlPlugin
    ],
    module:{
        rules:[
            {test:/\.js|jsx$/,use:'babel-loader',exclude:/node_modules/}
        ]
    },
        resolve:{
        extentsions:['.js','.jsx','.json'] //表示这几个文件的后缀名可以不写
    }
}
注意事项:
1 组件的首字母小写
2 在配置文件中要配置jsx的后缀

十八:配置webpack设置根目录:

1 配置别名:

//配置插件
    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')

// //创建一个插件的实例对象
 const htmlPlugin = new HtmlWebpackPlugin({
     template:path.join(__dirname,'./src/index.html'),
    filename:'index.html'
 })

//向外暴露一个打包对象
module.exports = {
    mode:'development',
    plugins:[
        htmlPlugin
    ],
    module:{
        rules:[
            {test:/\.js|jsx$/,use:'babel-loader',exclude:/node_modules/}
        ]
    },
    resolve:{
        extentsions:['.js','.jsx','.json'], //表示这几个文件的后缀名可以不写
        alias:{  //表示别名
           ** '@':path.join(__dirname,'./src')  //@表示项目根目录中**的'./src'
        }
    }
}

2 使用@符号映射:

import Hello form '@/component/Hello'

十九:【第二种创建组件的方式】创建类并且用过constructor挂载实例属性:

1 class的方式是ES6的新特性:
2 class的基本使用:
(1)ES6中的class关键字是实现面向对象编程的新形式
(2)创建类:
·传统方式:

function Person(name,age){
    this.name = name
    this.age = age
}
const p1 = new Person("sdfsd","12");
console.log(p1)

·使用class方式创建对象【创建类实例并且用过constructor挂载实例属性】

//定义类
class Animal{
    //使用构造器为创建的对象赋值
    //每一个类中都有一个构造器
    //没有定义,会自动生成一个默认的空参构造器:constructor(){}
    //手动定义构造器,会覆盖默认的空参构造器
    //构造器中的作用:创建类实例的时候,会优先执行构造器中的代码
    constructor(name,age){
        this.name=name
        this.age=age
    }
}
const a1 = new Animal("大黄","23");
console.log(a1)

(3)实例属性:

通过new的实例访问到的属性,叫做实例属性

(4)静态属性:

通过构造函数直接访问到的属性叫做静态属性【直接挂载给构造函数的属性】
即直接通过类名访问的属性
在class中,与构造函数平级,使用static修饰的属性

(5)实例方法,【挂载到原型实例上的方法】

//传统的对象
//可以被类的实例访问的方法:
person.prototype.say = function(){
   ...
}
//class对象
//与构造方法平级
jiao(){
   ...
   }

(6)静态方法:【挂载给构造函数的方法】

//传统类对象
//对象实例访问不到
person.show=function(){
   ...
}
//class类对象,在构造方法上挂载静态方法
//使用static关键字修饰
static show() {
...
}

二十:总结class的基本用法和俩个注意事项:

基本用法:
(1)class内部只能写构造器,属性【静态,实例】,方法【静态,实例】
(2)本质还是构造函数的方式,【语法糖】
(3)

二十一:使用extends实现子类继承父类

1 创建父类
2 创建子类
3 在class类中使用extends实现继承,并且访问实例属性
4 子类访问父类的实例方法

4.1父类定义实例方法
4.1子类访问父类的实例方法

5 constructor构造器中的super函数的使用说明:

5.1 使用super访问父类的构造函数
5.2 在子类的构造器中使用super()方法访问父类的构造方法
5.3 问题:
(1)为什么要在子类的构造器中调用super()方法
    答:因为,如果一个子类通过extends关键字继承了父类,那么在子类的构造函数中必须优先使用super()方法。
(2)什么是super()
    答:super()是一个函数,而且是父类的构造器,子类中的super()其实是构造器的一个引用。
(3)为什么调用了super(),方法,实例的属性都变为了undefined
    答:需要将参数通过构造器传递给真正给属性赋值的构造器上

6 为子类挂载独有的实例属性和实例方法:

答:使用this关键字为子类独有的实例属性赋值,【语法规范,子类中this只能放在super()方法之后】。

二十二:使用class关键字创建组件【创建组件的第二种方式】

1 最基本的组件结构

calss 组件名称 extends React.component{//必须继承React.component类
    //在组件的内部,必须要有render函数
    //作用:渲染当前的组件所对应的虚拟的DOM元素
    //是class的一个实例方法
    render(){
        //必须返回合法的JSX虚拟DOM元素
        return 
这是一个calss创建的组件
} }

2 为class创建的组件传递propos参数并直接使用this.propos来访问
(1)使用组件的时候从外部接受参数
(2)组件内部获取参数,【在class创建的组件中如果想使用外部传入的参数,不需要接受,只需要使用【{ths.propos.属性}】即可接受参数】
(3)使用ES6中的扩展方式接受参数

二十三:介绍react中的this.state

1 props只读的特性
2 俩种创建组件方式的区别(对比):
(1)使用class创建的组件有自己的私有的数据和生命周期,使用function创建的组件只有propos,没有生命周期。
有状态组件的私有数据:

constuctor(){
//调用父类的构造方法
super()
//保存有状态组件的私有数据
this.state={
//state中的数据可读可写
msg:"......."
}
}
render(){
rerurn ......
}

返回组件的是时候,通过【this.state.shuxing】访问私有数据。
(2)用构造函数创建的组件叫做【无状态组件】,使用class创建的组件叫做【有状态组件】,无状态组件一般用的不多。
3 什么情况下使用有状态组件,什么情况下使用五状态组件?
(1)如果一个组件需要自己的私有的数据,使用有状态组件
(2)如果一个组件不需要自己的私有的数据,使用无状态组件
(3)无状态组件由于没有私有数据,运行的效率较高
4 有状态组件和无状态组件的本质区别?
答:(1)有无state属性(2)有无生命周期函数
5 组件中的props和是state(data)之间的区别?
(1)propos中的数据都是外界传递进来的,只读,不能赋值
(2)state(data)中的数据都是组件私有的,(通过ajax获取到的数据,一般都是私有数据),可读可写。

二十四:评论列表案例

1 通过for循环生成多个组件

//数据
CompentList:[
{id:1,user:'张1',content:'哈哈,沙发1'},
{id:2,user:'张2',content:'哈哈,沙发2'},
{id:3,user:'张3',content:'哈哈,沙发3'},
{id:4,user:'张4',content:'哈哈,沙发4'},
{id:1,user:'张5',content:'哈哈,沙发5'},
]

2 创建父组件
3 在父组件的state【私有数据区】挂载数据
4 在返回值的部分循环数据并创建子组件。

二十五:将评论的item抽离为单独的CmItems组件

二十六:将评论列表和评论项抽取为单独的组件

1 抽取独立的组件的时候注意组件的引用关系,导入组件的路径问题,

二十七:抽取独立的组件之后的路径问题的优化

1 使用【@】优化路径问题

你可能感兴趣的:(react.js,前端)