国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

React-Redux小應(yīng)用(一)-React_Redux_Appointment

CoorChice / 537人閱讀

摘要:先來一波硬廣我的博客歡迎觀光傳送門這個小應(yīng)用使用創(chuàng)建演示地址,地址。這是之前的的版,之前的演示,改寫自的課程。

React-Redux-Appointment

先來一波硬廣:我的博客歡迎觀光:傳送門
這個小應(yīng)用使用Create React App創(chuàng)建,演示地址:https://liliang-cn.github.io/react_redux_appointment,repo地址:https://github.com/liliang-cn/react_redux_appointment。

這是之前的React_appointment的Redux版,之前的演示,改寫自Lynda的課程Building a Web Interface with React.js。

文件結(jié)構(gòu)

最終的文件目錄如下:

react_redux_appointment/
  README.md
  node_modules/
  package.json
  public/
    index.html
    favicon.ico
  src/
    actions/
      index.js
    components/
      AddForm.js
      AptList.js
      Search.js
      Sort.js
    constants/
      index.js
    containers/
      AddForm.js
      App.js
    reducers/
      apts.js
      formExpanded.js
      index.js
      openDialog.js
      orderBy.js
      orderDir.js
      query.js
    index.css
    index.js
用到的模塊
{
  "name": "react_redux_appointment",
  "version": "0.1.0",
  "private": true,
  "homepage": "https://liliang-cn.github.io/react_redux_appointment",
  "devDependencies": {
    "react-scripts": "0.8.4"
  },
  "dependencies": {
    "axios": "^0.15.3",
    "gh-pages": "^0.12.0",
    "lodash": "^4.17.2",
    "material-ui": "^0.16.5",
    "moment": "^2.17.1",
    "react": "^15.4.1",
    "react-dom": "^15.4.1",
    "react-redux": "^5.0.1",
    "react-tap-event-plugin": "^2.0.1",
    "redux": "^3.6.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "deploy": "yarn build && gh-pages -d build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}
所有的state

小應(yīng)用一共有六個狀態(tài),其中的formExpanded和openDialog是界面組件的狀態(tài),
剩下的四個分別是apts(代表所有的預約)、orderBy(根據(jù)什么來排列預約列表,根據(jù)姓名還是根據(jù)日期)、
orderDir(排列列表的方向,是增序還是降序)、query(搜索的關(guān)鍵字)。

所有的Action

在應(yīng)用中可能產(chǎn)生的actions有七種:

addApt,即新建預約

deleteApt, 即刪除預約

toggleDialog, 即顯示、隱藏警告框

toggleFormExpanded, 顯示/隱藏表單

query,即查詢

changeOrderBy,即改變排序的關(guān)鍵字

changeOrderDir, 即改變排序方向

定義七個常量來代表這些action的類型:

constants/index.js:

export const ADD_APT = "ADD_APT";

export const DELETE_APT = "DELETE_APT";

export const TOGGLE_DIALOG = "TOGGLE_DIALOG";

export const TOGGLE_FORM_EXPANDED = "TOGGLE_FORM_EXPANDED";

export const QUERY = "QUERY";

export const CHANGE_ORDER_BY = "CHANGE_ORDER_BY";

export const CHANGE_ORDER_DIR = "CHANGE_ORDER_DIR";

actions/index.js:

import {
    ADD_APT,
    DELETE_APT,
    TOGGLE_DIALOG,
    TOGGLE_FORM_EXPANDED,
    QUERY,
    CHANGE_ORDER_BY,
    CHANGE_ORDER_DIR
} from "../constants";

export const addApt = (apt) => ({
    type: ADD_APT,
    apt
});

export const deleteApt = (id) => ({
    type: DELETE_APT,
    id
});

export const toggleDialog = () => ({
    type: TOGGLE_DIALOG
});

export const toggleFormExpanded = () => ({
    type: TOGGLE_FORM_EXPANDED
});

export const query = (query) => ({
    type: QUERY,
    query
});

export const changeOrderBy = (orderBy) => ({
    type: CHANGE_ORDER_BY,
    orderBy
});

export const changeOrderDir = (orderDir) => ({
    type: CHANGE_ORDER_DIR,
    orderDir
});
UI組件 樣式

使用Material-UI需要引入Roboto字體:

src/index.css

@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500");
body {
  margin: 0;
  padding: 0;
  font-family: Roboto, sans-serif;
}
表單組件

components/addForm.js:

import React from "react";

import {Card, CardHeader, CardText} from "material-ui/Card";
import TextField from "material-ui/TextField";
import DatePicker from "material-ui/DatePicker";
import TimePicker from "material-ui/TimePicker";
import RaisedButton from "material-ui/RaisedButton";
import Paper from "material-ui/Paper";
import Divider from "material-ui/Divider";
import Dialog from "material-ui/Dialog";
import FlatButton from "material-ui/FlatButton";

import moment from "moment";

const paperStyle = {
  width: 340,
  margin: "0 auto 20px",
  textAlign: "center"
};

const buttonStyle = {
    margin: 12
};

// open, toggleDialog是兩個布爾值,handleAdd,formExpanded, toggleFormExpanded是三個回調(diào)函數(shù),來自于../containers/AddForm.js中的容器從store中獲取并傳遞下來的
const AddForm = ({handleAdd, open, toggleDialog, formExpanded, toggleFormExpanded}) => {
    let guestName, date, time, note;
    // 點擊Add時會先首先檢查是否所有的值都有輸入,如果輸入合法則發(fā)起ADD_APT的action然后發(fā)起切換表單顯示的action,如果輸入有誤則發(fā)起TOGGLE_DIALOG的action
    const onAdd = () => {
        guestName && date && time && note
        ?
        handleAdd({guestName, date, time, note}) && toggleFormExpanded()
        :
        toggleDialog()
    };

    // 這兩個函數(shù)用來獲取輸入的日期和時間
    const handleDateChange = (event, aptDate) => {
        date = moment(aptDate).format("YYYY-MM-DD")
    };

    const handleTimeChange = (event, aptTime) => {
        time = moment(aptTime).format("hh:mm")
    };

    const actions = [
        
    ];

    return (
        
            // Card組件的expanded的值是一個布爾值,來自于父組件傳下來的formExpanded,即應(yīng)用的狀態(tài)formExpanded,用來確定是否顯示表單
            
                
                
                     guestName = e.target.value.trim()}
                    />
                    
                    
                    
                    
                    
                     note = e.target.value.trim()}
                    />
                    
                    
                    
                
                // Dialog組件的open的值也是一個布爾值,來自于父組件傳下來的open,即應(yīng)用的狀態(tài)openDialog,用來驗證表單
                
                    All fileds are required!
                
            
        
    );
};

export default AddForm;
搜索表單

components/Search.js:

import React from "react";
import TextField from "material-ui/TextField";

const Search = ({handleSearch}) => {
    return (
        
handleSearch(e.target.value) } />
); }; export default Search;
排列選擇

components/Sort.js:

import React from "react";

import SelectField from "material-ui/SelectField";
import MenuItem from "material-ui/MenuItem"

const Sort = ({
    orderBy,
    orderDir,
    handleOrderByChange,
    handleOrderDirChange
}) => {
    return (
        
{handleOrderByChange(value)}} > {handleOrderDirChange(value)}} >
); }; export default Sort;
預約列表

這個組件的作用就是顯示預約列表,接受父組件傳來的apts數(shù)組和handleDelete函數(shù),在點擊RaisedButton的時候?qū)pt.id傳入handleDelete并執(zhí)行。

components/AptList.js:

import React from "react";
import {List, ListItem} from "material-ui/List";
import {Card, CardActions, CardHeader, CardTitle, CardText} from "material-ui/Card";
import RaisedButton from "material-ui/RaisedButton";

const buttonStyle = {
    width: "60%",
    margin: "12px 20%",
};

const AptList = ({apts, handleDelete}) => {
    return (
        

Appointments List

// 這里的i也可以直接用apt.id {apts.map((apt, i) => ( {apt.note} handleDelete(apt.id)} /> ))}
); }; export default AptList;
處理不同的actions 處理表單的顯示和隱藏

reducers/formExpanded.js:

import { TOGGLE_FORM_EXPANDED } from "../constants";

// formExpanded默認為false,即不顯示,當發(fā)起類型為TOGGLE_FORM_EXPANDED的action的時候,將狀態(tài)切換為true或者false
const formExpanded = (state=false, action) => {
    switch (action.type) {
        case TOGGLE_FORM_EXPANDED:
            return !state;
        default:
            return state;
    }
};

export default formExpanded;
表單驗證錯誤的提示對話框

reducers/openDialog.js:

import { TOGGLE_DIALOG } from "../constants";

// 這個action是由其他action引發(fā)的
const openDialog = (state=false, action) => {
    switch (action.type) {
        case TOGGLE_DIALOG:
            return !state;
        default:
            return state;
    }
};

export default openDialog;
處理新建預約和刪除預約

reducers/apts.js:

import { ADD_APT, DELETE_APT } from "../constants";

// 用唯一的id來標識不同的預約,也可以直接用時間戳new Date()
let id = 0;

// 根據(jù)傳入的數(shù)組和id來執(zhí)行刪除操作
const apts = (state=[], action) => {
    const handleDelete = (arr, id) => {
        for(let i=0; i
查詢和排列方式

這三個函數(shù)的作用就是根據(jù)action傳入的數(shù)據(jù),更新state里的對應(yīng)值,在這里并不會真正的去處理預約的列表。

reducers/orderBy.js:

import { CHANGE_ORDER_BY } from "../constants";

const orderBy = (state=null, action) => {
    switch (action.type) {
        case CHANGE_ORDER_BY:
            return action.orderBy
        default:
            return state;
    }
};

export default orderBy;

reducers/orderDir.js:

import { CHANGE_ORDER_DIR } from "../constants";

const orderDir = (state=null, action) => {
    switch (action.type) {
        case CHANGE_ORDER_DIR:
            return action.orderDir
        default:
            return state;
    }
};

export default orderDir;

reducers/query.js:

import { QUERY } from "../constants";

const query = (state=null, action) => {
    switch (action.type) {
        case QUERY:
            return action.query;
        default:
            return state;
    }
}

export default query;
合成reducers

reducers/index.js:

import { combineReducers } from "redux";

import apts from "./apts";
import openDialog from "./openDialog";
import formExpanded from "./formExpanded";
import query from "./query";
import orderBy from "./orderBy";
import orderDir from "./orderDir";

// redux提供的combineReducers函數(shù)用來將處理不同部分的state的函數(shù)合成一個
// 每當action進來的時候會經(jīng)過每一個reducer函數(shù),但是由于action類型(type)的不同
// 只有符合(switch語句的判斷)的reducer才會處理,其他的只是將state原封不動返回

const reducers = combineReducers({
    apts,
    openDialog,
    formExpanded,
    query,
    orderBy,
    orderDir
});

export default reducers;
容器組件

containers/AddForm.js:

import { connect } from "react-redux";

import { addApt, toggleDialog, toggleFormExpanded } from "../actions";

import AddForm from "../components/AddForm";

// AddForm組件可通過props來獲取兩個state:open和formExpanded
const mapStateToProps = (state) => ({
    open: state.openDialog,
    formExpanded: state.formExpanded
});

// 使得AddForm組件可以通過props得到三個回調(diào)函數(shù),調(diào)用即可相當于發(fā)起action
const mapDispatchToProps = ({
    toggleFormExpanded,
    toggleDialog,
    handleAdd: newApt => addApt(newApt)
});

// 使用react-redux提供的connect函數(shù),可以將一個組件提升為容器組件,容器組件可直接獲取到state、可以直接使用dispatch。
// 這個connect函數(shù)接受兩個函數(shù)作為參數(shù),這兩個作為參數(shù)的函數(shù)的返回值都是對象, 按約定他們分別命名為mapStateToProps,mapDispatchToProps
// mapStateToProps確定了在這個組件中可以獲得哪些state,這里的話只用到了兩個UI相關(guān)的state:open和formExpanded,這些state都可通過組件的props來獲取
// mapDispatchToProps本來應(yīng)該是返回對象的函數(shù),這里比較簡單,直接寫成一個對象,確定了哪些action是這個組件可以發(fā)起的,也是通過組件的props來獲取
// connect函數(shù)的返回值是一個函數(shù),接受一個組件作為參數(shù)。

export default connect(mapStateToProps, mapDispatchToProps)(AddForm);

containers/App.js:

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

import MuiThemeProvider from "material-ui/styles/MuiThemeProvider"
import injectTapEventPlugin from "react-tap-event-plugin";

injectTapEventPlugin();
import AppBar from "material-ui/AppBar";
import Paper from "material-ui/Paper";

import AddForm from "../containers/AddForm";
import Search from "../components/Search";
import Sort from "../components/Sort";
import AptList from "../components/AptList";

import { deleteApt, query, changeOrderBy, changeOrderDir } from "../actions";

const paperStyle = {
  minHeight: 600,
  width: 360,
  margin: "20px auto",
  textAlign: "center"
};

const App = ({
  apts,
  dispatch,
  orderBy,
  orderDir,
  handleSearch,
  handleDelete,
  handleOrderByChange,
  handleOrderDirChange
}) => (
  
    
); // 處理搜索和排序,返回處理后數(shù)組 const handledApts = (apts, query, orderBy, orderDir) => { const filterArr = (arr, query) => { return arr.filter(item => ( item.guestName.toLowerCase().indexOf(query) !== -1 || item.date.indexOf(query) !== -1 || item.time.indexOf(query) !== -1 || item.note.toLowerCase().indexOf(query) !== -1) ); }; const sortArr = (arr, orderBy, orderDir) => { if (orderBy && orderDir) { return arr.sort((apt1, apt2) => { const value1 = apt1[orderBy].toString().toLowerCase(); const value2 = apt2[orderBy].toString().toLowerCase(); if (value1 < value2) { return orderDir === "asc" ? -1 : 1; } else if (value1 > value2) { return orderDir === "asc" ? 1 : -1; } else { return 0; } }) } else { return arr; } }; if (!query) { return sortArr(apts, orderBy, orderDir); } else { return sortArr(filterArr(apts, query), orderBy, orderDir); } }; // App組件可通過props來獲取到四個state:query, orderBy, orderDir, apts // 這里是真正處理搜索和排序的地方,并不是直接將state中的apts返回,而是調(diào)用handleApts,返回處理的數(shù)組 const mapStateToProps = (state) => ({ query: state.query, orderBy: state.orderBy, orderDir: state.orderDir, apts: handledApts(state.apts, state.query, state.orderBy, state.orderDir), }); // App組件可通過props來獲取到四個函數(shù),也就是發(fā)起四個action:handleSearch,handleDelete,handleOrderByChange,handleOrderDirChange const mapDispatchToProps = ({ handleSearch: searchText => query(searchText), handleDelete: id => deleteApt(id), handleOrderByChange: orderBy => changeOrderBy(orderBy), handleOrderDirChange: orderDir => changeOrderDir(orderDir) }); export default connect(mapStateToProps, mapDispatchToProps)(App);
入口文件

src/index.js:

import React from "react";
import ReactDOM from "react-dom";

import { createStore } from "redux";
import { Provider } from "react-redux";

import App from "./containers/App";
import "./index.css";

import reducers from "./reducers";

// 使用createStore表示應(yīng)用的store,傳入的第一個參數(shù)是reducers,第二個參數(shù)是Redux的調(diào)試工具
const store = createStore(reducers, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());

// 使用react-redux提供的Provider組件,使App組件及子組件可以得到store的相關(guān)的東西,如store.getState(),store.dispatch()等。
ReactDOM.render(
  
    
  ,
  document.getElementById("root")
);
結(jié)尾

React提供的是通過state來控制控制UI和單向數(shù)據(jù)流動,
Redux提供的是單一數(shù)據(jù)源和只能通過action和reducer來處理state的更新。

以其中的點擊按鈕顯示新建預約表單的過程來捋一捋React、React-Redux的邏輯(靈感來源于自Cory House大神):

用戶:點擊按鈕

React:哈嘍,action生成函數(shù)toggleFormExpanded,有人點擊了展開新建預約的表單。

Action:收到,謝謝React,我馬上發(fā)布一個action也就是{type:TOGGLE_FORM_EXPANDED}告訴reducers來更新state。

Reducer:謝謝Action,我收到你的傳過來要執(zhí)行的action了,我會根據(jù)你傳遞進來的{type:TOGGLE_FORM_EXPANDED},先復制一份當前的state,然后把state中的formExpanded的值更新為true,然后把新的state給Store。

Store:嗯,Reducer你干得漂亮,我收到了新的state,我會通知所有與我連接的組件,確保他們會收到新state。

React-Redux:啊,感謝Store傳來的新數(shù)據(jù),我現(xiàn)在就看看React界面是否需要需要發(fā)生變化,啊,需要把新建預約的表單顯示出來啊,那界面還是要更新一下的,交給你了,React。

React:好的,有新的數(shù)據(jù)由store通過props傳遞下來的數(shù)據(jù)了,我會馬上根據(jù)這個數(shù)據(jù)把新建預約的表單顯示出來。

用戶:看到了新建預約的表單。

如果覺得還不錯,來個star吧。(笑臉)

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/86631.html

相關(guān)文章

  • react+react-router+react-redux全家桶項目開發(fā)過程分享

    摘要:項目地址下載完項目然后即可基于的項目,主要是為了學習實戰(zhàn)。數(shù)據(jù)都是固定的,從餓了么接口臨時抓的,模擬了一個的異步數(shù)據(jù)延遲,感謝餓了么。詳細信息可以看上面的官方文檔,我這里就簡單說一下我這個項目的應(yīng)用。 react-ele-webapp 項目地址 :https://github.com/kliuj/reac... run 下載完項目npm install然后npm run dev 即可 ...

    zzir 評論0 收藏0
  • React-Redux性能優(yōu)化

    摘要:但是和一起使用還需要一個工具,這一篇就說一下在使用上的一些性能優(yōu)化建議。如果的改變會引起值變化,那么會調(diào)用轉(zhuǎn)換函數(shù),傳入作為參數(shù),并返回結(jié)果。如果的值和前一次的一樣,它將會直接返回前一次計算的數(shù)據(jù),而不會再調(diào)用一次轉(zhuǎn)換函數(shù)。 前面寫了兩篇文章《React組件性能優(yōu)化》《Redux性能優(yōu)化》,分別針對React和Redux在使用上的性能優(yōu)化給了一些建議。但是React和Redux一起使用...

    JouyPub 評論0 收藏0
  • react、react-router、redux 也許是最佳實踐2

    摘要:上一篇也許是最佳小實踐加入在組件之間流通數(shù)據(jù)更確切的說,這被叫做單向數(shù)據(jù)流數(shù)據(jù)沿著一個方向從父組件流到子組件。這個將這個新的對象附加到上,并將它返回,用來更新。這一次,將當前的狀態(tài)仍舊是空數(shù)組和對象一起傳遞給了。 上一篇:react、react-router、redux 也許是最佳小實踐1 加入 redux React 在組件之間流通數(shù)據(jù).更確切的說,這被叫做單向數(shù)據(jù)流——數(shù)據(jù)沿著一個...

    AaronYuan 評論0 收藏0
  • React-redux基礎(chǔ)

    摘要:簡介創(chuàng)建的函數(shù),返回一個對象,包含等方法合并多個中間件處理,在實際的前調(diào)用一系列中間件,類似于綁定和函數(shù)式編程中常見的方法,介紹官方提供的綁定庫。 前言 在學習了React之后, 緊跟著而來的就是Redux了~ 在系統(tǒng)性的學習一個東西的時候, 了解其背景、設(shè)計以及解決了什么問題都是非常必要的。接下來記錄的是, 我個人在學習Redux時的一些雜七雜八~ Redux是什么 通俗理解 h...

    jsyzchen 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<