慕课 简书项目 个人笔记

第1章 课程导学

本章主要介绍学习react的重要性,课程的知识大纲,学习前提,讲授方式及预期收获。

1-1 课程导学
 React由Fackbook 2013年5月推出开源框架,
 函数式编程
 React 16以后的版本 -->也称React Fiber

第2章 React初探

本章主要讲解React项目的开发环境搭建,工程代码结构及React中最基础的语法内容,同时对前端组件化思想进行介绍。

2-1 React简介
  1. React Js (用React语法来编写网页交互) —>网页交互

  2. React Native (用React语法来编写原生App应用) —>原生App应用

  3. React VR(360) —>VR.全景应用

  4. React 由Facebook推出,2013年开源,函数式编程风格,

    官网地址:https://reactjs.org

  5. React 16以后的版本 -->也称React Fiber


2-2 React开发环境准备

开发环境搭建:

1. 引入.js文件来使用React 
(维护性低,需要拆分js文件,页面性能低)

2. 通过脚手架工具来编码  (
    手架工具:
        前端开发过程中的辅助工具,
        自动帮我们构建大型项目的开
        发流程和目录,它允许我们以
        一定的方式对js文件进行相互
        引用,让我们更方便对代码的
        管理,(但是在脚手架里面写
        的代码并不能直接运行,需要
        脚手架进行编译,编译出来的
        代码才可以被浏览器识别运行)
    常见的脚手架工具:GRUNT,Gulp,webpack
    官方推荐的脚手架工具:Create-react-app

安装官方脚手架工具:Create-react-app

1. 在官网点击文档Docs,在INSTALLATION
   (安装)中选择Add React to a New 
   App,打开
2.找到Create-react-app   下方会有安装
  命令
3.在命令行输入:
        (注意一定要先安装好node.js
        -->LTS稳定版,Current最新版)
    npm install -g Create-react-app     (install可以简写为i)
4. 选择项目存放的目录
5.创建项目
    Create-react-app   项目名
6.创建成功后,会出现提示命令
7.进入项目  cd  项目名
8.输入命令:npm start
9.会自动打开游览器,
  在localhost:3000运行项目

2-3 工程目录文件简介

运行项目:

1.进入项目文件
2.输入命令: npm run start

项目文件介绍:

1. yurn.lock(yurn不是npm安装的)
    ->项目所依赖的安装包的版本号
       会在这做一些限制
2. README.md->项目说明文件,
   可以自己写项目介绍(通过markdown语法)
3.Package.json->这个脚手架工具,
  代表是node的包文件(脚手架工具
  都会有这个文件)
4..gitignore->git管理文件时,
  有些文件不想传到git上面时,
  可以把这些文件放在本文件中
5.node_modules->项目依赖的第
  三方包,不是我们自己写的
6.public ->项目页面文件
7.public下的manifest.json
  -->定义了如果你可以当成
  一个APP来使用,就可以把
  它存储在桌面以上使用,有
  一个快捷方式,这个文件里
  面可以配置快捷方式的图标,
  大小和跳转的网页
8.src ->存放项目的所有源代码
   * src下面的index.js是项目的入口文件
   * all in js-->React中把文件都看成js文件
  9.src 下面的registerServiceWorker-->
     PWA全称progressive web application
     理念通过写一些网页来写手机App应用】
     引用`registerServiceWorker`实际上就
     是帮助我们借助网页去写手机APP应用的
     功能,可以做到的效果,假设我们引用了
     他,然后我们写了一个网页,把这个网页
     上线到一台支持https协议的服务器上,那
     么这个时候,我们网页就会具备这样的一
     个特性,当用户第一次访问我们这个网页,
     他需要联网才能看见我们这个网页,但是
     一旦用户访问完网页之后突然断网,如果你这
     个项目引用了`registerServiceWorker`,
     这个时候,即使他断网了第二次再访问,
     他也可以看到之前访问的那个页面,因为
     `registerServiceWorker`会帮您把之前
     的这个网页存储在游览器之内,即使你
     下次没网也可以再次访问	  
   10 src 下面的App.test.js文件->它是一
      个自动化的测试文件,当我们做react
      或者vue项目的时候,它里面会涉及函
      数式编程,所以我们可以做自动化的测试
//index.js  整个程序的入口
    【引入APP,然后把APP渲染在页面之上】
    
import React from 'react';//引入react包  
improt ReactDOM from 'react-dom';
import App from './App';//引入组件
        
ReactDOM.render(
        <App />,
        document.getElementById('root')
    );
    //把组件挂载到root节点上,
//App.js 【负责显示内容】

//import React from 'react';   
//class App extends React.Component {  
//等于下面的两行 
import React,{ Component} from 'react';         
 class App extends Component {  
   //一个类继承React下的Component这个基类
   就变成了React组件
   render(){
      return(
         <div>hello world</div>
      )
   }
}
export  default  App;  //将组件导出

上下两个文件相同,上面用了ES6解构赋值


2-4 React中的组件
  • 一个类继承React下的Component这个基类
    就变成了React组件

  • import App from './App'; //引入组件

  • 组件显示的内容由render()返回的内容决定

  • export default App;//将组件导出

  • ReactDOM.render(<App />,document.getElementById('root')); //ReactDOM是一个第三方模块,
    它的一个方法是render,这个方法可以 把组件挂载到某一个节点上,所有也需要引用ReactDOM

  • 使用JSX语法一定要引用 import React from 'react';


2-5 React 中最基础的JSX语法
  • 使用JSX语法,一定要引入React -> import React from 'react';

  • 组件名首字母大写,标签名的首字母大写的是组件(标签名的首字母小写的是html标签)

  • .要求render()返回的元素必须包含在一个大的元素中

    • 可以使用<Fragment></Fragment>占位符(React16版本提出的)

第3章 React基础精讲

本章通过TodoList功能的实现,给大家完整介绍React的基础语法,设计理念以及围绕React展开的一些编程思维。

3-1 使用React编写TodoList功能
   index.js  
   
       import React from 'react';     
       improt ReactDOM from 'react-dom';
       import TodoList from './TodoList';
       
       ReactDOM.render(
           <TodoList />,
           document.getElementById('root')
       );
       
    TodoList.js
    
        import React,{ Component,Fragment} from 'react';  
        
        class TodoList extends Component {  
        
            render(){
                return(
                    <Fragment>
                        <div><input /> <buton>提交</button></div>
                        <ul>
                            <li> 学英语</li>
                            <li> 学React</li>
                        </ul>
                    </Fragment>
                    
                )
            }
        }
        export  default  TodoList;  

3-2 React 中的响应式设计思想和事件绑定
//index.js
import React from 'react';
import ReactDom from 'react-dom';
import TodoList from './TodoList';

ReactDom.render(<TodoList />, document.getElementById('root'))
//TodoList.js
import React, { Component, Fragment } from 'react';

class TodoList extends Component {
	// constructor 在组件创建的第一个时刻自动被执行
	constructor(props) {//接受固定参数
		super(props);//继承调用父类的方法
		// 在组件中创建了两个数据,数据一定定义在state【状态】中
		this.state = {
			inputValue: 'hello world',
			list: []
		}
	}
    //当input的value改变时,获取新的值,替换页面是原来的值
	handleInputChange(e) {
		this.setState({
			inputValue: e.target.value
		})
	}
	render() {
		return (
			<Fragment>
				<input 
					value={this.state.inputValue}
					onChange={this.handleInputChange.bind(this)}
				/>
				<ul>
					<li>learn React</li>
					<li>learn Component</li>
				</ul>
			</Fragment>
		);
	}
}

export default TodoList;
  • 注意
    • 事件绑定【注意事件名称首字母大写】
    • this指向
    • 数据要放在状态state中
    • 要想改变状态中的数据需要调用setState函数【参数是一个对象】

3-3 实现 TodoList 新增删除功能
//index.js
import React from 'react';
import ReactDom from 'react-dom';
import TodoList from './TodoList';

ReactDom.render(<TodoList />, document.getElementById('root'))
//TodoList.js
import React, { Component, Fragment } from 'react';

class TodoList extends Component {

	constructor(props) {
		super(props);
		this.state = {
			inputValue: '',
			list: []
		}
	}
	//当input的value改变时,获取新的值,替换页面是原来的值
	handleInputChange(e) {
		this.setState({
			inputValue: e.target.value
		})
	}
    //当input输入完成时,按回车将将值保存在li中,并消除原来input中的值
	handleKeyUp(e) {
		if (e.keyCode === 13) {
			const list = [...this.state.list, this.state.inputValue];
			this.setState({
				list,
				inputValue: ''
			})
		}
	}
	//实现点击li,删除li,通过下标
	handleItemClick(index) {
		const list = [...this.state.list];
		list.splice(index, 1);
		this.setState({list});
	}

	render() {
		return (
			<Fragment>
				<input 
					value={this.state.inputValue}
					onChange={this.handleInputChange.bind(this)}
					onKeyUp={this.handleKeyUp.bind(this)}
				/>
				<ul>
					{
						this.state.list.map((value, index) => {
							return (
								<li 
									key={index} 
									onClick={this.handleItemClick.bind(this, index)}
								>
									{value}
								</li>
							)
						})
					}
				</ul>
			</Fragment>
		);
	}

}

export default TodoList;
  • 注意
    • bind可以传入第二个参数
    • react中有一个概念
    • immutable–>state 不允许我们做任何的改变
    • 【如果必须修改,则拷贝一个副本出来,修改副本】
    • 不要直接修改state,后面做react性能优化时,有问题

3-4 JSX语法细节补充
//index.js
import React from 'react';
import ReactDom from 'react-dom';
import TodoList from './TodoList';

ReactDom.render(<TodoList />, document.getElementById('root'))
//TodoList.js
import React, { Component, Fragment } from 'react';
import './style.css';

class TodoList extends Component {

	constructor(props) {
		super(props);

		this.handleInputChange = this.handleInputChange.bind(this);
		this.handleKeyUp = this.handleKeyUp.bind(this);

		this.state = {
			inputValue: '',
			list: []
		}
	}

	handleInputChange(e) {
		this.setState({
			inputValue: e.target.value
		})
	}

	handleKeyUp(e) {
		if (e.keyCode === 13 && e.target.value !== '') {
			const list = [...this.state.list, this.state.inputValue];
			this.setState({
				list,
				inputValue: ''
			})
		}
	}

	handleItemClick(index) {
		const list = [...this.state.list];
		list.splice(index, 1);
		this.setState({list});
	}

	getListItems() {
		return this.state.list.map((value, index) => {
			return (
				<li 
					key={index} 
					onClick={this.handleItemClick.bind(this, index)}
					dangerouslySetInnerHTML={{__html: value}}
				>
				</li>
			)
		})
	}

	render() {
		// 这是普通js中的注释
		return (
			<Fragment>
				{/* 这是JSX中的注释 */}
				<label htmlFor='myinput'>请输入内容:</label>
				<input 
					id='myinput'
					className='input'
					value={this.state.inputValue}
					onChange={this.handleInputChange}
					onKeyUp={this.handleKeyUp}
				/>
				<ul>
					{this.getListItems()}
				</ul>
			</Fragment>
		);
	}

}

export default TodoList;
  • 如何在JSX代码中编写注释

    • {/* 注释内容 */}

    • 第二种JSX注释
      {
      	//注释内容
      }
      
      
    • 注意第二种注释必须小心花括号的位置,不能与注释内容在一行

  • 组件以大写字母开头,小写字母开头的叫普通元素

  • class在react中用className替换

    • 因为可能和定义类的class混淆
  • 当在input输入框中输入HTML标签时,如何实现不被转意【如将<h1>字体样式为h1的样式</h1>

    • dangerouslySetInnerHTML={{__html: value}}
  • 当用label来扩大点击的区域,属性for,要换为htmlFor

    • 因为可能和循环的for混淆

3-5 拆分组件与组件之间的传值
//index.js
import React from 'react';
import ReactDom from 'react-dom';
import TodoList from './TodoList';

ReactDom.render(<TodoList />, document.getElementById('root'))

.input {
	border: 1px solid green;
}
//TodoList.js
import React, { Component, Fragment } from 'react';
import './style.css';

class TodoList extends Component {

	constructor(props) {
		super(props);

		this.handleInputChange = this.handleInputChange.bind(this);
		this.handleKeyUp = this.handleKeyUp.bind(this);

		this.state = {
			inputValue: '',
			list: []
		}
	}

	handleInputChange(e) {
		this.setState({
			inputValue: e.target.value
		})
	}

	handleKeyUp(e) {
		if (e.keyCode === 13 && e.target.value !== '') {
			const list = [...this.state.list, this.state.inputValue];
			this.setState({
				list,
				inputValue: ''
			})
		}
	}

	handleItemClick(index) {
		const list = [...this.state.list];
		list.splice(index, 1);
		this.setState({list});
	}

	getListItems() {
		return this.state.list.map((value, index) => {
			return (
				<li 
					key={index} 
					onClick={this.handleItemClick.bind(this, index)}
					dangerouslySetInnerHTML={{__html: value}}
				>
				</li>
			)
		})
	}

	render() {
		// 这是普通js中的注释
		return (
			<Fragment>
				{/* 这是JSX中的注释 */}
				<label htmlFor='myinput'>请输入内容:</label>
				<input 
					id='myinput'
					className='input'
					value={this.state.inputValue}
					onChange={this.handleInputChange}
					onKeyUp={this.handleKeyUp}
				/>
				<ul>
					{this.getListItems()}
				</ul>
			</Fragment>
		);
	}

}

export default TodoList;

以上代码是3.4的代码

现在将TodoList.js拆分

//TodoItem.js
import React,{Component} from 'react';

class TodoItem extends Component{
    constructor(props){
        super(props);
        this.handleClick=this.handleClick.bind(this);
    }
    render(){
        return (
            <div onClick={this.handleClick}>
            	{this.props.content}
            </div>)
    }
    //点击每一项,调用父组件的删除数据的方法,传入当前点击的第几项
    handleClick(){
        this.props.deleteItem(this.props.index)
    }
}

export default TodoItem;
//TodoList.js
import React, { Component, Fragment } from 'react';
improt TodoItem from  './TodoItem';
import './style.css';

class TodoList extends Component {

	constructor(props) {
		super(props);

		this.handleInputChange = this.handleInputChange.bind(this);
		this.handleKeyUp = this.handleKeyUp.bind(this);

		this.state = {
			inputValue: '',
			list: []
		}
	}

	handleInputChange(e) {
		this.setState({
			inputValue: e.target.value
		})
	}

	handleKeyUp(e) {
		if (e.keyCode === 13 && e.target.value !== '') {
			const list = [...this.state.list, this.state.inputValue];
			this.setState({
				list,
				inputValue: ''
			})
		}
	}

	handleItemClick(index) {
		const list = [...this.state.list];
		list.splice(index, 1);
		this.setState({list});
	}



	render() {
		// 这是普通js中的注释
		return (
			<Fragment>
				{/* 这是JSX中的注释 */}
				<label htmlFor='myinput'>请输入内容:</label>
				<input 
					id='myinput'
					className='input'
					value={this.state.inputValue}
					onChange={this.handleInputChange}
					onKeyUp={this.handleKeyUp}
				/>
				<ul>
					this.state.list.map((value, index) => {
					  return ({/*注意后面的组件和注释内容是返回两个内容,需要用一个div包裹起来*/}
						<div>
                          	<TodoItem 
                              content={value} 
                              index={index}
                              deleteItem={this.handleItemDelete.bind(this)}  
                                        
                             />
                            {/* <li 
							key={index} 
							onClick={this.handleItemClick.bind(this, index)}
							dangerouslySetInnerHTML={{__html: value}}
						  >
						  </li>*/}
                           </div>
						)
					})
				</ul>
			</Fragment>
		);
	}

}

export default TodoList;

组件是一个树形结构

  • 父组件向子组件传递数据
    • 父组件通过属性的形式来传【如<TodoItem content={value} />属性content可自定义】
    • 子组件通过this.props.属性名来使用【如{this.props.content}
  • 子组件向父组件传递数据【例如点击子组件中的其中每一项,实现删除】
    • 第一步需要获取到当前点击的是第几项,需要从父组件向子组件传递index={index}
    • 第二步子组件需要调用删除父组件中保存 ul中数据方法,因为子组件不能直接删除,也需要调用deleteItem={this.handleItemDelete}.bind(this)这里注意要报父组件的方法的this指向父组件,不然子组件在调用的时候会报错,找不到这个方法
    • 第三步子组件调用父组件的方法,把当前点击的第几向传过去this.props.deleteItem(this.props.index)

3-6 TodoList 代码优化
//TodoItem.js
import React,{Component} from 'react';

class TodoItem extends Component{
    constructor(props){
        super(props);
        this.handleClick=this.handleClick.bind(this);
    }
    render(){
        const {content}=this.props  {/*通过ES6解构赋值*/}
        return (
            <div onClick={this.handleClick}>
           		 {/*{this.props.content}*/}
				{content}
            </div>)
    }
    //点击每一项,调用父组件的删除数据的方法,传入当前点击的第几项
    handleClick(){
        const {deleteItem,index} = this.props;
        {/*this.props.deleteItem(this.props.index)*/}
        deleteItem(index);
    }
}

export default TodoItem;
//TodoList.js
import React, { Component, Fragment } from 'react';
improt TodoItem from  './TodoItem';
import './style.css';

class TodoList extends Component {

	constructor(props) {
		super(props);
		this.state = {
			inputValue: '',
			list: []
		}
        this.handleInputChange = this.handleInputChange.bind(this);
	    this.handleKeyUp = this.handleKeyUp.bind(this);
		this.handleItemDelete=this.handleItemDelete.bind(this);
    }

	render() {
		// 这是普通js中的注释
		return (
			<Fragment>
				{/* 这是JSX中的注释 */}
				<label htmlFor='myinput'>请输入内容:</label>
				<input 
					id='myinput'
					className='input'
					value={this.state.inputValue}
					onChange={this.handleInputChange}
					onKeyUp={this.handleKeyUp}
				/>
				<ul>
					{this.getTodoItem()}
				</ul>
			</Fragment>
		);
	}
    getTodoItem(){
       return this.state.list.map((value, index) => {
			 return (
				<div>
                     <TodoItem 
                         content={value} 
                          index={index}
                          deleteItem={this.handleItemDelete}          
                       />
                    </div>
				)
			})
    }
	handleInputChange(e) {
		//this.setState({
		//	inputValue: e.target.value
		//})
        /*this.setState(() =>{
            return{
                inputValue:e.target.value
            }
        })*/
        //简写
        const value=e.target.value//这里是异步的设置数据,后面讲
    	this.setState(() =>({
                inputValue:value
           }));
	} 
	handleKeyUp(e) {
		if (e.keyCode === 13 && e.target.value !== '') {
			const list = [...this.state.list, this.state.inputValue];
			this.setState({
				list,
				inputValue: ''
			});
		}
	}

	handleItemClick(index) {
		const list = [...this.state.list];
		list.splice(index, 1);
		this.setState({list});
	}


}

export default TodoList;

3-7 围绕 React 衍生出的思考
  • react是声明式开发,与之对应的是命令式的开发方式–>像盖楼一样,如果用命令式的,需要一步步告诉它怎么盖。而react是面向数据来编程的,只需要把数据构建好了就可以了,react会自动帮你根据数据会构建这座大厦,【可以节约大量的DOM操作的代码】
  • 可以与其他框架并存–>react只会管理绑定的根节点的部分
  • 组件化
  • 单向数据流 -->父组件可以向子组件传值,但是子组件不能去改变这个值【这个值对应子组件来说是只读的】
  • 视图层框架【数据与页面渲染】
  • 函数式编程 【优势1.维护容易2.面向测试的开发流程,更容易实现自动化测试】

第4章 React高级内容

本章讲解React高级部分内容,包含PropTypes,生命周期函数,虚拟Dom,数据mock,动画实现等部分课程讲解。

第4章 React高级内容

本章讲解React高级部分内容,包含PropTypes,生命周期函数,虚拟Dom,数据mock,动画实现等部分课程讲解。

4-1 React developer tools 安装及使用
  • 下载React插件需要翻墙

4-2 PropTypes 与 DefaultProps 的应用
  • PropTypes -->用于传值类型校验
    • 1.没有传值的不会去校验
    • 2.isRequired 不传值会报警告
    • 3.oneofType([ 类型1,类型2]) -->类型是括号中的任意一种
  • DefaultProps–>默认属性值
//TodoItem.js

TodoItem.propTypes={
    test:PropTypes.string,//判断test类型是否是字符串
    content:PropType.string,
    deleteItem:PropTypes.func,//判断deleteItem类型是否是函数
    index:PropTypes.number//判断index类型是否是数值
}

4-3 props,state 与 render 函数的关系
  • 当组件的state或者props发生改变的时候,render函数就会重新执行

    • 当父组件的render函数被运行时,它子组件的render都将被重新运行一次
    //counter.js
    import React, { Component, Fragment } from 'react';
    import Child from './child';
    
    class Counter extends Component {
    
    	constructor(props) {
    		super(props);
    		this.handleBtnClick = this.handleBtnClick.bind(this);
    		this.state = {
    			counter: 1
    		}
    	}
    
    	handleBtnClick() {
    		const newCounter = this.state.counter + 1;
    		this.setState({
    			counter: newCounter
    		})
    	}
    
    	render() {
    		// 当组件初次创建的时候,render函数会被执行一次
    		// 当state数据发生变更的时候,render函数会被重新执行
    		// 当props数据发生变更的时候,render函数会被重新执行
    		return (
    			<Fragment>
    				<button onClick={this.handleBtnClick}>增加</button>
    				<Child number={this.state.counter}/>
    			</Fragment>
    		)
    	}
    
    }
    
    export default Counter;
    
    //child.js
    import React, { Component } from 'react';
    
    class Child extends Component {
    
    	render() {
    		console.log('child render');
    		return (
    			<div>{this.props.number}</div>
    		)
    	}
    
    }
    
    export default Child;
    

4-4 React 中的虚拟DOM
  • 第一次推导过程

    1. state函数
    2. JSX 模块
    3. 数据 +模块 结合,生成真实的DOM,来显示
    4. state 发生改变
    5. 数据 +模块 结合,生成真实的DOM,替换原始的DOM
    • 缺陷:
      • 第一次生成了一个完整的DOM片段
      • 第二次生成了一个完整的DOM片段
      • 第二次生成的DOM替换第一次生成的DOM片段
  • 第二次推导过程

    1. state函数
    2. JSX 模块
    3. 数据 +模块 结合,生成真实的DOM,来显示
    4. state 发生改变
    5. 数据 +模块 结合,生成真实的DOM,本不直接替换原始的DOM
    6. 新的DOM(DoucumentFragment->文档碎片) 和原来的DOM 做对比,找差异
    7. 找出input框发生了变化
    8. 只用新的DOM中的input元素,替换掉老的DOM中的input元素
    • 缺陷、
      • 性能提高不明显
  • 第三次推导过程

    1. state 函数

    2. JSX 模块

    3. 数据 +模块 结合,生成真实的DOM,来显示

      <div id='abc'><span>hello world</span></div>

    4. 生成虚拟DOM (虚拟DOM就是一个js对象,用它来描述真实的DOM) (损耗了性能)

      ['div',{id:'abc'},['span',{},'hello world']]

    5. state 发生变化

    6. 数据 +模块 生成新的虚拟DOM (极大的提升了性能)

      ['div',{id:'abc'},['span',{},'bye bye']]

    7. 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容 (极大的提升了性能)

    8. 直接操作DOM,改变span中的内容

  • 最终版还在下面4-5


4-5 深入了解虚拟DOM
  • 最终版

    1. state 函数

    2. JSX模板

    3. 数据 +模板生成虚拟DOM (虚拟DOM就是一个js对象,用它来描述真实的DOM) (损耗了性能)

      ['div',{id:'abc'},['span',{},'hello world']]

    4. 用虚拟DOM的结构生成真实的DOM,来显示

      <div id='abc'><span>hello world</span></div>

    5. state 发生改变

    6. 数据 + 模板 生成新的虚拟DOM (极大的提升了性能)

      ['div',{id:'abc'},['span',{},'bye bye']]

    7. 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容 (极大的提升了性能)

    8. 直接操作DOM,改变span中的内容

    • 优点
      1. 性能提升了
      2. 它使跨端应用得以实现。 React Native

    虚拟DOM的应用:

    • 原始应用=>虚拟DOM=>原生组件
    • 网页应用=>虚拟DOM=>真实DOM

    JSX实现原理

    • JSX–>create Elaement–>虚拟DOM(JS对象)–>真实DOM

4-6 虚拟 DOM 中的 Diff 算法
  • 目的:找差异

  • 定义:两个虚拟DOM之间的对比

  • Diff算法分为

    1. 同层对比
      • 先对比顶层,再从上到下,如果顶层不同,就不在对比后面的
    2. key对比
      • key是为了提高虚拟DOM对比的性能,key不建议为index,建议为item(内容)
  • setState是异步的,可以把多次setState结合成一次setState,减少虚拟DOM的对比次数

    • setState是一个异步函数,第一个参数是异步函数执行完后才调用

4-7 React 中 ref 的使用
import React, { Component, Fragment } from 'react';

class Counter extends Component {

	constructor(props) {
		super(props);
		this.handleBtnClick = this.handleBtnClick.bind(this);
		this.state = {
			counter: 1
		}
	}

	handleBtnClick() {
		const newCounter = this.state.counter + 1;
		console.log(this.divElem.innerHTML);
		// setState 是异步的
		this.setState(() => {
			return {
				counter: newCounter
			}
		}, () => {
			console.log(this.divElem.innerHTML);
		})
	}

	render() {
		// ref 写在html标签上,获取的是dom节点
		// ref 写在组件标签上,获取的是组件的js实例
		return (
			<Fragment>
				<button onClick={this.handleBtnClick}>
					增加
				</button>
				<div ref={(div)=>{this.divElem = div}}>{this.state.counter}</div>
			</Fragment>
		)
	}

}

export default Counter;
  • ref是在react中帮助我们直接获取DOM元素
  • setState是一个异步函数,第一个参数是异步函数执行完后才调用

4-8 React 的生命周期函数
import React, { Component, Fragment } from 'react';
import Number from './number';
// 在React中,生命周期函数指的是组件在某一时刻会自动执行的函数
// 当数据发生变化时,render函数会被自动执行, render函数是一个react的生命周期函数

class Counter extends Component {

	handleClick() {
		const newNumber = this.state.number + 1;
		this.setState({
			number: newNumber
		})
	}

	constructor(props) {
		console.log('constructor');
		super(props);
		this.handleClick = this.handleClick.bind(this);
		this.state = {
			number : 1
		}
	}

	// 在组件即将被挂载到页面的时刻自动执行【执行一次】
	componentWillMount() {
		console.log('componentWillMount');
	}
	
	// 渲染时自动执行
	// 组件更新前 componentWillUpdate 自动执行
	render() {
		console.log('render')
		return (
			<div>
				<div onClick={this.handleClick}>hello world</div>
				<Number count={this.state.number}/>
			</div>
		)
	}

	//组件被挂载到页面之后,自动被执行【执行一次】
	componentDidMount() {
		console.log('componentDidMount');
	}

	// 组件更新前 前自动执行
	shouldComponentUpdate() {
		console.log('shouldComponentUpdate');
		return true;
	}

	// 组件更新前 shouldComponentUpdate之后 自动执行
	componentWillUpdate() {
		console.log('componentWillUpdate');
	}

	// 组件更新前 render 自动执行
	componentDidUpdate() {
		console.log('componentDidUpdate');
	}

	// 组件从页面中移除前自动执行
	componentWillUnmount() {
		console.log('componentWillUnmount');
	}

}

export default Counter;
  • 生命周期函数值在某一时刻组件会自动调用执行的函数

    • constructor也是一个什么周期函数,是ES6的,不是react的–>组件一创建时调用
  • Initalization -->初始化过程

    • setup props and state
  • Mounting -->组件挂载

    • componentWillMount -->在组件即将被挂载到页面的时刻自动执行【执行一次】
    • render —>1.渲染时自动执行 2.组件更新前 componentWillUpdate 自动执行
    • componentDidMount -->组件被挂载到页面之后,自动被执行【执行一次】
  • Updation -->组件更新

    • props

      • componentwillReceiveProps -->1.一个组件要从父组件接收参数 2.如果这个组件第一次存在于父组件中,不会被执行 3.如果这个组件之前已经存在于父组件中,才执行
      • shouldComponentUpdate–>组件被更新之前(你的组件需要更新吗?) return true 表示更新 false表示不高兴,后面的生命周期函数不会执行
      • componentWillUpdate–>组件被更新之后执行,在shouldComponentUpdate之后执行,如果shouldComponentUpdate为true,才执行,false不执行
      • render
      • componentDidUpdate–>组件更新完成之后,才执行
    • Unmounting

      • componentWillUnmount–>把组件从页面中剔除的时候会被执行

      每一个组件都有生命周期函数


4-9 React 生命周期函数的使用场景
  • 除了render生命周期函数外,其他的生命周期函数都可以删除

    • 为什么不能删除render生命周期函数?
      • 我们的组件是继承Component组件的,reactComponent组件默认内置了所有生命周期函数,唯独没有内置render函数的默认实现,所有对于我们组件来说,我们的render函数必须自己定义,不然会报错
  • 提升子组件的性能

    • 因为每一次改变父组件的数据,会影响子组件,通过sholdComponentUpdate声明周期函数来提升
    • 可以避免一个组件,做无谓的render操作
    • render函数重新执行,就意味着react底层要对组件生成一份虚拟DOM,和以前的虚拟DOM做比对【性能优化】
    shouldComponentUpdate(nextProps,nextState){//nextProps[State]表示接下来我的Props[State]会变成什么样
        if(nextProps.content !== this.Props.cotent){//接下来的content不等于原来的content时
            return true;//重新渲染
        }else{
            return false;//接下来的content等于原来的content时,不重新渲染
        }
    }
    

    !!!react中性能优化的点:

    1. this.handleClick.bind(this);这样的方法改变作用域的话,我们把作用域的修改放在constructor,这样会保证作用域的修改,直接进行一次,也可以避免子组件的无谓渲染

    2. setState是异步的,可以把多次setState结合成一次来做,减少虚拟DOM的对比频率

    3. react底层用了虚拟DOM这个概念,然后还有同层比对和key值比对,来提升虚拟DOM匹配的速度,从而提高性能

    4. 借助sholdComponentUpdate这个方法,可以避免无谓的组件的render`运行

  • AJAX请求

    • componentDidMount() ->在组件挂载在页面之前执行,之后不会在被重新执行
    • 放在constructor或者 componentDidMount都可以,但是不建议
  • 推荐一个react的AJAX请求 axios

    • 通过yarn add axios 添加到项目

    • 使用方法:

      1. 页面中引入import axios from 'axios';

      2. componentDidMount() 中 调用,代码如下:

        componentDidMount() {//then表示成功 catch 失败
        	axios.get('/api/todolist')
                .then(()=>{alert('succ')})
            	.catch(()=>{alert('error')})
        }
        

4-10 使用Charles实现本地数据mock
  • Charles图标是一个陶瓷花瓶

  • mock–>自己模拟一下接口的数据

  • 如何模拟后台数据接口:

    1. 新建一个.json文件,并填入数据

    2. 打开Charles工具

    3. 找到Togls—>Map Local

    4. 开始是一个空的内容,我们可以add(添加一个配置项)

    5. 添加配置

      Protocol:http
      	Host:localhost
      	Port:3000
      	Path:/api/todolist
      	Query:[不填]
      	代理到哪里
      	Local path:选择到.json文件【路径是.json文件的路径】
      	
      
    6. 点击OK

    7. 注意要把Enable Map Local 勾选上

    8. Location 我们刚才配置的选项也勾选上

    9. 点击OK

    10. 输入好请求的路径,刷新页面,打卡控制台,找到Network,找到刚才请求的文件,选择Preview即可查看请求返回的内容

  • Charles的功能:

    • 可以抓到游览器向外发送的请求,可以对一些请求做一些处理
    • 经过刚才我们配置的模拟后台的数据接口,可以把游览器发送的请求修改为我们本地模拟的数据文件
    • Charles相当于中间的代理服务器
  • 模拟数据接口之后,如何填充数据,代码如下:

    componentDidMount() {//then表示成功 catch 失败
    	axios.get('/api/todolist')
            .then((res)=>{
            console.log(res.data);//获取请求返回的数据
            //this.setState(() =>{
            //    retrun{
            //  	list:res.data
            //   }
            // });
            //因为放回的是一个数据,可以这样写,
            //用展开运算符,可以防止数据被更改
            this.setState(() =>({
                list:[..res.data]
            }));
        })
        	.catch(()=>{alert('error')})
    }
    

4-11 React 中实现 CSS 过渡动画
//index.js
import React from  'react';
import ReactDOM from 'react-dom';
import App from './App';
//App.js
import React ,{Component, Fragment} from 'react';
import './style.css'; 

class App extends Component {
constructor(props){
    super(props);
    this.state={
        show:true
    }
    this.handleToggole=this.handleToggole.bind(this);
}
render(){
    return(
    	<Fragment>
        	<div className={this.state.show? 'show' : 'hide'}>hello</div>
			<button onClick={this.handleToggole}>toggle</button>
    	</Fragment>
	)
}
handleToggole(){
    this.setState({
        show: this.state.show ? false : true
    })
}

}
export default App;
/*style.css*/
.show{
    opacity:1;
    transition:all 1s ease-in;
}
.hide{
    opacity:0;
    transition:all 1s ease-in;
}

4-12 React 中使用 CSS 动画效果
//index.js
import React from  'react';
import ReactDOM from 'react-dom';
import App from './App';
//App.js
import React ,{Component, Fragment} from 'react';
import './style.css'; 

class App extends Component {
constructor(props){
    super(props);
    this.state={
        show:true
    }
    this.handleToggole=this.handleToggole.bind(this);
}
render(){
    return(
    	<Fragment>
        	<div className={this.state.show? 'show' : 'hide'}>hello</div>
			<button onClick={this.handleToggole}>toggle</button>
    	</Fragment>
	)
}
handleToggole(){
    this.setState({
        show: this.state.show ? false : true
    })
}

}
export default App;
/*style.css*/
.show{
     transition:show-item 2s ease-in forwards;
     /*forwards 可以让动画结束之后,保持最后一帧的样式*/
}
.hide{
    transition:hide-item 2s ease-in forwards;
    /*forwards 可以让动画结束之后,保持最后一帧的样式*/
}
@keyframes show-item{
    0%{
        opacity:1;
        color:red;
    }
    50%{
        opacity:0.5;
        color:green;
    }
    100%{
        opacity:1;
        color:blue;
    }
}
@keyframes hide-item{
    0%{
        opacity:1;
        color:red;
    }
    50%{
        opacity:0.5;
        color:green;
    }
    100%{
        opacity:0;
        color:blue;
    }
}

4-13 使用 react-transition-group 实现动画(1)
4-14 使用 react-transition-group 的使用(2)


第5章 Redux入门

本章主要讲解Redux产生背景,组成内容以及使用方式,通过实例带大家上手Redux数据管理框架的使用。

5-1 Redux 概念简述
三大原则
    1. 单一数据源
         整个应用的 state 被储存在一棵 object tree 中,
         并且这个 object tree 只存在于唯一一个 store 中。
    2.State 是只读的
            唯一改变 state 的方法就是触发 action,
            action 是一个用于描述已发生事件的普通对象。
    3.使用纯函数来执行修改
        为了描述 action 如何改变 state tree ,你需要编写 reducers。       
            
            
            
Readx=Reducer+Flux
5-2 Redux 的工作流程
5-3 使用 Antd 实现 TodoList 页面布局
5-4 创建 redux 中的 store
5-5 Action 和 Reducer 的编写
5-6 使用 Redux 完成 TodoList 删除功能
5-7 ActionTypes 的拆分
5-8 使用 actionCreator 统一创建 action
5-9 Redux 知识点复习补充

第6章 Redux进阶

本章主要讲解UI组件与容器组件基础,如何使用redux-thunk,redux-saga等Redux中间件,以及react-redux的使用方式。

6-1 UI组件和容器组件
6-2 无状态组件
6-3 Redux 中发送异步请求获取数据
6-4 使用Redux-thunk 中间件实现ajax数据请求
6-5 什么是Redux的中间件
6-6 Redux-saga中间件入门(1)
6-7 Redux-saga中间件入门(2)
6-8 如何使用 React-redux(1)
6-9 如何使用 React-redux(2)
6-10 使用React-redux完成TodoList功能

第7章 项目实战:Header组件开发

本章讲解项目中公用Header组件的开发,包含动画效果实现,iconfont,immutable.js,styled-components的使用以及异步数据的获取。

7-1 项目目录搭建,Styled-Components 与 Reset.css 的结合使用
7-2 使用 styled-components 完成 Header 组件布局(1)
7-3 使用 styled-components 完成 Header 组件布局(2)
7-4 使用 iconfont 嵌入头部图标
7-5 搜索框动画效果实现
7-6 使用 React-Redux 进行应用数据的管理
7-7 使用 combineReducers 完成对数据的拆分管理
7-8 actionCreators 与 constants 的拆分
7-9 使用 Immutable.js 来管理store中的数据
7-10 使用 redux-immutable 统一数据格式
7-11 热门搜索样式布局
7-12 Ajax获取推荐数据
7-13 代码优化微调
7-14 热门搜索换页功能实现
7-15 换页旋转动画效果的实现
7-16 避免无意义的请求发送,提升组件性能

第8章 项目实战:首页开发

本章将带大家完成项目首页的开发,课程能容包含react-router4的使用,组件及reducer的拆分设计,首页部分的核心功能包含列表显示,加载更多,返回顶部等。

8-1 什么是路由,如何在React中使用路由功能
8-2 首页组件的拆分
8-3 首页专题区域布局及reducer的设计
8-4 首页文章列表制作
8-5 首页推荐部分代码编写
8-6 首页异步数据获取
8-7 异步操作代码拆分优化
8-8 实现加载更多功能
8-9 返回顶部功能实现
8-10 首页性能优化及路由跳转

第9章 项目实战:详情页面和登录功能开发

本章将完成详情页面的开发,过程中将完整介绍react-router跨页面传值的方法及登陆鉴权的实现思路。同时我们将给大家介绍异步组件和路由withRouter方法的使用方式。

9-1 详情页面布局
9-2 使用redux管理详情页面数据
9-3 异步获取数据
9-4 页面路由参数的传递
9-5 登陆页面布局
9-6 登陆功能实现
9-7 登陆鉴权及代码优化
9-8 异步组件及withRouter路由方法的使用

第10章 课程总结

本章将给大家介绍项目的上线流程,React版本升级对本项目的影响,并带大家进行整个课程的知识点回顾。

10-1 项目上线流程
10-2 React 版本升级说明
10-3 课程总结
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值