- JSX: javascript xml。是javascript的一种拓展语法。可以在js代码中编写更像xml写法的代码。它不能直接在浏览器中执行,需要经过转换器将jsx转换成js。本质上jsx是React.createElement()的语法糖。
2.转译工具:Babel来转换。早期提供浏览器当中的转译脚本,browser.js
3.react组件生命周期。
- react + redux数据流管理。
redux动机:状态管理,预测与追踪状态的变化。
三大特性:
1.单一数据源:整个应用state都存储在一个js对象中。--Store
2.state是只读的,只可以通过action修改。
3.使用纯函数执行修改。相同输入,永远会得到相同的输出。
redux#组成:Action、Reducer、Store
Action:Store中数据的唯一来源,描述整个应用中的所有行为。
一个Action创建有3点
1.定义类型(type)
2. 定义内容
3. 定义Action Creator(Action生成函数)
Reducer: ( Action:负责dispatch对应的typeAction?---- reducer:根据对应的typeAction直接更改store?-----store )
- Action定义了要执行的操作,但没有规定如何更改state,而Reducer但职责定义整个应用的状态如何更改。它是一个纯函数。
- combineReducers(Object): 由于应用会比较复杂,reducer可以拆分多个单独的函数,单独负责管理state的一部分代码。最后用combineReducers(Object)方法连接
import { combineReducers } from 'redux'
import cart, * as fromCart from './cart'
import products, * as fromProducts from './products'
/**
* 用于 Reducer 的拆分,定义各个子 Reducer 函数,然后用这个方法,
* 将它们合成一个大的 Reducer
*/
export default combineReducers({
cart,
products
})
Store:4个api以及创建store。
- getState()方法用于获取state;
- dispatch(action)方法用于执行一个Action。
- subscribe(listener)用于注册回调,监听state的变化。
- replaceReducer(nextPeducer)更新当前Store内的Reducer(一般只会在开发模式中使用)。
- 创建store: 详细见下面整个应用入口JS示例。
createStore(reducer, [preloaderState], enhancer)方法3个参数。
参数1: reducer( Function ):接收2个参数,分别是当前state和要执行的Action,并返回新state树。
参数2:preloadedState:可选参数,初始state状态。
参数3: enhancer(Function): 可选参数。store enhancer,增强store的功能。
import { createStore, applyMiddleware } from "redux";
//浏览器Redux工具,用于调试
import { composeWithDevTools } from 'redux-devtools-extension';
// 创建store,整个应用中有且只有一个Store,用于存放整个应用中所有的state。
// store的创建,也相当于是reducer的创建作为createStore必传参数。
const store = createStore(reducer, composeWithDevTools(
applyMiddleware(...middleware), //applyMiddleware告诉createStore如何处理中间件
));
函数式组件:
1.通过mapStateToProps、mapDispatchToProps等state,action传入组件。
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { checkout } from '../../actions'
import { getTotal, getCartProducts } from '../../reducers'
const CartContainer = ({ products, total, checkout }) => {
const hasProducts = products.length > 0;
return (
<div>
<h3>您的购物车</h3><em>请选择以上商品</em>
<div className="cart-container">
<div>
{
products.map(product =>
<div key={product.id}>{product.title} - {product.price}元{product.quantity ? ` x ${product.quantity} 本` : null}</div>
)
}
</div>
<p>总价是: {total}元</p>
</div>
<button className="submit-btn" onClick={() => checkout(products)}
disabled={hasProducts ? '' : 'disabled'}>
去结算
</button>
</div>
)
}
CartContainer.propTypes = {
products: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
title: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
quantity: PropTypes.number.isRequired
})).isRequired,
total: PropTypes.string,
checkout: PropTypes.func.isRequired
}
//mapStateToProps: 返回的对象的所有key都为当前组件的props
const mapStateToProps = (state) => ({
products: getCartProducts(state),
total: getTotal(state)
})
//conect个Provider相互配合将 Action和state传入 组件app。
// connect 主要作用是连接React组件与React Store
export default connect(
mapStateToProps, //state,
{ checkout } //checkout这个应该是mapDispatchToProps,
)(CartContainer)
中间件:-----
react+redux +middleware(中间件)
redux是独立存在不属于react,可以搭配react使用。
react-redux2个重要的对象:Provider, connect.
Provider:包裹所有react组件,作为父组件,将store作为属性传给Provider。
connect:连接React组件与Redux Store,当前组件可以通过props获取应用中的state和Actions。(把state和action传给了组件用)
connect的4个参数:
mapStateToProps()、mapDispatchToProps()、mergeProps()和options。
mapDispatchToProps(): 这个可以通过redux提供的工具方法(bindActionCreators(action,dispatch))将action与dispatch绑定。
middleware:类似于在redux中间穿插一些记录日志、报错等等功能。
bindActionCreators工具函数的使用如下:将action与dispatch绑定
import { bindActionCreators } from "redux";
const mapDispatchToProps = dispatch => {
return bindActionCreators(
{
signinUser,
loginModalhide
},
dispatch
);
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Login);
react路由
5. react的性能及优化
1. diff算法:
- Tree Diff
对比虚拟DOM,把同一层级的节点遍历比较。只要不同就直接暴力删除。 - component Diff
类型相同的组件则按照原来的策略继续比较tree。
不同类型的组件,会将这个组件内部所有的子节点重新替换。 - element diff
相同组件类型的,还会继续对组件内部元素进行对比,这就是element diff。进行插入、移动、删除这3种操作。
2. shouldComponentUpdate() 这里优化
是否需要更新组件用:
- react-addons-shallow-compare 插件。第三方插件:react-addons-pure-render-mixin。原理就是重写了shouldComponentUpdate这个生命周期,但它的内部做法是让新旧props进行浅比较(PureRender)只对对象进行了引用的比较(===比较),而没有作值的比较。
浅比较源码:待补充。 - Immutable持久性数据结构库
优点主要体现数据的不可变。
Immutable和原生javascript对象相互转换。--- 待补充
Immutable与React配合使用 -- 待补充。
调试工具:
redux-devtools-extension:https://github.com/zalmoxisus/redux-devtools-extension
/**
* combineReducers用于 Reducer 的拆分,定义各个子 Reducer 函数,然后用这个方法,
* 将它们合成一个大的 Reducer
*/
import { combineReducers } from 'redux'
import React from "react";
import { render } from "react-dom";
import { createStore, applyMiddleware } from "redux";
//浏览器Redux工具
import { composeWithDevTools } from 'redux-devtools-extension';
// Redux顶层组件,用于包裹原有组件
import { Provider } from "react-redux";
//中间件,日志打印
import { createLogger } from "redux-logger";
// 中间件
import thunk from "redux-thunk";
// 应用的Reducer
import reducer from "./reducers";
//应用的Action
import { getAllProducts } from "./actions";
//应用的UI组件
import App from "./containers/App.jsx";
import "./index.css";
const middleware = [thunk];
if (process.env.NODE_ENV !== "production") {
//开发环境就添加 日志打印
middleware.push(createLogger());
}
// 创建store,整个应用中有且只有一个Store,用于存放整个应用中所有的state。
const store = createStore(reducer, composeWithDevTools(
applyMiddleware(...middleware),
));
// 请求接口获取数据
store.dispatch(getAllProducts());
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
react组件:写法:
- connect突出作用:连接了store与组件。把state和action传给了组件用。
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { addToCart } from '../../actions'
import { getVisibleProducts } from '../../reducers/products'
const BooksContainer = ({ products, addToCart }) => (
<div>
<h2>网上书店</h2>
<div className="products-container">
{products.map(product =>
<div key={product.id}>
{product.title} - {product.price}元 库存数量: {product.inventory ? `${product.inventory}` : null}
<button
className="add-btn"
onClick={() => addToCart(product.id)}
disabled={product.inventory > 0 ? '' : 'disabled'}>
{product.inventory > 0 ? '添加到购物车' : '售罄'}
</button>
</div>
)}
</div>
</div>
)
BooksContainer.propTypes = {
products: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
title: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
inventory: PropTypes.number.isRequired
})).isRequired,
addToCart: PropTypes.func.isRequired
}
const mapStateToProps = state => ({
products: getVisibleProducts(state.products)
})
export default connect(
mapStateToProps,
{ addToCart }
)(BooksContainer)
import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from 'redux-devtools-extension';
import { Provider } from "react-redux";
import { createLogger } from "redux-logger";
import thunk from "redux-thunk";
import reducer from "./reducers";
5.react生命周期
image.png
问题确认
网友评论