React:React组件化入门,state、props、refs开发,脚手架评论管理GitHub用户搜索功能,组件式通信,React-rounter,ReactUI组件AntDesign,Redux

1. React入门

## 1.1. React基本认识
## 1.2. React基本使用
## 1.3. JSX的理解和使用
## 1.4. 模块与模块化, 组件与组件化的理解

2. React组件化编程

## 2.1. 组件的定义与使用
## 2.2. 组件的3大属性: state, props, refs
## 2.3. 组件中的事件处理
## 2.4. 组件的组合使用
## 2.5. 组件收集表单数据
## 2.6. 组件的生命周期
## 2.7. 虚拟DOM与DOM diff算法
## 2.8. 命令式编程与声明式编程

1. React入门

1.1. React的基本认识

1). Facebook开源的一个js库
2). 一个用来动态构建用户界面的js库
3). React的特点
	Declarative(声明式编码)
	Component-Based(组件化编码)
	Learn Once, Write Anywhere(支持客户端与服务器渲染)
	高效
	单向数据流
4). React高效的原因
	虚拟(virtual)DOM, 不总是直接操作DOM(批量更新, 减少更新的次数) 
	高效的DOM Diff算法, 最小化页面重绘(减小页面更新的区域)

1.2. React的基本使用

1). 导入相关js库文件(react.js, react-dom.js, babel.min.js)
2). 编码:
	

1.3. JSX的理解和使用

1). 理解
	* 全称: JavaScript XML
	* react定义的一种类似于XML的JS扩展语法: XML+JS
	* 作用: 用来创建react虚拟DOM(元素)对象
2). 编码相关
	* js中直接可以套标签, 但标签要套js需要放在{}中
	* 在解析显示js数组时, 会自动遍历显示
	* 把数据的数组转换为标签的数组: 
		var liArr = dataArr.map(function(item, index){
			return 
  • {item}
  • }) 3). 注意: * 标签必须有结束 * 标签的class属性必须改为className属性 * 标签的style属性值必须为: {{color:'red', width:12}}

    1.4. 几个重要概念理解

    1). 模块与组件

    1. 模块:
      	理解: 向外提供特定功能的js程序, 一般就是一个js文件
      	为什么: js代码更多更复杂
      	作用: 复用js, 简化js的编写, 提高js运行效率
    2. 组件: 
    	理解: 用来实现特定功能效果的代码集合(html/css/js)
      	为什么: 一个界面的功能太复杂了
      	作用: 复用编码, 简化项目界面编码, 提高运行效率
    

    2). 模块化与组件化

    1. 模块化:
    	当应用的js都以模块来编写的, 这个应用就是一个模块化的应用
    2. 组件化:
    	当应用是以多组件的方式实现功能, 这上应用就是一个组件化的应用
    

    2. react组件化开发

    2.1. 基本理解和使用

    1). 自定义的标签: 组件类(函数)/标签
    2). 创建组件类
    	//方式1: 无状态函数(简单组件, 推荐使用)
    	function MyComponent1(props) {
    		return 

    自定义组件标题11111

    } //方式2: ES6类语法(复杂组件, 推荐使用) class MyComponent3 extends React.Component { render () { return

    自定义组件标题33333

    } } 3). 渲染组件标签 ReactDOM.render(, cotainerEle) 4). ReactDOM.render()渲染组件标签的基本流程 React内部会创建组件实例对象/调用组件函数, 得到虚拟DOM对象 将虚拟DOM并解析为真实DOM 插入到指定的页面元素内部

    2.2. 组件的3大属性: state

    1. 组件被称为"状态机", 页面的显示是根据组件的state属性的数据来显示
    2. 初始化指定:
        constructor() {
          super()
          this.state = {
            stateName1 : stateValue1,
            stateName2 : stateValue2
          }
        }
    3. 读取显示: 
        this.state.stateName1
    4. 更新状态-->更新界面 : 
        this.setState({stateName1 : newValue})
    

    2.2. 组件的3大属性: props

    所有组件标签的属性的集合对象
    给标签指定属性, 保存外部数据(可能是一个function)
    在组件内部读取属性: this.props.propertyName
    作用: 从目标组件外部向组件内部传递数据
    对props中的属性值进行类型限制和必要性限制
    	Person.propTypes = {
    		name: React.PropTypes.string.isRequired,
    		age: React.PropTypes.number.isRequired
    	}
    扩展属性: 将对象的所有属性通过props传递
        
    

    2.2. 组件的3大属性: refs

    组件内包含ref属性的标签元素的集合对象
    给操作目标标签指定ref属性, 打一个标识
    在组件内部获得标签对象: this.refs.refName(只是得到了标签元素对象)
    作用: 找到组件内部的真实dom元素对象, 进而操作它
    

    2.3. 组件中的事件处理

    1. 给标签添加属性: onXxx={this.eventHandler}
    2. 在组件中添加事件处理方法
        eventHandler(event) {
                    
        }
    3. 使自定义方法中的this为组件对象
      	在constructor()中bind(this)
      	使用箭头函数定义方法(ES6模块化编码时才能使用)
    4. 事件监听
    	绑定事件监听
    		事件名
    		回调函数
    	触发事件
    		用户对对应的界面做对应的操作
    		编码
    

    2.4. 组件的组合使用

    1)拆分组件: 拆分界面,抽取组件
    2)实现静态组件: 使用组件实现静态页面效果
    3)实现动态组件
    	① 动态显示初始化数据
    	② 交互功能(从绑定事件监听开始)
    

    2.5. 组件收集表单数据

    受控组件
    非受控组件
    

    2.6. 组件的生命周期

    1. 组件的三个生命周期状态:
    	Mount:插入真实 DOM
    	Update:被重新渲染
    	Unmount:被移出真实 DOM
    2. 生命周期流程:
    	* 第一次初始化显示: ReactDOM.render(, containDom)
    		constructor()
    		componentWillMount() : 将要插入回调
    		render() : 用于插入虚拟DOM回调
    		componentDidMount() : 已经插入回调
    	* 每次更新state: this.setState({})
    	    componentWillReceiveProps(): 接收父组件新的属性
    	    componentWillUpdate() : 将要更新回调
    	    render() : 更新(重新渲染)
    	    componentDidUpdate() : 已经更新回调
    	* 删除组件: ReactDOM.unmountComponentAtNode(div): 移除组件
    		componentWillUnmount() : 组件将要被移除回调
    3. 常用的方法
    	render(): 必须重写, 返回一个自定义的虚拟DOM
      	constructor(): 初始化状态, 绑定this(可以箭头函数代替)
      	componentDidMount() : 只执行一次, 已经在dom树中, 适合启动/设置一些监听
    

    2.7. 虚拟DOM与DOM diff算法

    1). 虚拟DOM是什么?

    一个虚拟DOM(元素)是一个一般的js对象, 准确的说是一个对象树(倒立的)
    虚拟DOM保存了真实DOM的层次关系和一些基本属性,与真实DOM一一对应
    如果只是更新虚拟DOM, 页面是不会重绘的
    

    2). Virtual DOM 算法的基本步骤

    用JS对象树表示DOM树的结构;然后用这个树构建一个真正的DOM树插到文档当中
    当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
    把差异应用到真实DOM树上,视图就更新了
    

    3). 进一步理解

    Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。
    可以类比 CPU 和硬盘,既然硬盘这么慢,我们就在它们之间加个缓存:既然 DOM 这么慢,我们就在它们 JS 和 DOM 之间加个缓存。CPU(JS)只操作内存(Virtual DOM),最后的时候再把变更写入硬盘(DOM)。
    

    2.8. 命令式编程与声明式编程

    声明式编程
    	只关注做什么, 而不关注怎么做(流程),  类似于填空题
    命令式编程
    	要关注做什么和怎么做(流程), 类似于问答题
    
    var arr = [1, 3, 5, 7]
    // 需求: 得到一个新的数组, 数组中每个元素都比arr中对应的元素大10: [11, 13, 15, 17]
    // 命令式编程
    var arr2 = []
    for(var i =0;i

    1. 使用React脚手架创建一个React应用

    1). react脚手架

    1. xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
    	* 包含了所有需要的配置
    	* 指定好了所有的依赖
    	* 可以直接安装/编译/运行一个简单效果
    2. react提供了一个专门用于创建react项目的脚手架库: create-react-app
    3. 项目的整体技术架构为: react + webpack + es6  + babel + eslint
    

    2). 创建项目并启动

    npm install -g create-react-app
    create-react-app react-app
    cd react-app
    npm start
    

    3). 使用脚手架开发的项目的特点

    模块化: js是一个一个模块编写的
    组件化: 界面是由多个组件组合编写实现的
    工程化: 实现了自动构建/运行/打包的项目
    

    4). 组件化编写项目的流程

    拆分组件
    实现静态组件--->静态页面
    实现动态组件
    	动态显示初始化数据
    	交互
    

    2. app1: 实现一个评论管理功能

    1). 拆分组件:

    应用组件: App
    添加评论组件: CommentAdd
    评论项组件: CommentItem
    评论列表组件: CommentList
    

    2). 确定组件的state和props:

    App: 
    	* state: comments/array
    CommentAdd
    	* state: username/string, content/string
    	* props: add/func
    commentList
      	* props: comments/array, delete/func
    CommentItem
    	* props: comment/object, delete/func, index/number
    

    3). 编写静态组件

    拆分页面
    拆分css
    

    4). 实现动态组件

    1. 动态展示初始化数据
      * 初始化状态数据
      * 传递属性数据
    2. 响应用户操作, 更新组件界面
      * 绑定事件监听, 并处理
      * 更新state
    

    3. app2: 实现github用户搜索功能

    1). react应用中的ajax请求

    axios: 包装XMLHttpRequest对象, promise风格, 支持浏览端/node服务器端
    fetch: 浏览器内置语法, promise风格, 老浏览器不支持, 可以引入fetch.js兼容包
    

    2). 拆分组件

    App
    	* state: searchName/string
    Search
      	* props: setSearchName/func
    List
      	* props: searchName/string
      	* state: firstView/bool, loading/bool, users/array, errMsg/string
    

    3). 编写组件

    编写静态组件
    编写动态组件
    	componentWillReceiveProps(nextProps): 监视接收到新的props, 发送ajax
    	使用axios库发送ajax请求
    

    4. 组件间通信总结

    1). 方式一: 通过props传递

    共同的数据放在父组件上, 特有的数据放在自己组件内部(state)
    一般数据-->父组件传递数据给子组件-->子组件读取数据
    函数数据-->子组件传递数据给父组件-->子组件调用函数
    问题: 多层传递属性麻烦, 兄弟组件通信不方便
    

    2). 方式二: 使用消息订阅(subscribe)-发布(publish)机制: 自定义事件机制

    工具库: PubSubJS
    下载: npm install pubsub-js --save
    使用: 
      import PubSub from 'pubsub-js' //引入
      PubSub.subscribe('delete', function(msg, data){ }); //订阅
      PubSub.publish('delete', data) //发布消息
    优点: 可以支持任意关系组件之间的通信
    

    3). 事件监听理解

    1. DOM事件
    	* 绑定事件监听
    		* 事件名(类型): 只有有限的几个, 不能随便写
    		* 回调函数
    	* 用户操作触发事件(event)
    		* 事件名(类型)
    		* 数据
    2. 自定义事件
    	* 绑定事件监听
    		* 事件名(类型): 任意
    		* 回调函数: 通过形参接收数据, 在函数体处理事件
    	* 触发事件(编码)
    		* 事件名(类型): 与绑定的事件监听的事件名一致
    		* 数据: 会自动传递给回调函数
    

    5. ES6新语法总结

    定义变量/常量: const/let
    解构赋值: let {a, b} = this.props   import {aa} from 'xxx'
    对象的简洁表达: {a, b}
    箭头函数: 
    	组件的自定义方法: xxx = () => {}
    	map/filter的回调方法: (item, index) => {}
    	优点:
    		* 简洁
    		* 没有自己的this,使用引用this查找的是外部this
    扩展运算符: ...
    	拆解对象:  const MyProps = {}, 
    类: class/extends/constructor/super
    ES6模块化: export default | import
    

    6. 项目打包运行

    npm run build  //生成打包文件
    npm install -g serve  //全局下载服务器包
    serve build  //通过服务器命令运行打包项目
    访问: http://localhost:5000  //浏览器访问
    

    1. 理解react-router

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

    2. 几个重要问题

    1). SPA应用

    单页Web应用(single page web application,SPA)
    整个应用只有一个完整的页面
    点击页面中的链接不会刷新页面, 本身也不会向服务器发请求
    当点击链接时, 只会做页面的局部更新
    数据都需要通过ajax请求获取, 并在前端异步展现
    

    2). 路由

    1. 什么是路由?
    	一个路由就是一个映射关系(key:value)
    	key为路由路径, value可能是function/component
    2. 路由分类
    	后台路由: node服务器端路由, value是function, 用来处理客户端提交的请求并返回一个响应数据
    	前台路由: 浏览器端路由, value是component, 当请求的是路由path时, 浏览器端前没有发送http请求, 但界面会更新显示对应的组件 
    3. 后台路由
    	* 注册路由: router.get(path, function(req, res))
    	* 当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
    * 前端路由
    	* 注册路由: 
    	* 当浏览器的hash变为#about时, 当前路由组件就会变为About组件
    

    3). 关于url中的

    1. 理解#
    	'#'代表网页中的一个位置。其右面的字符,就是该位置的标识符
    	改变#不触发网页重载
    	改变#会改变浏览器的访问历史
    2. 操作#
    	window.location.hash读取#值
    	window.onhashchange = func 监听hash改变
    3. 学习资源: 
    	阮一峰教程: http://www.ruanyifeng.com/blog/2011/03/url_hash.html
    

    3. react-router的学习资源

    github主页: https://github.com/ReactTraining/react-router
    官网教程: https://github.com/reactjs/react-router-tutorial
    阮一峰教程: http://www.ruanyifeng.com/blog/2016/05/react_router.html
    

    4. 相关API

    1). react-router中的相关组件:

    Router: 路由器组件, 用来包含各个路由组件
    Route: 路由组件, 注册路由 
    IndexRoute: 默认子路由组件
    hashHistory: 路由的切换由URL的hash变化决定,即URL的#部分发生变化
    Link: 路由链接组件
    

    2). Router: 路由器组件

    属性:  history={hashHistory} 用来监听浏览器地址栏的变化, 并将URL解析成一个地址对象,供React Router匹配
    子组件: Route
    

    3). Route: 路由组件

    属性1: path="/xxx"  
    属性2: component={Xxx}
    根路由组件: path="/"的组件, 一般为App
    子路由组件: 子配置的组件
    

    4). IndexRoute: 默认路由

    当父路由被请求时, 默认就会请求此路由组件
    

    5). hashHistory

    用于Router组件的history属性
    作用: 为地址url生成?_k=hash, 用于内部保存对应的state
    

    6). Link: 路由链接

    属性1: to="/xxx"
    属性2: activeClassName="active"
    

    5. react-router的基本使用

    1). 下载

    npm install react-router --save
    

    2). 定义各个路由组件

    1. About.js
      import React from 'react'
      function About() {
        return 
    About组件内容
    } export default About 2. Home.js import React from 'react' function Home() { return
    Home组件内容2
    } export default Home 3. Repos.js import React, {Component} from 'react' export default class Repos extends Component { render() { return (
    Repos组件
    ) } } 4. App.js import React, {Component} from 'react' import {Link} from 'react-router' export default class App extends Component { render() { return (

    Hello, React Router!

    • About2
    • Repos2
    {this.props.children}
    ) } }

    3). index.js: 注册路由, 渲染路由器标签

    import React from 'react'
    import {render} from 'react-dom'
    import {Router, Route, IndexRoute, hashHistory} from 'react-router'
    import App from './modules/App'
    import About from './modules/About'
    import Repos from './modules/Repos'
    import Home from './modules/Home'
    
    render((
      
        
          
          
          
        
      
    ), document.getElementById('app'))
    

    3). 主页面: index.html

    
    

    6. 向路由组件传递请求参数

    1). repo.js: repos组件下的分路由组件

    import React from 'react'
    export default function ({params}) {
      let {username, repoName} = params
      return (
        
    用户名:{username}, 仓库名:{repoName}
    ) }

    2). repos.js

    import React from 'react'
    import NavLink from './NavLink'
    
    export default class Repos extends React.Component {
    
      constructor(props) {
        super(props);
        this.state = {
          repos: [
            {username: 'faceback', repoName: 'react'},
            {username: 'faceback', repoName: 'react-router'},
            {username: 'Angular', repoName: 'angular'},
            {username: 'Angular', repoName: 'angular-cli'}
          ]
        };
        this.handleSubmit = this.handleSubmit.bind(this)
      }
    
      handleSubmit () {
    
        const repos = this.state.repos
        repos.push({
          username: this.refs.username.value,
          repoName: this.refs.repoName.value
        })
        this.setState({repos})
        this.refs.username.value = ''
        this.refs.repoName.value = ''
      }
    
      render() {
        return (
          

    Repos

      { this.state.repos.map((repo, index) => { const to = `/repos/${repo.username}/${repo.repoName}` return (
    • {repo.repoName}
    • ) }) }
    • / {' '} {' '}
    {this.props.children}
    ); } }

    3). index.js: 配置路由

    
      
    
    

    7. 优化Link组件

    1). NavLink.js

    import React from 'react'
    import {Link} from 'react-router'
    export default function NavLink(props) {
      return 
    }
    

    2). Repos.js

    {repo.repoName}
    

    1. 最流行的开源React UI组件库

    1). material-ui(国外)

    官网: http://www.material-ui.com/#/
    github: https://github.com/callemall/material-ui
    

    2). ant-design(国内蚂蚁金服)

    官网: https://ant.design/
    github: https://github.com/ant-design/ant-design/
    

    2. ant-design使用入门

    1). 使用create-react-app搭建react开发环境

    npm install create-react-app -g
    create-react-app antd-demo
    cd antd-demo
    npm start
    

    2). 搭建antd的基本开发环境

    1. 下载
    	npm install [email protected] --save
    2. src/App.js
        import React, { Component } from 'react';
        import { Button } from 'antd';
        import './App.css';
        
        class App extends Component {
          render() {
            return (
              
    ); } } export default App; 3. src/App.css @import '~antd/dist/antd.css'; .app { text-align: center; }

    3). 实现按需加载(组件js/组件css)

    1. 使用eject命令将所有内建的配置暴露出来
    	npm run eject
    2. 下载babel-plugin-import(用于按需加载组件代码和样式的 babel 插件)
    	npm install babel-plugin-import --save-dev
    3. 修改配置: config/webpack.config.dev.js
        // Process JS with Babel.
        {
          test: /\.(js|jsx)$/,
          include: paths.appSrc,
          loader: 'babel',
          options: {
          +   plugins: [
          +     ['import', { libraryName: 'antd', style: 'css' }],
          +   ],
              // This is a feature of `babel-loader` for webpack (not Babel itself).
              // It enables caching results in ./node_modules/.cache/babel-loader/
              // directory for faster rebuilds.
              cacheDirectory: true
            }
    	 },
    4. 去除引入全量样式的语句: src/App.css
        @import '~antd/dist/antd.css' 
    

    0. redux要点

    1. redux理解
    2. redux相关API
    3. redux核心概念(3个)
    4. redux工作流程
    5. 使用redux及相关库编码
    

    1. redux理解

    什么?: redux是专门做状态管理的独立第3方库, 不是react插件
    作用?: 对应用中状态进行集中式的管理(写/读)
    开发: 与react-redux, redux-thunk等插件配合使用
    

    2. redux相关API

    redux中包含: createStore(), applyMiddleware(), combineReducers()
    store对象: getState(), dispatch(), subscribe()
    react-redux: , connect()()
    

    3. redux核心概念(3个)

    action: 
    	默认是对象(同步action), {type: 'xxx', data: value}, 需要通过对应的actionCreator产生, 
    	它的值也可以是函数(异步action), 需要引入redux-thunk才可以
    reducer
    	根据老的state和指定的action, 返回一个新的state
    	不能修改老的state
    store
    	redux最核心的管理对象
    	内部管理着: state和reducer
    	提供方法: getState(), dispatch(action), subscribe(listener)
    

    4. redux工作流程

    5. 使用redux及相关库编码

    需要引入的库: 
    	redux
    	react-redux
    	redux-thunk
    	redux-devtools-extension(这个只在开发时需要)
    redux文件夹: 
    	action-types.js
    	actions.js
    	reducers.js
    	store.js
    组件分2类: 
    	ui组件(components): 不使用redux相关PAI
    	容器组件(containers): 使用redux相关API
    

    开发: 与react-redux, redux-thunk等插件配合使用

    
    # 2. redux相关API
    
    

    redux中包含: createStore(), applyMiddleware(), combineReducers()
    store对象: getState(), dispatch(), subscribe()
    react-redux: , connect()()

    
    # 3. redux核心概念(3个)
    
    

    action:
    默认是对象(同步action), {type: ‘xxx’, data: value}, 需要通过对应的actionCreator产生,
    它的值也可以是函数(异步action), 需要引入redux-thunk才可以
    reducer
    根据老的state和指定的action, 返回一个新的state
    不能修改老的state
    store
    redux最核心的管理对象
    内部管理着: state和reducer
    提供方法: getState(), dispatch(action), subscribe(listener)

    
    # 4. redux工作流程
    
    [外链图片转存中...(img-NO6sCqIC-1595170262174)]
    [外链图片转存中...(img-EAraVevm-1595170262177)]
    		
    
    # 5. 使用redux及相关库编码
    
    

    需要引入的库:
    redux
    react-redux
    redux-thunk
    redux-devtools-extension(这个只在开发时需要)
    redux文件夹:
    action-types.js
    actions.js
    reducers.js
    store.js
    组件分2类:
    ui组件(components): 不使用redux相关PAI
    容器组件(containers): 使用redux相关API
    ``

    你可能感兴趣的:(前端,#,JavaWeb)