成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

從無(wú)到有-在create-react-app基礎(chǔ)上接入react-router、redux-saga

褰辯話 / 570人閱讀

摘要:將所有的需要鑒權(quán)的頁(yè)面放在例如下,只有在有微信相關(guān)鑒權(quán)的信息存在,才允許訪問(wèn)接下來(lái)的界面,否則,容器內(nèi)甚至可以直接不渲染接下來(lái)的界面。而接下來(lái)的則是把路由導(dǎo)向至了一個(gè)微信端專用的。

搭建項(xiàng)目框架 新建項(xiàng)目

執(zhí)行如下代碼,用create-react-app來(lái)建立項(xiàng)目的基礎(chǔ)框架,然后安裝需要用到的依賴。

$ npx create-react-app my-test-project
$ cd my-test-project
$ yarn add react-router-dom react-redux prop-types redux redux-saga
$ yarn start

完成后,應(yīng)用啟動(dòng)在localhost的3000端口。

接入react-router-dom

react-router-dom其實(shí)就是react-router 4.0,與之前的3.0有什么區(qū)別呢?react-router被一分為三。react-router、react-router-domreact-router-native

react-router實(shí)現(xiàn)了路由的核心的路由組件和函數(shù)。而react-router-domreact-router-native則是基于react-router,提供了特定的環(huán)境的組件。

react-router-dom依賴react-router,安裝的時(shí)候,不用再顯示的安裝react-router, 如果你有機(jī)會(huì)去看react-router-dom的源碼,就會(huì)發(fā)現(xiàn)里面有些組件都是從react-router中引入的。

新建layout

/src下新建layout目錄。為什么要新建layout目錄,因?yàn)橛锌赡芪覀儠?huì)用到多個(gè)layout,layout是一個(gè)什么樣的概念?

例如這個(gè)應(yīng)用需要提供一部分功能在微信使用。那么進(jìn)入所有微信的相關(guān)界面下都要進(jìn)行鑒權(quán)。沒(méi)有鑒權(quán)信息就不允許訪問(wèn),但是這個(gè)服務(wù)仍然有所有人都可以訪問(wèn)的路由。使用layout可以很好的幫我們解決這個(gè)問(wèn)題。

將所有的需要鑒權(quán)的頁(yè)面放在例如WechatContainer下,只有在有微信相關(guān)鑒權(quán)的信息存在,才允許訪問(wèn)接下來(lái)的界面,否則,容器內(nèi)甚至可以直接不渲染接下來(lái)的界面。

/src/layout下新建兩個(gè)文件,分別是AppLayout.js、WechatLayout.js。

AppLayout.js的代碼如下。在這個(gè)layout中,首頁(yè)就是單純的一個(gè)路由,導(dǎo)向至首頁(yè)。而接下來(lái)的/wechat則是把路由導(dǎo)向至了一個(gè)微信端專用的layout。

import React, { Component } from "react";
import Home from "../routes/home";
import WechatLayout from "./WechatLayout";
import { Route, Switch } from "react-router-dom";

/**
 * 項(xiàng)目入口布局
 * 在此處根據(jù)一級(jí)路由的不同進(jìn)入不同的container
 * 每個(gè)container有自己不同的作用
 *
 * 在react-router V4中,將原先統(tǒng)一在一處的路由分散到各個(gè)模塊中,分散到各個(gè)模塊當(dāng)中
 * 例如: WechatLayout的路由為/wechat 表示到該layout下的默認(rèn)路徑
 */
class AppLayout extends Component {
  constructor(props) {
    super(props);

    this.state = {};
  }

  render() {
    return (
      
); } } export default AppLayout;

WechatLayout.js的代碼如下。在這個(gè)layout中,我們就可以對(duì)訪問(wèn)該路由的用戶進(jìn)行鑒權(quán)。如果沒(méi)有權(quán)限,我們可以直接限制用戶的訪問(wèn),甚至直接不渲染render中的數(shù)據(jù)。

例如,我們可以在componentWillMount中或者在render中,根據(jù)當(dāng)前的state數(shù)據(jù),對(duì)當(dāng)前用戶進(jìn)行鑒權(quán)。如果沒(méi)有權(quán)限,我們就可以將當(dāng)前頁(yè)面重定向到?jīng)]有權(quán)限的提示界面。

import React, { Component } from "react";
import Home from "../routes/wechat/home";
import { Route, Switch } from "react-router-dom";
import { connect } from "react-redux";

class WechatLayout extends Component {
  constructor(props) {
    super(props);

    this.state = {};
  }

  componentWillMount() {
  }

  render() {
    const className = "Wechat-Layout";

    return (
      
Our Manage Layout
); } } const mapStateToProps = state => ({ reducer: state.wechatLayout }); export default connect(mapStateToProps)(WechatLayout);
新建routes

新建/src/routes/home/index.js,代碼如下。

import React, { Component } from "react";
import {Link} from "react-router-dom";

class Home extends Component {
  constructor(props) {
    super(props);

    this.state = {};
  }

  render() {
    const className = "Home";

    return (
      

This is Home

Manage Home
); } } export default Home;

新建/src/routes/wechat/home/index.js, 代碼如下。在代碼中可以看到,觸發(fā)reducer很簡(jiǎn)單,只需要調(diào)用dispatch方法即可。dispatch中的payload就是該請(qǐng)求所帶的參數(shù),該參數(shù)會(huì)傳到saga中間層,去調(diào)用真正的后端請(qǐng)求。并在請(qǐng)求返回成功之后,調(diào)用put方法更新state。

import React, { Component } from "react";
import {connect} from "react-redux";

class Home extends Component {
  constructor(props) {
    super(props);

    this.state = {};
  }

  componentWillMount() {
    this.props.dispatch({ type: "WATCH_GET_PROJECT", payload: { projectName: "tap4fun" } });
  }

  render() {
    const className = "Wechat-Home";

    return (
      

Home

The project name is : { this.props.reducer.projectName }

); } } const mapStateToProps = state => ({ reducer: state.wechat }); export default connect(mapStateToProps)(Home)
新建container

/src下新建container,在container中新建文件AppContainer.js。我們整個(gè)react應(yīng)用都裝在這個(gè)容器里面。AppContainer.js的代碼如下。

而其中的Provider組件,將包裹我們應(yīng)用的容器AppLayout包在其中,使得下面的所有子組件都可以拿到state。Provider接受store參數(shù)作為props,然后通過(guò)context往下傳遞。

import React, { Component } from "react";
import PropTypes from "prop-types";
import { Provider } from "react-redux";
import { BrowserRouter as Router } from "react-router-dom";
import AppLayout from "../layout/AppLayout";

class AppContainer extends Component {
  constructor(props) {
    super(props);

    this.state = {};
  }

  static propTypes = {
    store: PropTypes.object.isRequired
  };

  render() {
    const { store } = this.props;

    return (
      
        
          
        
      
    );
  }
}

export default AppContainer;
修改項(xiàng)目入口文件

更新/src/index.js,代碼如下。在此處會(huì)將create出來(lái)的store容器當(dāng)作屬性傳入到Appcontainer中,作為我們應(yīng)用的狀態(tài)容器。

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import * as serviceWorker from "./serviceWorker";
import AppContainer from "./container/AppContainer";
import createStore from "./store/createStore";

const store = createStore();

ReactDOM.render(, document.getElementById("root"));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
新建store

新建/src/store/craeteStore.js,代碼如下。通過(guò)以下的方式,我們可以給redux添加很多中間件,甚至是自己寫的中間件。

比如,我們可以自己實(shí)現(xiàn)一個(gè)日志中間件,然后添加到中間件數(shù)組middleWares中,在創(chuàng)建redux的store的時(shí)候,應(yīng)用我們自己寫的中間件。

import { applyMiddleware, compose, createStore } from "redux";
import createSagaMiddleware  from "redux-saga";
import rootReducer from "../reducers";
import rootSaga  from "../saga";

export default function configureStore(preloadedState) {
  // 創(chuàng)建saga中間件
  const sagaMiddleware = createSagaMiddleware();
  const middleWares = [sagaMiddleware];
  const middlewareEnhancer = applyMiddleware(...middleWares);

  const enhancers = [middlewareEnhancer];
  const composedEnhancers = compose(...enhancers);

  // 創(chuàng)建存儲(chǔ)容器
  const store = createStore(rootReducer, preloadedState, composedEnhancers);
  sagaMiddleware.run(rootSaga);

  return store;
}

在這引入了redux-saga。我之前在使用redux的時(shí)候,幾乎在每個(gè)模塊都要寫相應(yīng)的action和reducer,然后在相應(yīng)的模塊文件中引入action的函數(shù),然后在使用mapDispatchToProps將該函數(shù)注入到props中,在相應(yīng)的函數(shù)中調(diào)用。并且,一個(gè)action不能復(fù)用,即使觸發(fā)的是相同的reducer。這樣就會(huì)出現(xiàn)很多重復(fù)性的代碼,新增一個(gè)模塊的工作也相對(duì)繁瑣了很多。

但是使用了redux-saga之后,只需要在reducer中定義好相應(yīng)類型的操作和saga就可以了。不需要定義action的函數(shù),不需要在文件中引入action中函數(shù),甚至連mapDispatchToProps都不需要,直接使用this.props.dispatch({ "type": "WATCH_GET_PROJECT" })就可以調(diào)用。而且,action可以復(fù)用。

新建saga

新建/src/saga/index.js,代碼如下。

import { put, takeEvery } from "redux-saga/effects";
import { delay } from "redux-saga";

export function* fetchProject() {
  yield delay(1000);
  yield put({ type: "GET_PROJECT" })
}

export default function * rootSaga() {
  yield takeEvery("WATCH_GET_PROJECT", fetchProject);
}
新建reducer

新建/src/reducers/wechat.js,代碼如下。

const initialState = {
  projectName: null
};

export default function counter(state = initialState, action) {
  let newState = state;
  switch (action.type) {
    case "GET_PROJECT":
      newState.projectName = action.payload.projectName;
      break;
    default:
      break;
  }
  return {...newState}
}

新建/src/reducers/index.js,代碼如下。

import { combineReducers } from "redux";
import Wechat from "./wechat";

export default combineReducers({
  wechat: Wechat
});

在這里我們使用了combineReducers。在之前的基于redux的應(yīng)用程序中,常見(jiàn)的state結(jié)構(gòu)就是一個(gè)簡(jiǎn)單的JavaScript對(duì)象。

重新啟動(dòng)應(yīng)用

到此處,重新啟動(dòng)應(yīng)用,就可以在http://localhost:3000/wechat/home下看到從reducer中取出的數(shù)據(jù)。

在頁(yè)面中,我們就可以通過(guò)代碼this.props.dispatch的方式,來(lái)觸發(fā)action。

參考

https://github.com/mrdulin/bl...

https://cn.redux.js.org/docs/...

項(xiàng)目源代碼

Github倉(cāng)庫(kù)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/100102.html

相關(guān)文章

  • 分享一個(gè)react單頁(yè)應(yīng)用腳手架

    摘要:項(xiàng)目技術(shù)棧項(xiàng)目地址項(xiàng)目演示現(xiàn)在比較流行的腳手架應(yīng)該是,由官方開(kāi)發(fā)。網(wǎng)上關(guān)于項(xiàng)目的目錄結(jié)構(gòu)也很多,那應(yīng)該怎么合理地去組織我們的目錄結(jié)構(gòu)呢為了處理這個(gè)問(wèn)題,我參考了一些項(xiàng)目,然后把它們的優(yōu)點(diǎn)結(jié)合起來(lái),最后寫了這個(gè)腳手架。 項(xiàng)目技術(shù)棧:react16+react-router4+antd-mobile2+mobx+axios+webpack4項(xiàng)目github地址:https://github...

    kycool 評(píng)論0 收藏0
  • React生態(tài),dva源碼閱讀

    摘要:下面會(huì)從淺到深,淡淡在閱讀源碼過(guò)程中自己的理解。分拆子頁(yè)面后,每一個(gè)子頁(yè)面對(duì)應(yīng)一個(gè)文件??偨Y(jié)上面就是最早版本的源碼,很簡(jiǎn)潔的使用了等其目的也很簡(jiǎn)單簡(jiǎn)化相關(guān)生態(tài)的繁瑣邏輯參考源碼地址 ??dva的思想還是很不錯(cuò)的,大大提升了開(kāi)發(fā)效率,dva集成了Redux以及Redux的中間件Redux-saga,以及React-router等等。得益于Redux的狀態(tài)管理,以及Redux-saga中...

    bergwhite 評(píng)論0 收藏0
  • React生態(tài),dva源碼閱讀

    摘要:下面會(huì)從淺到深,淡淡在閱讀源碼過(guò)程中自己的理解。分拆子頁(yè)面后,每一個(gè)子頁(yè)面對(duì)應(yīng)一個(gè)文件??偨Y(jié)上面就是最早版本的源碼,很簡(jiǎn)潔的使用了等其目的也很簡(jiǎn)單簡(jiǎn)化相關(guān)生態(tài)的繁瑣邏輯參考源碼地址 ??dva的思想還是很不錯(cuò)的,大大提升了開(kāi)發(fā)效率,dva集成了Redux以及Redux的中間件Redux-saga,以及React-router等等。得益于Redux的狀態(tài)管理,以及Redux-saga中...

    txgcwm 評(píng)論0 收藏0
  • React生態(tài),dva源碼閱讀

    摘要:下面會(huì)從淺到深,淡淡在閱讀源碼過(guò)程中自己的理解。分拆子頁(yè)面后,每一個(gè)子頁(yè)面對(duì)應(yīng)一個(gè)文件??偨Y(jié)上面就是最早版本的源碼,很簡(jiǎn)潔的使用了等其目的也很簡(jiǎn)單簡(jiǎn)化相關(guān)生態(tài)的繁瑣邏輯參考源碼地址 ??dva的思想還是很不錯(cuò)的,大大提升了開(kāi)發(fā)效率,dva集成了Redux以及Redux的中間件Redux-saga,以及React-router等等。得益于Redux的狀態(tài)管理,以及Redux-saga中...

    harryhappy 評(píng)論0 收藏0
  • React 328道最全面試題(持續(xù)更新)

    摘要:希望大家在這浮夸的前端圈里,保持冷靜,堅(jiān)持每天花分鐘來(lái)學(xué)習(xí)與思考。 今天的React題沒(méi)有太多的故事…… 半個(gè)月前出了248個(gè)Vue的知識(shí)點(diǎn),受到很多朋友的關(guān)注,都強(qiáng)烈要求再出多些React相前的面試題,受到大家的邀請(qǐng),我又找了20多個(gè)React的使用者,他們給出了328道React的面試題,由我整理好發(fā)給大家,同時(shí)發(fā)布在了前端面試每日3+1的React專題,希望對(duì)大家有所幫助,同時(shí)大...

    kumfo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<