最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 记录一些React笔记

    正文概述 掘金(略略略丶77)   2021-06-08   529

    React 笔记

    React 简介

    React 的特点

    1. 声明式编码
    2. 组件化编码
    3. React Native 编写原生应用
    4. 高效(优秀的Diffing算法)
    

    React 高效的原因

    1. 使用虚拟DOM,不总是直接操作页面真实DOM
    2. DOM Diffing算法,最小化页面重绘
    

    虚拟 DOM 与真实 DOM

    1. React 提供了一些 API 来创建一种“特别”的一般js对象
    	const VDOM = React.createElement('xx', {id: 'xx'}, 'xx');
    2. 虚拟 DOM 对象最终都会被 React 转换为真实的 DOM
    3. 我们编码时基本只需要操作 react 的虚拟 DOM 相关数据,react 会转换为真实 DOM 变化而更新界面
    

    React JSX

    JSX
    1. 全称:JavaScript XML
    2. react 定义的一种类似于 XML 的 JS 扩展语法:JS + XML 本质是
    	React.createElement(component, props, ...children)方法的语法糖
    3. 作用:用来简化创建虚拟 DOM
    	1). 写法: var ele = <h1>Hello JSX!</h1>
        2). 注意1:它不是字符串,也不是 HTML/XML 标签
        3). 注意2:它最终产生的就是一个 JS 对象
    4. 标签名任意:HTML 标签或其他标签
    5. 标签属性任意:HTML 标签属性或其他
    6. 基本语法规则
        1). 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
        2).	遇到以 { 开头的代码,以JS语法解析: 标签中的js表达式必须用{ }包含
    7. babel.js的作用
        1).	浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
        2).	只要用了JSX,都要加上type="text/babel", 声明需要babel来处理
    

    渲染虚拟 DOM(元素)

    1. 语法:ReactDOM.render(virtualDOM, containerDOM);
    2. 作用:将虚拟 DOM 元素渲染到页面中的真实容器 DOM 中显示
    3. 参数说明:
    	1). 参数一:纯 js 或 jsx 创建的虚拟 dom 对象
    	2). 参数二:用来包含 DOM 元素的真实 dom 元素对象(一般是一个div)
    

    事件处理

    1. 通过 onXxx(列如:onClick) 属性指定事件处理函数(注意大小写)
    	1). React 使用的是自定义(合成)事件,而不是使用的原生 DOM 事件(原生例如:onclick)	----- 为了更好的兼容性
    	2). React 中的事件是通过事件委托方式处理的(委托给组件最外层的元素)	----- 为了高效
    2. 通过 event.target 得到发生事件的 DOM 元素对象
    

    React 面向组件编程

    渲染类组件标签的基本流程

    1. React 内部会创建组件实例对象
    2. 调用 render() 得到虚拟 DOM,并解析为真实 DOM
    3. 插入到指定的页码元素内部
    

    组件的三大核心属性

    state
    // 理解
    1. state 是组件对象最重要的属性,值是对象(可以包含多个 key-value的组合)
    2. 组件被称为“状态机”,通过更新组件的 state 来更新对应的页面显示(重新渲染组件)
    
    // 强烈注意
    1. 组件中 render 方法中的 this 为组件实例对象
    2. 组件自定义的方法中 this 为 undefined,如何解决?
    	1). 强制绑定 this:通过函数对象的 bind()
    	2). 箭头函数
    3. 状态数据,不能直接修改或更新
    
    props
    // 理解
    1. 每个组件对象都会有 props(properties的简写)属性
    2. 组件标签的所有属性都保存在 props 中
    
    // 作用
    1. 通过标签属性从组件外向组件内部传递变化的数据
    2. 注意:组件内部不要修改 props 数据
    
    // 编码操作
    1. 内部读取某个属性值
    this.props.name
    2. 对 props 中的属性值进行类型限制和必要性限制
    	1). 第一种方式(React v15.5 开始已弃用)	
    	Person.propTypes = {
    		name: React.PropTypes.string.isRequired,
            age: React.PropTypes.number
        }
    	2). 第二种方式(新):使用 prop-types 库进行限制(需要引入 prop-types 库)
        Person.propTypes = {
    		name: PropTypes.string.isRequired,
            age: PropTypes.number
        }
    3.扩展属性:将对象的所有属性通过 porps 传递
    <Person {...person} />
    4. 默认属性值
    Person.propTypes = {
        name: '略略略',
        age: 18
    }
    5. 组件类的构造函数
    constructor(props) {
        super(props);
    }
    
    refs
    // 理解
    组件内的标签可以定义 ref 属性来标识自己
    
    // 编码
    1. 字符串形式的 ref
    <input ref="input1" />
    取值:this.refs.inputVal.value
    
    2. 回调形式的 ref
    <input ref={val => this.inputVal = val} />
    取值:this.inputVal.value
    
    3. createRef 创建 ref 容器
    myRef = React.createRef()
    <input ref={this.myRef} />
    取值:this.myRef.current.value
    
    // 注意点
    通过 event.target 得到发生事件的 DOM 元素对象 ----- 不要过度使用 ref
    

    组件的声明周期

    理解

    1. 组件从创建到死亡它会进行一些特定的阶段
    2. React 组件中包含一系列钩子函数(生命周期回调函数),会在特定的时刻调用
    3. 我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作
    

    生命周期(旧)

    // 声明周期的三个阶段(旧)
    1. 初始化阶段:由 ReactDOM.render() 触发 ----- 初次渲染
    	1). constructor()
    	2). componentWillMount()
    	3). render()
    	4). componentDidMount()
    2. 更新阶段:由组件内部 this.setState() 或父组件重新 render 触发
    	1). shouldComponentUpdate()
    	2). componentWillUpdate()
    	3). render()
    	4). componentDidUpdate()
    3. 卸载组件:由 ReactDOM.umountComponentAtNode() 触发
    	1). componentWillUnmount()
    

    生命周期(新)

    // 生命周期的三个阶段(新)
    1. 初始化阶段:由 ReactDOM.render() 触发 ----- 初次渲染
    	1). constructor()
    	2). getDerivedStateFromProps
        3). render()
    	4). componentDidMount()
    2. 更新阶段:由组件内部 this.setState() 或父组件重新 render 触发
    	1). getDerivedStateFromProps
        2). shouldComponentUpdate()
    	3). render()
    	4). getSnapshotBeforeUpdate
        5). componentDidUpdate()
    3. 卸载组件:由 ReactDOM.unmountComponentAtNode() 触发
    

    重要的钩子

    1. render:初始化渲染或更新渲染调用
    2. componentDidMount:开启监听,发送 ajax 请求
    3. componentWillUnmount:做一些收尾工作,如:清理定时器
    

    即将废弃的钩子

    1. componentWillMount
    2. componentWillReceiveProps
    3. componentWillUpdate
    现在使用会出现警告,下一个大版本需要加上 UNSAFE_ 前缀才能使用,以后可能会被彻底废弃,不建议使用
    

    React 应用(基于React脚手架)

    react 脚手架

    1. 脚手架:用来帮助程序员快速创建一个基于 xxx 库的模板项目
    	1). 包含了所有需要的配置(语法检查、jsx编译、devServer...)
    	2). 下载好了所有相关的依赖
    	3). 可以直接运行一个简单效果
    2. react 提供了一个用于创建 react 项目的脚手架库:create-react-app
    3. 项目的整体技术架构为:react + webpack + es6 + eslint
    4. 使用脚手架开发的项目的特点:模块化,组件化,工程化
    

    创建项目并启动

    第一步:全局安装:npm i -g create-react-app
    第二步:切换到想要创建项目的目录,使用命令:npx create-react-app hello-react
    第三步:进入项目文件夹:cd hello-react
    第四步:启动项目:npm start
    

    react 脚手架项目结构

    public ---- 静态资源文件夹
    		favicon.icon ------ 网站页签图标
    		index.html -------- 主页面
    		logo192.png ------- logo图
    		logo512.png ------- logo图
    		manifest.json ----- 应用加壳的配置文件
    		robots.txt -------- 爬虫协议文件
    src ---- 源码文件夹
    		App.css -------- App组件的样式
    		App.js --------- App组件
    		App.test.js ---- 用于给App做测试
    		index.css ------ 样式
    		index.js ------- 入口文件
    		logo.svg ------- logo图
    		reportWebVitals.js --- 页面性能分析文件(需要web-vitals库的支持)
    		setupTests.js ---- 组件单元测试的文件(需要jest-dom库的支持)
    

    React ajax

    理解

    前置说明
    1. React 本身只关注于界面,并不包含发送 ajax 请求的代码
    2. 前端应用需要通过 ajax 请求与后台进行交互(json数据)
    3. react 应用中需要集成第三方 ajax 库(或自己封装)
    
    常用的 ajax 请求库
    1. jQuery:比较重,如果需要另外引入不建议使用
    2. axios:轻量级,建议使用
    	1). 封装 XMLHttpRequest 对象的 ajax
    	2). promise 风格
    	3). 可以用在浏览器端和 node 服务器端
    

    axios

    GET 请求
    axios.get('/user?ID=12345')
      .then(function (response) {
        console.log(response.data);
      })
      .catch(function (error) {
        console.log(error);
      });
    
    axios.get('/user', {
        params: {
          ID: 12345
        }
      })
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });
    
    POST 请求
    axios.post('/user', {
      firstName: 'Fred',
      lastName: 'Flintstone'
    })
    .then(function (response) {
    console.log(response);
    })
    .catch(function (error) {
    console.log(error);
    });
    

    扩展:Fetch

    特点
    1. fetch:原生函数,不再使用 XMLHttpRequest 对象提交 ajax 请求
    2. 老版本浏览器可能不支持
    
    GET 请求
    fetch(url).then(function(response) {
        return response.json()
      }).then(function(data) {
        console.log(data)
      }).catch(function(e) {
        console.log(e)
      });
    
    POST 请求
    fetch(url, {
        method: "POST",
        body: JSON.stringify(data),
      }).then(function(data) {
        console.log(data)
      }).catch(function(e) {
        console.log(e)
      })
    

    React 路由

    SPA 的理解

    1. 单页 Web 应用 (single page web application, SPA)
    2. 整个应用只有一个完整的页面
    3. 点击页面中的连接不会刷新页面,只会做页面的局部更新
    4. 数据都需要通过 ajax 请求获取,并在前端异步展现
    

    路由的理解

    什么是路由?
    1. 一个路由就是一个映射关系(key: value)
    2. key 为路径,value 可能是 function 或 component
    
    路由分类
    1. 后端路由:
    	1). 理解:value 是 function,用来处理客户端提交的请求
        2). 注册路由:router.get(path, function(req, res))
        3). 工作过程:当 node 接收到一个请求时,根据请求路径找到匹配的路由,调用路由中的函数来处理请求,返回响应数据
    2. 前端路由:
    	1). 浏览器端路由,value 是 component,用于展示页面内容
        2). 注册路由:<Route path="/test" component={Test} />
        3). 工作过程:当浏览器的 path 变为 /test 时,当前路由组件就会变为 Test 组件    
    

    react-router-dom 的理解

    1. react 的一个插件库
    2. 专门用来实现一个 SPA 应用
    3. 基于 react 的项目基本都会用到此库
    

    react-router-dom 相关 API

    内置组件
    1. 	<BrowserRouter>
    2.	<HashRouter>
    3.	<Route>
    4.	<Redirect>
    5.	<Link>
    6.	<NavLink>
    7.	<Switch>
    
    其他
    1.	history对象
    2.	match对象
    3.	withRouter函数
    

    路由的基本使用

    准备
    下载 react-router-dom: npm install --save react-router-dom
    

    状态管理

    状态管理目录结构

    文件夹目录
    //状态管理根目录
    redux
    	//存放各种action对象
    	actions			
        	test1.js	//对象1
    		test1.js	//对象2
    	//用于初始化状态、加工状态
    	reducers		
        	index.js	//该文件用于汇总所有的reducer为一个总的reducer
    		test1.js	//存放的信息1
    		test2.js	//存放的信息2
    	//该模块是用于定义action对象中type类型的常量值,目的只有一个:便于管理的同时防止程序员单词写错
    	constant.js		
    	//redux 库最核心的管理对象
    	store.js		
    

    store.js 的配置

    /** 该文件专门用于暴露一个store对象,整个应用只有一个store对象 */
    
    //引入createStore,专门用于创建redux中最为核心的store对象
    import {createStore,applyMiddleware} from 'redux'
    //引入汇总之后的reducer
    import reducer from './reducers'
    //引入redux-thunk,用于支持异步action 
    //需要安装:npm i redux-thunk
    import thunk from 'redux-thunk'
    //引入redux-devtools-extension
    //需要安装:npm i redux-devtools-extension
    import {composeWithDevTools} from 'redux-devtools-extension'
    
    //暴露store 
    export default createStore(reducer,composeWithDevTools(applyMiddleware(thunk)))
    

    constant.js 的配置

    /* 该模块是用于定义action对象中type类型的常量值,目的只有一个:便于管理的同时防止程序员单词写错 */
    export const TEST1 = 'test1'
    export const TEST2 = 'test2'
    export const TEST3 = 'test3'
    

    action 中的每一个 对象js 配置

    /* 
    	该文件专门为Count组件生成action对象
    */
    import {INCREMENT,DECREMENT} from '../constant'
    
    //同步action,就是指action的值为Object类型的一般对象
    export const increment = data => ({type:INCREMENT,data})
    export const decrement = data => ({type:DECREMENT,data})
    
    //异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的。
    export const incrementAsync = (data,time) => {
    	return (dispatch)=>{
    		setTimeout(()=>{
    			dispatch(increment(data))
    		},time)
    	}
    }
    

    reducers 中的文件

    index.js 的配置
    /* 
    	该文件用于汇总所有的reducer为一个总的reducer
    */
    //引入combineReducers,用于汇总多个reducer
    import {combineReducers} from 'redux'
    //引入为Count组件服务的reducer
    import count from './count'
    //引入为Person组件服务的reducer
    import persons from './person'
    
    //汇总所有的reducer变为一个总的reducer
    export default  combineReducers({
    	count,
    	persons
    })
    
    其他的reducer 的配置
    /* 
    	1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
    	2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
    */
    import {INCREMENT,DECREMENT} from '../constant'
    
    const initState = 0 //初始化状态
    export default function countReducer(preState=initState,action){
    	// console.log('countReducer@#@#@#');
    	//从action对象中获取:type、data
    	const {type,data} = action
    	//根据type决定如何加工数据
    	switch (type) {
    		case INCREMENT: //如果是加
    			return preState + data
    		case DECREMENT: //若果是减
    			return preState - data
    		default:
    			return preState
       	<!-- 如果加工的是对象 可以 - {...preState, ...data} -->
    	}
    }
    

    在redux中的使用

    import store from './redux/store';
    import { userAction1 } from './redux/actions/user1';
    import { userAction2 } from './redux/actions/user2';
    
    
    
    //获取到存放在redux中的数据
    store.getState();
    //分发 action,触发 reducer 调用,产生新的state
    dispatch(action);		//示例:dispatch(userAction1(里面可以放需要修改的值,也可忽略))
    //注册监听,当产生新的 state 时,自动调用
    subscribe(listener)		
    //示例:store.subscribe(() => {
    	进行一些操作
        比如说可以:
    	this.setState({})
    })
    

    在react-redux中的使用

    //在App.js中引入 
    //可以不再App.js中引入 目的是包裹
    import store from './redux/store';
    import { Provider } from 'react-redux';		
    //并包裹
    <Provider store={store}>
        <div className="App">
            一些组件...
        </div>
    </Provider>
    
    //在组件中引入
    import { connect } from 'react-redux';
    //暴露的方式不再是 export default class Home extends Component
    //改成
    class Home extends Component {
        ....内容
    }
    //如果是发送action的一方
    export default connect(null, mapDispatchToProps)(Home);
    //接收信息的话就是
    export default connect(mapStateToProps)(Home);
    
    //两个函数的实现 - 简单示例
    //第一个函数 - 之后在 this.props。。。。中可以看到数据
    const mapStateToProps = (state) => {
        return state;
    }
    //第二个函数 - 需要在其他地方调用里面的函数 sendAction, 
    const mapDispatchToProps = (dispatch) => {
        return {
            sendAction: (这里可以带参数,比如说 value) => {
                dispatch({
                    //这里的对象其实就是一个action
                    type: 'add_action',
                    data: 1 //然后在这里替换 value
                })
            }
        }
    }
    

    redux

    redux 理解

    redux 是什么?
    1. redux 是一个专门用于做状态管理的 JS 库(不是 react 插件库)
    2. 它可以用在 react,angular,vue 等项目中,但基本与 react 配合使用
    3. 作用:集中式管理 react 应用中多个组件共享的状态
    
    什么情况下需要使用 redux
    1. 某个组件的状态,需要让他组件可以随时拿到(共享)
    2. 一个组件需要改变另一个组件的状态(通信)
    3. 总体原则:能不用就不用,如果不用比较吃力才考虑使用
    

    redux 的三个核心概念

    aciton
    1. 动作的对象
    2. 包含2个属性:
    	1). type:标识属性,值为字符串,唯一,必要属性
    	2). data:数据属性,值类型任意,可选属性
    3. 例子:{ type: 'ADD_STUDENT', data: {name: 'LueLueLue', age: 20} }
    
    reducer
    1. 用于初始化状态、加工状态
    2. 加工时,根据旧的 state 和 action,产生新的 state 的纯函数
    
    store
    1. 将 state、action、reducer 联系在一起的对象
    2. 如何得到此对象?
    	1). import { createStore } from 'redux'
    	2). import reducer from './reducers'
    	3). const store = createStore(reducer)
    3. 此对象的功能?
    	1). getState():得到 state
    	2). dispatch(action):分发 action,触发 reducer 调用,产生新的state
    	3). subscribe(listener):注册监听,当产生新的 state 时,自动调用
    

    redux 的核心 API

    createStore()
    作用:创建包含指定 reducer 的 store 对象
    
    store 对象
    1. 作用:redux 库最核心的管理对象
    2. 它内部维护着:
    	1). state
    	2). reducer
    3. 核心用法:
    	1). getState()
    	2). dispatch(action)
    	3). subscribe(listener)
    4. 具体编码:
    	1). store.getState()
    	2). store.dispatch({ type: 'INCREMENT', number })
    	3). store.subscribe(render)
    

    applyMiddleware()

    作用:应用上基于 redux 的中间件(插件库)
    

    combineReducers()

    作用:合并多个 reducer 函数
    

    redux 异步编程

    理解
    1. redux 默认时不能进行异步处理的
    2. 某些时候应用中需要在 redux 中执行异步任务(ajax,定时器)
    
    使用异步中间件
    npm install --save redux-thunk
    

    react-redux

    理解

    1. 一个 react 插件库
    2. 专门用来简化 react 应用中使用 redux
    

    React-Redux将所有组件分成两大类

    UI组件
    1. 只负责 UI 的呈现,不带有任何业务逻辑
    2. 通过props接收数据(一般数据和函数)
    3. 不使用任何 Redux 的 API
    4. 一般保存在components文件夹下
    
    容器组件
    1. 负责管理数据和业务逻辑,不负责UI的呈现
    2. 使用 Redux 的 API
    3. 一般保存在containers文件夹下
    

    相关 API

    // Provider:让所有组件都可以得到 state 数据
    <Provider store={store}>
    	<App/>
    </Provider>
    
    // connect:用于包装 UI 组件生成容器组件
    import { connect } from 'react-redux';
    connect(
    	mapStateToprops,		
        mapDispatchToProps
    )(Hello);
    
    // mapStateToprops:将外部的数据(即state对象)转换为UI组件的标签属性
    const mapStateToprops = function (state) {
      return {
        value: state
      }
    } 
    
    // mapDispatchToProps:将分发action的函数转换为UI组件的标签属性
    

    使用上redux调试工具

    安装chrome浏览器插件
    Redux DevTools
    
    下载工具依赖包
    npm install --save-dev redux-devtools-extension
    

    纯函数和高阶函数

    纯函数

    1. 一类特别的函数: 只要是同样的输入(实参),必定得到同样的输出(返回)
    2. 必须遵守以下一些约束  
        1).	不得改写参数数据
        2).	不会产生任何副作用,例如网络请求,输入和输出设备
        3).	不能调用Date.now()或者Math.random()等不纯的方法  
    3. redux的reducer函数必须是一个纯函数
    
    

    高阶函数

    // 理解: 一类特别的函数
        1)	情况1: 参数是函数
        2)	情况2: 返回是函数
        
    // 常见的高阶函数: 
        1)	定时器设置函数
        2)	数组的forEach()/map()/filter()/reduce()/find()/bind()
        3)	promise
        4)	react-redux中的connect函数
    
    // 作用: 能实现更加动态, 更加可扩展的功能
    

    起源地下载网 » 记录一些React笔记

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元