React基础
官网
1) 英文官网: https://reactjs.org/
2) 中文官网: doc.react-china.org/
介绍描述
1) 用于构建用户界面的 JavaScript 库(只关注于View)
2) 由Facebook开源
React的特点
1) Declarative(声明式编码)
2) Component-Based(组件化编码)
3) Learn Once, Write Anywhere(支持客户端与服务器渲染)
4) 高效
5) 单向数据流
React高效的原因
1) 虚拟(virtual)DOM, 不总是直接操作DOM
2) DOM Diff算法, 最小化页面重绘
React的基本使用
注意: 此时只是测试语法使用, 并不是真实项目开发使用
效果
相关js库
1) react.js: React的核心库
2) react-dom.js: 提供操作DOM的react扩展库
3) babel.min.js: 解析JSX语法代码转为纯JS语法代码的库
在页面中导入js
编码
<**script** **type=** **"text/babel"** >
*//* *必须声明* *babel** **//*
*创建虚拟* *DOM* *元素** ***
**const** ***vDom*** = <**h1**>Hello React</**h1**>
*//* *千万不要加引号*
*//* *渲染虚拟* *DOM* *到页面真实* *DOM* *容器中** *****ReactDOM**.render(***vDom***, **document**.getElementById( **'test'** )) </**script**>
虚拟DOM
1) React提供了一些API来创建一种 特别 的一般js对象
a. var element = React.createElement('h1', {id:'myTitle'},'hello')
b. 上面创建的就是一个简单的虚拟DOM对象
2) 虚拟DOM对象最终都会被React转换为真实的DOM
3) 我们编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界面
JSX
1) 全称: JavaScript XML
2) react定义的一种类似于XML的JS扩展语法: XML+JS
3) 作用: 用来创建react虚拟DOM(元素)对象
var ele = <h1>Hello JSX!</h1>
b. 注意1: 它不是字符串, 也不是HTML/XML标签
c. 注意2: 它最终产生的就是一个JS对象
4) 标签名任意: HTML标签或其它标签
5) 标签属性任意: HTML标签属性或其它
6) 基本语法规则
a. 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
b. 遇到以 { 开头的代码,以JS语法解析: 标签中的js代码必须用{ }包含
7) babel.js的作用
a. 浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
b. 只要用了JSX,都要加上type="text/babel", 声明需要babel来处理
React面向组件编程
自定义组件
注意
1) 组件名必须首字母大写
2) 虚拟DOM元素只能有一个根元素
3) 虚拟DOM元素必须有结束标签
render()渲染组件标签的基本流程
1) React内部会创建组件实例对象
2) 得到包含的虚拟DOM并解析为真实DOM
3) 插入到指定的页面元素内部
组件三大属性1: state
1) state是组件对象最重要的属性, 值是对象(可以包含多个数据)
2) 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
1) 更新状态---->组件界面更新
this.setState({
stateProp1 : value1,
})
组件三大属性2: props
1) 通过标签属性从组件外向组件内传递变化的数据
2) 注意: 组件内部不要修改props数据
1) 内部读取某个属性值
this.props.propertyName
2) 对props中的属性值进行类型限制和必要性限制
Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number.isRequired
}
3) 扩展属性: 将对象的所有属性通过props传递
<Person {...person}/>
4) 默认属性值
Person.defaultProps = {
name: 'Mary'
}
5) 组件类的构造函数
constructor (props) {
super(props)
console.log(props) // 查看所有属性
}
refs与事件处理
1) 组件内的标签都可以定义ref属性来标识自己
a. <input type="text" ref={input => this.msgInput = input}/>
b. 回调函数在组件初始化渲染完或卸载时自动调用
2) 在组件中可以通过this.msgInput来得到对应的真实DOM元素
3) 作用: 通过ref获取组件内容特定标签对象, 进行读取其相关数据
事件处理
1) 通过onXxx属性指定组件的事件处理函数(注意大小写)
a. React使用的是自定义(合成)事件, 而不是使用的原生DOM事件
b. React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)
2) 通过event.target得到发生事件的DOM元素对象
*handleFocus(event) {***
*event.target //返回input对象***
}
注意
1) 组件内置的方法中的this为组件对象
2) 在组件类中自定义的方法中this为null
a. 强制绑定this: 通过函数对象的bind()
b. 箭头函数(ES6模块化编码时才能使用)
受控组件和不受控组件的使用场景
受控组件
在 HTML 中,表单元素(如<input>、 <textarea> 和 <select>)通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。
我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
非受控组件
非受控组件,而不是为每个状态更新都编写数据处理函数,你可以 使用 ref 来从 DOM 节点中获取表单数据
ref定义:
<input type="text" ref={this.input} />
this.input = React.createRef();
使用:
handleSubmit(event) {
alert('A name was submitted: ' + this.input.current.value);
}
如果您的表单在UI反馈方面非常简单,则不受 refs 控制完全没问题。
包含表单的组件分类
- 受控组件: 表单项输入数据能自动收集成状态
- 非受控组件: 需要时才手动读取表单输入框中的数据
生命周期流程图
虚拟DOM与DOM Diff算法
react ajax
1) jQuery: 比较重, 如果需要另外引入不建议使用
2) axios: 轻量级, 建议使用
a. 封装XmlHttpRequest对象的ajax
b. promise风格
c. 可以用在浏览器端和node服务器端
3) fetch: 原生函数, 但老版本浏览器不支持
a. 不再使用XmlHttpRequest对象提交ajax请求
b. 为了兼容低版本的浏览器, 可以引入兼容库fetch.js
axios
1) GET请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
axios.get('/user', {
params: {
ID: 12345 }
})
.then(function (response) {
console.log(response); })
.catch(function (error) {
console.log(error); });
2) POST请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
组件间通信
方式一: 通过props传递****
1) 共同的数据放在父组件上, 特有的数据放在自己组件内部(state)
2) 通过props可以传递一般数据和函数数据, 只能一层一层传递
3) 一般数据-->父组件传递数据给子组件-->子组件读取数据
4) 函数数据-->子组件传递数据给父组件-->子组件调用函数
方式二: 使用消息订阅(subscribe)-发布(publish)机制****
1) 工具库: PubSubJS
2) 下载: npm install pubsub-js --save
3) 使用:
import PubSub from 'pubsub-js' //引入
PubSub.subscribe('delete', function(data){ }); //订阅
PubSub.publish('delete', data) //发布消息
learn_from_bili_goToGuigu## 1.1. React的基本认识
官网
1) 英文官网: https://reactjs.org/
2) 中文官网: doc.react-china.org/
介绍描述
1) 用于构建用户界面的 JavaScript 库(只关注于View)
2) 由Facebook开源
React的特点
1) Declarative(声明式编码)
2) Component-Based(组件化编码)
3) Learn Once, Write Anywhere(支持客户端与服务器渲染)
4) 高效
5) 单向数据流
React高效的原因
1) 虚拟(virtual)DOM, 不总是直接操作DOM
2) DOM Diff算法, 最小化页面重绘
React的基本使用
注意: 此时只是测试语法使用, 并不是真实项目开发使用
效果
相关js库
1) react.js: React的核心库
2) react-dom.js: 提供操作DOM的react扩展库
3) babel.min.js: 解析JSX语法代码转为纯JS语法代码的库
在页面中导入js
编码
<**script** **type=** **"text/babel"** >
*//* *必须声明* *babel** **//*
*创建虚拟* *DOM* *元素** ***
**const** ***vDom*** = <**h1**>Hello React</**h1**>
*//* *千万不要加引号*
*//* *渲染虚拟* *DOM* *到页面真实* *DOM* *容器中** *****ReactDOM**.render(***vDom***, **document**.getElementById( **'test'** )) </**script**>
虚拟DOM
1) React提供了一些API来创建一种 特别 的一般js对象
a. var element = React.createElement('h1', {id:'myTitle'},'hello')
b. 上面创建的就是一个简单的虚拟DOM对象
2) 虚拟DOM对象最终都会被React转换为真实的DOM
3) 我们编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界面
JSX
1) 全称: JavaScript XML
2) react定义的一种类似于XML的JS扩展语法: XML+JS
3) 作用: 用来创建react虚拟DOM(元素)对象
var ele = <h1>Hello JSX!</h1>
b. 注意1: 它不是字符串, 也不是HTML/XML标签
c. 注意2: 它最终产生的就是一个JS对象
4) 标签名任意: HTML标签或其它标签
5) 标签属性任意: HTML标签属性或其它
6) 基本语法规则
a. 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
b. 遇到以 { 开头的代码,以JS语法解析: 标签中的js代码必须用{ }包含
7) babel.js的作用
a. 浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
b. 只要用了JSX,都要加上type="text/babel", 声明需要babel来处理
React面向组件编程
自定义组件
注意
1) 组件名必须首字母大写
2) 虚拟DOM元素只能有一个根元素
3) 虚拟DOM元素必须有结束标签
render()渲染组件标签的基本流程
1) React内部会创建组件实例对象
2) 得到包含的虚拟DOM并解析为真实DOM
3) 插入到指定的页面元素内部
组件三大属性1: state
1) state是组件对象最重要的属性, 值是对象(可以包含多个数据)
2) 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
1) 更新状态---->组件界面更新
this.setState({
stateProp1 : value1,
})
组件三大属性2: props
1) 通过标签属性从组件外向组件内传递变化的数据
2) 注意: 组件内部不要修改props数据
1) 内部读取某个属性值
this.props.propertyName
2) 对props中的属性值进行类型限制和必要性限制
Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number.isRequired
}
3) 扩展属性: 将对象的所有属性通过props传递
<Person {...person}/>
4) 默认属性值
Person.defaultProps = {
name: 'Mary'
}
5) 组件类的构造函数
constructor (props) {
super(props)
console.log(props) // 查看所有属性
}
refs与事件处理
1) 组件内的标签都可以定义ref属性来标识自己
a. <input type="text" ref={input => this.msgInput = input}/>
b. 回调函数在组件初始化渲染完或卸载时自动调用
2) 在组件中可以通过this.msgInput来得到对应的真实DOM元素
3) 作用: 通过ref获取组件内容特定标签对象, 进行读取其相关数据
事件处理
1) 通过onXxx属性指定组件的事件处理函数(注意大小写)
a. React使用的是自定义(合成)事件, 而不是使用的原生DOM事件
b. React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)
2) 通过event.target得到发生事件的DOM元素对象
*handleFocus(event) {***
*event.target //返回input对象***
}
注意
1) 组件内置的方法中的this为组件对象
2) 在组件类中自定义的方法中this为null
a. 强制绑定this: 通过函数对象的bind()
b. 箭头函数(ES6模块化编码时才能使用)
受控组件和不受控组件的使用场景
受控组件
在 HTML 中,表单元素(如<input>、 <textarea> 和 <select>)通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。
我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
非受控组件
非受控组件,而不是为每个状态更新都编写数据处理函数,你可以 使用 ref 来从 DOM 节点中获取表单数据
ref定义:
<input type="text" ref={this.input} />
this.input = React.createRef();
使用:
handleSubmit(event) {
alert('A name was submitted: ' + this.input.current.value);
}
如果您的表单在UI反馈方面非常简单,则不受 refs 控制完全没问题。
包含表单的组件分类
- 受控组件: 表单项输入数据能自动收集成状态
- 非受控组件: 需要时才手动读取表单输入框中的数据
生命周期流程图
虚拟DOM与DOM Diff算法
react ajax
1) jQuery: 比较重, 如果需要另外引入不建议使用
2) axios: 轻量级, 建议使用
a. 封装XmlHttpRequest对象的ajax
b. promise风格
c. 可以用在浏览器端和node服务器端
3) fetch: 原生函数, 但老版本浏览器不支持
a. 不再使用XmlHttpRequest对象提交ajax请求
b. 为了兼容低版本的浏览器, 可以引入兼容库fetch.js
axios
1) GET请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
axios.get('/user', {
params: {
ID: 12345 }
})
.then(function (response) {
console.log(response); })
.catch(function (error) {
console.log(error); });
2) POST请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
组件间通信
方式一: 通过props传递****
1) 共同的数据放在父组件上, 特有的数据放在自己组件内部(state)
2) 通过props可以传递一般数据和函数数据, 只能一层一层传递
3) 一般数据-->父组件传递数据给子组件-->子组件读取数据
4) 函数数据-->子组件传递数据给父组件-->子组件调用函数
方式二: 使用消息订阅(subscribe)-发布(publish)机制****
1) 工具库: PubSubJS
2) 下载: npm install pubsub-js --save
3) 使用:
import PubSub from 'pubsub-js' //引入
PubSub.subscribe('delete', function(data){ }); //订阅
PubSub.publish('delete', data) //发布消息
ES6常用新语法
1) 定义常量/变量: const/let
2) 解构赋值: let {a, b} = this.props import {aa} from 'xxx'
3) 对象的简洁表达: {a, b}
4) 箭头函数:
a. 常用场景
-
组件的自定义方法: xxx = () => {}
-
参数匿名函数
b. 优点:
-
简洁
-
没有自己的this,使用引用this查找的是外部this
5) 扩展(三点)运算符: 拆解对象(const MyProps = {}, <Xxx {...MyProps}>)
6) 类: class/extends/constructor/super
7) ES6模块化: export default | import
react-router4.0
1) react的一个插件库
2) 专门用来实现一个SPA应用
3) 基于react的项目基本都会用到此库
SPA的理解*
1) 单页Web应用(single page web application,SPA)
2) 整个应用只有一个完整的页面
3) 点击页面中的链接不会刷新页面, 本身也不会向服务器发请求
4) 当点击路由链接时, 只会做页面的局部更新
5) 数据都需要通过ajax请求获取, 并在前端异步展现
路由的理解*
1) 什么是路由?
a. 一个路由就是一个映射关系(key:value)
b. key为路由路径, value可能是function/component
2) 路由分类
a. 后台路由: node服务器端路由, value是function, 用来处理客户端提交的请求并返回一个响应数据
b. 前台路由: 浏览器端路由, value是component, 当请求的是路由path时, 浏览器端前没有发送http请求, 但界面会更新显示对应的组件
3) 后台路由
a. 注册路由: router.get(path, function(req, res))
b. 当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
4) 前端路由
a. 注册路由:
b. 当浏览器的hash变为#about时, 当前路由组件就会变为About组件
前端路由的实现
1) history库
a. 网址: <https://github.com/ReactTraining/history>
b. 管理浏览器会话历史(history)的工具库
c. 包装的是原生BOM中window.history和window.location.hash
2) history API
a. History.createBrowserHistory(): 得到封装window.history的管理对象
b. History.createHashHistory(): 得到封装window.location.hash的管理对象
c. history.push(): 添加一个新的历史记录
d. history.replace(): 用一个新的历史记录替换当前的记录
e. history.goBack(): 回退到上一个历史记录
f. history.goForword(): 前进到下一个历史记录
g. history.listen(function(location){}): 监视历史记录的变化
redux### 学习文档****
1) 英文文档: redux.js.org/
2) 中文文档: www.redux.org.cn/
3) Github: github.com/reactjs/red…
redux是什么?
1) redux是一个独立专门用于做状态管理的JS库(不是react插件库)
2) 它可以用在react, angular, vue等项目中, 但基本与react配合使用
3) 作用: 集中式管理react应用中多个组件共享的状态
redux工作流程
什么情况下需要使用redux
1) 总体原则: 能不用就不用, 如果不用比较吃力才考虑使用
2) 某个组件的状态,需要共享
3) 某个状态需要在任何地方都可以拿到
4) 一个组件需要改变全局状态
5) 一个组件需要改变另一个组件的状态
redux的核心API
createStore()
1) 作用:
创建包含指定reducer的store对象
2) 编码:
import {createStore} from 'redux'
import counter from './reducers/counter'
const store = createStore(counter)
store对象
1) 作用:
redux库最核心的管理对象
2) 它内部维护着:
state
reducer
3) 核心方法:
getState()
dispatch(action)
subscribe(listener)
4) 编码:
store.getState()
store.dispatch({type:'INCREMENT', number})
store.subscribe(render)
applyMiddleware()******
1) 作用:
应用上基于redux的中间件(插件库)
2) 编码:
import {createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk' // redux异步中间件
const store = createStore(
counter,
applyMiddleware(thunk) // 应用上异步中间件
)
combineReducers()******
1) 作用:
合并多个reducer函数
2) 编码:
export default combineReducers({
user,
chatUser,
chat
})
redux的三个核心概念
action
1) 标识要执行行为的对象
2) 包含2个方面的属性
a. type: 标识属性, 值为字符串, 唯一, 必要属性
b. xxx: 数据属性, 值类型任意, 可选属性
3) 例子:
const action = {
type: 'INCREMENT',
data: 2
}
4) Action Creator(创建Action的工厂函数)
const increment = (number) => ({type: 'INCREMENT', data: number})
reducer
1) 根据老的state和action, 产生新的state的纯函数
2) 样例
export default function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + action.data
case 'DECREMENT':
return state - action.data
default:
return state
}
}
3) 注意
a. 返回一个新的状态
b. 不要修改原来的状态
store
1) 将state,action与reducer联系在一起的对象
2) 如何得到此对象?
import {createStore} from 'redux'
import reducer from './reducers'
const store = createStore(reducer)
3) 此对象的功能?
getState(): 得到state
dispatch(action): 分发action, 触发reducer调用, 产生新的state
subscribe(listener): 注册监听, 当产生了新的state时, 自动调用
纯函数和高阶函数
纯函数
1) 一类特别的函数: 只要是同样的输入,必定得到同样的输出
2) 必须遵守以下一些约束
a. 不得改写参数
b. 不能调用系统 I/O 的API
c. 能调用Date.now()或者Math.random()等不纯的方法
3) reducer函数必须是一个纯函数
高阶函数
4) 理解: 一类特别的函数
a. 情况1: 参数是函数
b. 情况2: 返回是函数
5) 常见的高阶函数:
a. 定时器设置函数
b. 数组的map()/filter()/reduce()/find()/bind()
c. react-redux中的connect函数
6) 作用:
a. 能实现更加动态, 更加可扩展的功能