React核心知识点总结(全)

React知识点总结(全)

一:React脚手架(create-react-app(cra))

1:安装

cnpm install -g create-react-app

2:初始化项目

create-react-app demoNmae

3:了解react脚手架中的webpack配置文件

​ 释放配置文件(一般不释放)

npm run eject(要删除目录下的.git文件) 释放所有的webpack配置文件

4:理解react设计的核心思想,一切皆为组件,可以细化一个元素

5:React开发特性:除了react本身这个库,其它的所有解决方案以及依赖库都是社区维护

二:理解JSX对象原理

名称释义:

JavaScript XmL 就是使用JS来描述一个DOM结构的对象
三:React组件

1:类组件(状态组件,有this)

快捷键创建方式:rcc
必须有return方法,return我们的Dom内容,同时,我们需要继承react.component,使我们的类变成一个组件。在return内部需要一个render函数,通过render函数来渲染创建我们的Dom内容。
类组件默认有属性,this.props,里面包含了关于路由(router)的一些参数,具体参见下面的react路由部分
事件this问题,参见下面react事件机制部分

2:函数组件(无状态组件,无this)

快捷创建方式:rfc
定义一个方法,通过return导出我们的jsx对象

3:组件应该包含的内容

react   库
react-dom  组件内容
react-dom.return  导出组件内容  类组件中应当包含render方法,渲染我们的DOM节点

4:关于组件的引用

在react中,引入的组件的第一个字母,必须大写(特别注意)

四:react事件机制

1:事件this指向问题

需要使用箭头函数或bind(this)的方法改变this的指向

(因为this是谁调用就是指向谁,在jsx事件中,this为jsx对象,无this,所以需要将this指向外层)

2:事件传值方式:默认为最后一个参数为事件对象,如果用户传值,则按顺序接收传值

五:react中组件传值

基本传值方式:在组件上直接使用元素属性来传值,指定传值的属性

传值的接收:

1:类组件:使用this.props来接收值,接收到的是一个对象,里面包含有传过来的属性值

2:函数组件:使用入参的形式接收参数,接收到的是一个对象(props入参)

六:react中属性传值的校验规则

1:安装属性类型检查插件:cnpm i -S prop-types

2:使用方法

引入我们的prop-types库
import propCheck from 'prop-types'
一:类组件中
通过定义静态变量的方式来进行属性校验
static propTypes = {
	//propsName : propCheck.type  例子如下
	userid: propCheck.stying,
	//添加isRequired属性来标识当前属性为必传属性
	userName : propCheck.stying.isRequired
}
//属性默认值
static defaultProps = {
	userAge: '12'
}

注:以上两个静态变量的名称为固定写法,不可更改  (propTypes, defaultProps)
二:函数组件中(类组件也可以使用此方法)
直接在组件对象上添加一个属性XXX.propTypes = {}对象 进行属性校验
在组件对象上添加一个属性XXX.defaultProps = {}对象 进行属性默认初始化
const Home = props =>{
	return (
		.....
	)
}
Home.propTypes = {
	userid: propCheck.stying,
	userName : propCheck.stying.isRequired
}
Home.defaultProps = {
	userid: '志伟'
}
七:react中样式书写

一:在jsx对象中使用style属性来进行样式书写

style属性使用绑定语法接收一个对象,这个对象里面的各种样式属性都是以小驼峰命名的方式存在着
	example:
	return(
		
)

二:使用classNames插件来给定样式名

cnpm i -S classnames

let sytle = classnames({
	active:active,
	disable:!active
	"title-cls":true,这里因为有- 所以需要使用引号
})

三:使用less来进行样式处理加载

​ 在react的webPack中,已经集成了sass样式预计sass样式的预处理器,如果使用sass来书写样式,可以不用安装sass已经sass-loader

使用less

​ 由于react中没有集成less已经less-loader,所以如果我们需要使用less,需要重构我们的开发依赖

1:安装我们的 react-app-rewired
	cnpm i -D react-app-rewired
2:安装我们的less一级less-loader
	cnpm i -D less less-loader
3:安装一个自定义库 customize-cra
 	cnpm i -D customize-cra
4:在我们的package.json同级目录下,新建一个文件: config-overriders.js
	在config-overriders.js文件中,引入自定义库,使用overrider方法,导出对象,再把对应的库加载到这个方法里面(2.x版本)
	const {
		override,
		addLessLoader
		addDecoratorsLegacy    //Es6装饰器
	} = require('customize-cra')
	module.exports = override(
		addLessLoader()
		addDecoratorsLegacy()
	)
	1.x版本(现在基本不用了)
	module.exports = config => {
        console.log(config.module.rules[1].oneOf)
        config.module.rules[1].oneOf.push({
            test: /\.less$/,
            use: [
              {
                loader: "style-loader",
              },
              {
                loader: "css-loader",
              },
              {
                loader: "less-loader",
                options: {
                  lessOptions: {
                    strictMath: true,
                  },
                },
              },
            ],
          })
        return config
	}

四:修改项目的启动命令

在package.json文件中,将我们的启动命令改为如下

 "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build"
  }
八:react中的虚拟Dom

在react中,虚拟Dom节点,使用createElement(type, props,children)方法 三个参数必传,不能不传

我们的render方法最终都会转换为createElement方法

createElement(
	'div',//标签
	{},//属性
	“这里是div标签内容”,
	createElement(   //从第三个参数开始,同级排列的参数都为div标签的子元素
        'p',//标签
        {},//属性
        “这里是p标签内容”, //从第三个参数开始,同级排列的参数都为p标签的子元素
	)
	“这里是div标签的第二个内容”
)
九:react中配置请求代理

当我们需要使用ajax进行跨域请求的时候,需要我们使用react中配置请求代理

一:安装依赖库 cnpm i -D http-proxy-middleware
二:配置setupProxy文件,在src路径下进行一个setupProxy.js文件,默认导出一个函数对象,这个函数有一个入参,为我们的express实例对象,通过这个对象,使用插件,引入我们的http-proxy-middleware库,然后使用createProxyMiddleware方法。
这里注意:app.use(),可以传入一个插件,或者定义一个插件,(定义一个插件第一个参数为,变量名,第二个参数为,处理内容)

代码如下:

const { createProxyMiddleware } = require('http-proxy-middleware')
module.exports = app =>{
	app.use(  //这里app.use使用一个插件库,createProxyMiddleware这个方法就返回一个插件
	createProxyMiddler('/apis',{
		//目标地主:
		target:'xxxxxxxx',
		//重写/apis字符
		pathRewrite:{'/apis':''},
		//是否改变请求源,域名
		changeOrigin:true
	})
	)
}

//这里导入导出的规范是遵循的common.js的模块化规范

到这里一个项目的基本框架就搭好了,这里放德明老师给我们项目框架,cnpm install

documentary-web.zip (报两天工时,开始摸鱼)

下面继续,react知识

十:react中数据定义

一:类组件中(两种方式)

1:直接写state,将类中的state覆盖掉
state = {
		
}
2:在constructor里面写
constructor() {
        // 为了能够继承Component 的构造函数,所以必须使用super()
        super()
        this.state = {
            date: Date.now(),
            __date: Date.now()
        }
    }

二:在函数组件中

使用useState方法
let [state, setState] = useState(initialState);
需要使用值得使用直接state,设置值得时候setState方法  
setState(newState)
十一:react中获取页面节点的方法
一:在我们的jsx对象上给定ref属性
二:通过我们的this.refs.属性可以获取到页面节点(不推荐)
三:通过createRef方法来获取,获取到的是一个reactDom对象,current属性为当前的页面节点(推荐),一般在componentDidMount生命周期,指定echarts图对象
代码如下:
state = {
	node:createRef()
}

render(){
	return (
		
) } componentDidMount(){ this.state.node.current //当前div的页面节点 } 四:在函数组件中 使用useRef()方法,类似于类组件的createRef方法
十二:react中类组件的生命周期,以及函数组件的钩子函数

类组件的生命周期

一张图,说明

在这里插入图片描述

这里列出常用的生命周期(按用途分,需要牢记)

一:挂载生命周期

componentDidMount()

可以获取页面节点,修改state初始数据,echarts对象实例化

二:更新生命周期

shouldComponentUpate(nextprops,nextstate)(更新之前)

用于性能优化,当props或state发送变化时,shouldComponentenUpdate()会在渲染执行之前被调用。返回值默认为true。首次渲染或使用forceUpadate()时不会被调用

PS:在做性能优化的时候,最后判断一下新旧两个props/state是否相同,相同则返回false不要触发更新,这样就不用生成新的dom树和旧的进行diff算法对比,从而进行性能优化

shouldComponentUpdate(nextProps, nextState){
	if(nextProps.content !== this.props.content){
		return true
	}
	else{
		return false
	}
}

componentDidUpdate(prevProps, prevState)(更新之后)

更新之后会被立即调用。首次渲染不会执行此方法。当组件更新后,可以在此处对DOM进行操作,如果使用this.setState()方法,需要加上限制条件,不然会造成死循环

三:卸载生命周期

componentWillUnmount()

一般移出我们的监听事件和我们的echarts对象,和大数据对象,已经清除定时器

函数组件的钩子函数

一:useState()方法,相当于我们类组件的state属性

useState方法返回一个对象,第一个参数为state的值,第二个参数为设值state的方法,useState方法中可以传递一个初始值

let [token, setToken] = useState('diengkdngaignelgndslgjieng')

二:useEffect()方法

它与类组件的componentDidMount、shouldComponentUpdate这个生命周期类似

如果传递了第二个参数,在数据进行改变的时候,只有当被监听的数据发生变化才会执行这个方法,否则不会执行

useEffect( () =>{
	.........
},[props])

三:useMemo()方法

使用useMemo方法的时候,一定要加上我们的依赖项,避免性能消耗,需要有一个返回值,return

let total = useMemo(() =>{
	return amount * rate + amount
})

四:useRef()方法

类似于类组件的createRef方法

十三:使用cotext进行简单的数据和方法传递

为了能够解决数据逐层传递的问题,提出使用cocntext来进行局部/全局简单的数据和方法传递

//引入创建我们的createContext方法
import Reatc, { createContext } from  'react'

const context = createContext()

引入createContext方法创建一个新的Context对象,使用Context.Provider来储存数据(数据,方法)

把组件的子组件加载到页面上,指定位置
const Store = ({children}) => {
    const [title, setTitle] = useState('新标题')
    const changeTitle = num => {
        setTitle('新标题+' + num)
    }
    return (
         //provider,必须有value属性
            
Store Title
{ children }
) } 导出当前组件,并且还要导出与Provider成对的Consumer组件 const Comsumer = Context.Consumer export { Store, Comsumer }

在下发数据的地方进行组件注册(scr/index.js 全局数据挂载,也可以在对应的需要传递数据的地方进行注册)


        
    

在需要消费的地方使用store.js导出Consumer对象进行数据消费
Consumer组件必须接收一个方法或函数
在Provider进行注册的数据/方法以入参的形式进行注入

 
 {
     args => {
     	return 

{ args.changeTitle(Math.random()) } }>{args.title}

} }
十四:react中高阶组件的使用-hoc

把一个复杂的业务分为了一步一步的操作,简单理解柯里化

高阶函数

function x(a){
	return function(b){
		return a+b
	}
}

高阶组件,类似于一个方法里面返回组件,这个方法里面需要传入一个组件作为入参,然后再重新返回一个组件

const MainLayout = (PageLayout) =>{
	return class Layout extends Component{
		render(){
			return (
				
) } } }
十五:使用redux,react-redux进行数据传递

redux相对于context来说,redux更加的规范,体系完整,有完整的数据操作流程

一:redux原理

简单来说就是,数据初始化—>数据修改动作发起—>数据扭转—>数据导出

深层原理:

二:在项目中使用react-redux(将redux和context进行结合,进行全局数据传递)

1:安装redux  cnpm i -S redux react-redux
2:新建一个store文件夹,暴露一个使用Redux.createStore方法创建一个store对象出来,store对象接收一个合并后的reducers

import { createStore } from 'redux'
import RootReducer from './reducers'
export default createStore(RootReducer)

3:需要新建一个reducers文件夹,暴露一个使用Redux.combineReducers合并后的reducer出来
combineReducers这个方法,接收一个对象,里面里面传入我们的不同的reducer

import { combineReducers } from 'redux'
import count from './count'
export default combineReducers({
    count
})

4:在reducers文件夹下边新建reducer文件进行单独的业务reducer开发。一个reducer为一个方法,这个方法需要传入两个参数,一个为初始值,一个为action。action为一个对象,这个对象必须包含一个type,以及其他需要传过来的参数。在reducer进行数据扭转

import {REDUCE_ACT, ADD_ACT} from '../action/types'
const initData = {value: 50}
const reducer = (state = initData, action) => {
    switch(action.type) {
        case REDUCE_ACT:
            return {
                ...state,
                value: state.value - action.step
            }
        case ADD_ACT:
            return {
                ...state,
                value: state.value + action.step
            }
        default:
            return {...state}
    }
}
export default reducer

5:因为action需要一个type,type一般为一个动作的类型/名字,所以需要使用静态变量来声明动作名字或类型

export const REDUCE_ACT = '减少'
export const ADD_ACT = '增加'

6:因为页面只是调用action,每一个action有单独的业务处理,所以需要单独定义每一个action

import {REDUCE_ACT, ADD_ACT} from './types'
export const getReduceAct = () => {
    return {type: REDUCE_ACT, step: 3}
}
export const getAddAct = () => {
    return {type: ADD_ACT, step: 6}import { connect } from 'react-redux'

7:在主页上全局注册
自己封装一个Context,使用Provider进行数据管理,再使用Consumer进行数据获取

import { Provider } from 'react-redux'

// 在使用react-redux的Provider的时候,不能使用value进行挂载store对象,需要使用store属性进行redux挂载

    
        
    ,
    
8:在其他页面上进行数据引用和动作发起

import { connect } from 'react-redux'

connect方法
第一个参数为映射state中的数据到组件的属性上
第二个参数为dispatch,如果不写的话会自动在组件的属性上加上dispatch方法,否则需要自己实现dispatch方法映射

三:异步action的实现

很多时候,在定义action的时候,需要我们请求数据,以便进行传递,这个时候,我们就需要实现我们的异步action了
问:为什么使用了中间件就能实现异步action了呢
React核心知识点总结(全)_第1张图片

1: 安装库:cnpm i -S redux-thunk
2: 在store的createStore方法中使用applyMiddleware方法进行thunk中间件使用

import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import RootReducer from './reducer'
export default createStore(RootReducer, applyMiddleware(thunk))

3:在action中的return 会是一个回调函数,回调函数会入参一个dispatch对象,在完成所有业务以后,使用dispatch方法返回一个action

const addAjaxAction = () =>{
	return async dispatch => {
		let result = await ajax()
		dispatch({type:actionType, step: 10})
	}
}
十六:react中路由的基本使用

一:基本使用

1:Router模式

​ Router(HashRouter:在路由中有一个#,BrowserRouter:这中模式成为H5 History模式,在react中开发可以测试,当正式发布的时候,需要后端支持)

​ Switch(相当于switch方法,匹配一个即结束路由匹配);Route(当条路由配置对象/组件:path、component/render)组件使用;Redirect组件,重定向

2:通用路由的使用方法
1、默认路由一般方法路由定义的最后,如果有404页面,需要放在默认路由的后边;
2、权限判断,可以使用简单的三目运算,也可以使用render方法进行权限判断

1:react-router-dom:是页面开发的路由,react-router-native:是react-native(RN)开发的路由管理器
安装我们的路由管理器

cnpm i -S react-router-dom

2:在我们的pages下面的index页面,进行路由管理

render() {
        return (
            
                {/* 使用switch匹配到一个路由就停止查找路由 */}
                {/* 相当于页面的switch方法,在写默认路由的时候,需要把默认路由写在最后 */}
                
                    
                    
                    {/* 普通模式下,匹配路由以什么开头,或则与当前要跳转的路由一定匹配 */}
                    {/* 如果路由出现二级这样的路由的时候,需要使用exact来精确匹配 */}
                    {/*  */}
                     {
                            return 
                        }
                    } exact/>
                    
                    {/*  */}
                    
                    {/*  {
                            return (
                                this.getUserRole()
                                ?
                                
                                :
                                
                            )
                        }
                    }/> */}
                    
                    {/* 默认路由,页面进来初始化路由 */}
                    
                    {/* 如果整个路由都匹配完以后,还是没有匹配到具体的路由,应该跳转到默认页面 */}
                    
                
            
        )
    }

二:路由传参

1、动态路由,在定义路由的时候在路由字符串上添加(/:paramsName)属性,在页面上使用props.match.params.paramsName来接收参数;
2、在页面上的history.push()方法中传递一个对象,{pathname: 路由名字, state: {key-value形式来传递参数}},在页面上使用props.location.state对象来接收数据;
3、在Route中使用render方法,routeParams => RouteComponent,对应的数据在页面上使用props直接接收;
十七:搭建React开发框架
a、得到一个空项目,编写全局请求地址文件
	b、新建src/index.js作为项目的入口文件
	c、新建src/pages/index.js作为项目组件分发/入口的文件
	d、项目中需要使用ajax请求:安装axios来实现数据交互,开发的时候需要使用http-proxy-middleware做请求代理,cnpm i -S axios http-proxy-middleware,新建src/setupProxy.js 文件来做开发请求代理:导出一个方法,方法有一个Express()实例对象,使用Express().use方法注册代理方法
	e、项目中需要使用样式预处理器less:安装样式加载器less/less-loader,还需要使用react-app-rewired、脚手架资定加载库customize-cra配置到全局webpack rules中:cnpm i -D less less-loader react-app-rewired customize-cra;在package.json同级目录下新建config-overrides.js,在这个文件中需要导出一个重载方法(override()),再在这个重载方法中添加需要使用到的customize-cra库;需要修改package.json中的启动、打包命令:react-scripts -> react-app-rewired
	f、因为cra是单页面开发模式,需要使用路由这个库来实现页面切换:使用react-router-dom库来实现功能,cnpm i -S react-router-dom,在项目的页面入口src/pages/index.js 文件中进行路由部署
	g、项目中需要缓存一些重要的数据,减少后端接口的调用次数减轻后端服务器压力,使用redux、react-redux,为了能够在redux的action中发起异步操作需要使用redux-thunk库:cnpm i -S redux react-redux redux-thunk;为了解决react-redux的connect方法的调用使用难度,需要使用注解/装饰器这个库,修改config-overrides添加装饰器库;
	h、在项目中新建一个文件夹(src/store),需要使用store/index.js暴露一个store数据对象(reducer是合并后的reducers,支持异步操作的中间件redux-thunk库的安装);新建src/store/reducer文件夹,使用reducer/index.js 合并并暴露一个reducer;因为reducer需要传递一个action,action在redux中定义为一个对象,并且必须有type属性,所以需要新建src/store/action文件夹,再在action/types.js文件中暴露所有的type;
十八:react的优化
immutable的使用

类似于vue中的数据后,重新渲染你的dom节点的原理,减少因为拷贝数据对象造成的性能损耗

用法

定义一个Map对象
import { Map } from 'immutable'
const obj = Map({
	x:10,
	y:20,
	z:30,
	k:{
		x:40,
		y:{
			h:60
		}
	}
})

//获取值  
obj.get('x')

//获取有层级下的值
obj.getIn(['x','y','h'])

//设置值
obj.set('x')  

//设置有层级下的值
obj.setIn(['x','y','h'])

在项目中的使用

在我们的store中,reducer进行数据扭转的时候,可以使用map来减少因为拷贝数据对象造成的性能损耗

import { Map } from 'immutable'

let initData = Map({
	count:10
})

const common = {state = initDate, action} =>{
	switch(action.type){
		cast:'add'
		return state.set('count', state.count + action.step)
	}
}

在页面上,使用我们的数据,则为Map.get()
结合redux-immutable的使用,减少reducer的拷贝,提高性能
import { combineReducers } from 'redux-immutable'

const reducer = combineReducers({
	common
})


//页面的使用
const mapStateToProps = state =>{
	count: state.get('common').get('count')
}
//get('count')为reducer中的state的MaP
//state.get('common')为我们reducer的Map
十九:Mobx的使用,替换我们的redux(注意版本问题,不要安装最新版本,mbox安装5的版本,mobx-react安装6的版本)
安装我们的Mobx

数据的提供者 Provider
数据的消费者 inject

在我们的store中直接定义我们的一个类,保护我们方法和数据
import { action, observable } from 'mobx'
class Counter {

	@observable
	count = 10,
	
	@action
	add(step){
		this.count += step
	}
}
export default new Counter()


在我们的主页面中
import { Provider } from 'mobx-react'
import counter from './store/counter'
render(
	
		
	
	document.getElementById('root')
)

在我们用的页面上,我们直接使用
import { inject, observer } from 'mobx-react'

@inject('counter')
@observer //函数组件用useobserver
class Home extends Component{
	//获取我们传下拉的值
	console.log(this.props.counter.count)
	render(){
		return(
			
{this.props.counter.count}
) } }

你可能感兴趣的:(学习笔记,reactjs)