emmmmm。。。。。。。。。。css
若是有什么说的不对的地方,欢迎评论告知。html
=3333333=前端
先从最基础的react提及吧,目前框架都属于组件化的,可是更主要的目的是为了让前端围绕着数据逻辑来作页面而并不是原先的去操做dom的思想,三大框架目前都是往一个方向去。不过相比其余,react主打是diff算法处理dom,因此掌握他的生命周期去处理好数据才是咱们最初应该学习的东西。node
最经常使用的就是react.Component
谈一下他的生命周期吧。
假如我页面有一个首页,咱们如今要作顶部的导航栏,那么咱们如今去写一个顶部导航的组件。
假设这个顶部的导航,每一个人权限不一样,看到的东西不同,那么这个导航是经过请求数据来实现的。react
来,先熟悉git
挂载时期会执行的(能够理解为这个组件丢到页面时候会执行,而且只执行一次的)。github
constructor() // 构造函数,通常我会在这里去定当前组件的state初始化 componentWillMount() // 挂载以前,在17以后更名下面一条 UNSAFE_componentWillMount() // 上面挂载前立刻要更改的名字。 //这个是惟一会在服务端调用的生命周期钩子,在这里设置一些东西不会致使组件从新渲染, //因此这里最好不要随意进行一些组件须要数据的请求。 render() // 这个组件须要输出的东西,按道理来讲都是一些jsx之类的, //若是你输出的是字符串和数字,则会变成text node, //若是输出的是布尔值的false,或者null,就会不进行渲染。 componentDidMount() // 这里就是组件挂载时候最后触发的一个生命周期了。 // 由于这个里面请求数据会让组件从新渲染,因此通常数据放在这里进行请求。
而后这个组件由于数据变化也会从新渲染,一种是props改变的时候(或者父组件从新渲染的时候),一种是本身的state改变的时候。web
props改变的时候会执行的生命周期算法
UNSAFE_componentWillReceiveProps(nextProps) // 这个生命周期在17版以前叫componentWillReceiveProps // 通常是在父组件更新的时候,或者props改变的时候会触发的,用来根据props更改而改本组件state用的 // 官方目前推荐用下一条去替换他 static getDerivedStateFromProps(nextProps, prevState) // 接收到新的props或者父组件从新渲染的时候,都会调用。 // 若是你只想处理变化,就要比较新旧值 // 做用跟上面一条是同样的,props改变时候要改state就在这里作 shouldComponentUpdate(nextProps, nextState) // 这里能够经过返回false,来阻止从新渲染 // 默认为true,若shouldComponentUpdate()返回false, //然后UNSAFE_componentWillUpdate(),render(), 和 componentDidUpdate()将不会被调用 UNSAFE_componentWillUpdate() // 17版之前叫componentWillUpdate // 在收到新的state或者props的时候,渲染前被当即调用 //不要在这里setState,不要在这里setState,不要在这里setState, render() // 固然少不了输出须要显示的东西啦 getSnapshotBeforeUpdate() // 在最新的渲染输出提交给DOM前将会当即调用 // 为了支持异步渲染,若是在componentWillUpdate处理的一些事情,可能会有延迟滞后 // 这一辈子命周期返回的任何值将会 做为参数被传递给componentDidUpdate()。 componentDidUpdate(prevProps, prevState) // 终于说到最后一个了,我擦啦 // 更新发生后当即被调用 // 这也是一个适合发送请求的地方,要是你对比了当前属性和以前属性(例如,若是属性没有改变那么请求也就不必了),否则就循环给你看,嘿嘿嘿嘿嘿嘿
而后就是state更改的时候了,懒得打了,就是上面props更改时候的一些生命周期去掉UNSAFE_componentWillReceiveProps(nextProps)或者static getDerivedStateFromProps(nextProps, prevState),直接从shouldComponentUpdate开始。redux
最后组件准备被移除的时候
componentWillUnmount() // 在组件被卸载和销毁以前马上调用。能够在该方法里处理任何须要的清理工做 // 例如解绑定时器,取消网络请求,清理任何在componentDidMount环节建立的DOM元素。
捕捉错误的生命周期
componentDidCatch(error, info) // 打印它们之下组件里的错误,不能捕捉它本身内部的错误。 // 在这里是用来处理错误的,不要尝试用这个去处理数据
好了,生命周期大体就是这些,估计看完也困了。
咱们假如要作一个顶部导航,那么(敲黑板)重点就在于这个组件怎么请求,请求完了啥时候往里面丢,页面怎么处理之类的。
其实总结起来也比较简单,步骤以下
另外有的小伙伴说,React.PureComponent能够帮你处理一些 shouldComponentUpate()新旧值的判断是否要从新渲染,不过这个只会对对象进行浅对比。
若是对象包含复杂的数据结构,那么可能会致使他没法渲染出你要的最新的数据,React.PureComponent 的 shouldComponentUpate() 会忽略整个组件的子级。请确保全部的子级组件也是”Pure”的。
说简单一点,其实就是
action => reducer => store
不过由于redux不但愿有一些反作用的数据产生,因此咱们要在这里面请求数据,就须要一些中间件。
目前比较大众的有俩。
redux-saga和redux-thunk
先大体介绍一下
说简单一些,就是让action中能够请求异步操做,请求到了数据再执行reducer存入store里面。
引入方法
import thunkMiddleware from 'redux-thunk' import { Provider } from 'react-redux' import { createStore, applyMiddleware } from 'redux' import { Reduces } from './store/index.js' // 引入全部的reduces const store = createStore( Reduces, applyMiddleware( thunkMiddleware // 容许 dispatch() 函数 ) ) <Provider store={store}> // 丢到里面去 <Router> </Router> </Provider>
而后在action里面,就能够
/** * 获取用户订单信息 * @param {String} type 用户订单的请求类型 * @return {dispatch} dispatch 返回调用新的action方法 */ getUserOrderList(type) { return dispatch => { // 这个OrderModel是我本身项目全部订单请求都放在里面的,其实就至关与写一个fetch,而后then的处理他 return OrderModel.orderlist({ status: type }).then(response => { // 这里在存入store里面去,这里通常我会写一个公用的dispatch的方法进行丢入 }) } }
而后用dva的朋友通常用的都是
这个其实我了解的并不深,就拿官网的事例来用一下
import { call, put, takeEvery, takeLatest } from 'redux-saga/effects' import Api from '...' // worker Saga : 将在 USER_FETCH_REQUESTED action 被 dispatch 时调用 function* fetchUser(action) { try { // call这里进行请求数据,拿到的数据丢到user里面 const user = yield call(Api.fetchUser, action.payload.userId); // 开始匹配type,进行数据更改在这里 yield put({type: "USER_FETCH_SUCCEEDED", user: user}); } catch (e) { yield put({type: "USER_FETCH_FAILED", message: e.message}); } }
这里放上两个文档供参考
通常玩react最容易遇到的坑,就是如何处理好数据,搭配生命周期,刚开始可能会由于没处理好数据,致使组件无内容报错,也有循环不加key等。
感受报错最多的可能性应该是这个key了。
当循环的时候,或者使用table表单的时候,特别是antd里面的table,要仔细看文档,须要key的时候必定要加上。
route目前用的比较多的是两种
BrowserRouter和HashRouter
这个就比较丑了,可是路由都在前端,全部的页面都是用#后面带上一些东西,前端本身作管理就行了。
HashRouter 使用 URL 的 hash (例如:window.location.hash) 来保持 UI 和 URL 的同步。
不过像描点就不要想啦。
import { HashRouter } from 'react-router-dom' <HashRouter> <App/> </HashRouter>
这个就是使用 HTML5 提供的 history API 来处理路由,全部的页面都是真实路径,须要后端配置全部请求页面都指向咱们的主页面。
import { BrowserRouter } from 'react-router-dom' <BrowserRouter> <App/> </BrowserRouter>
跳转路由直接页面里面跳转,能够用下面的方法
import { Link } from 'react-router-dom' <Link to="/about">关于</Link>
若是是在js里面想跳转,则
this.props.history.push() // 或者replace,过着go()啥的
就能够进行跳转了,不过组件里面要拿到父组件的props须要继承一下
好比
<子组件 {...this.props}></子组件>
这样就能够把父组件的props所有丢到子组件里面去 =3=
最后把项目的一些须要的文档整理了一下