標籤:
曾經實現過Angular版,這次感覺用了高大上的React卻寫了更多的代碼,需要的配置也更多了,有利有弊吧。
但這個“導航條問題”很有意思,涉及到在Redux中寫timer,其實我很困惑,到底如何完美類比使用者的頁面載入,
貌似瀏覽器並沒有提供進度API,只能以這樣拙劣的方式進行類比,有興趣的朋友不妨與我交流。
代碼附上:
LoadingBar.jsx
import React, { Component, PropTypes } from ‘react‘;import { connect } from ‘react-redux‘; export class LoadingBar extends Component { constructor(props) { super(props); this.state = { timer: null, style: { display: ‘none‘, position: ‘absolute‘, width: ‘0%‘, height: ‘3px‘, backgroundColor: ‘blue‘, transition: ‘width 400ms ease-out, height 400ms linear‘ } }; } componentWillReceiveProps(nextProps) { if (nextProps.status) { let progress = 0; this.setState({ style: Object.assign({}, this.state.style, { width: ‘0%‘ }) }); let timer = setInterval(() => { if (progress <= (100 - nextProps.step)) { this.setState({ style: Object.assign({}, this.state.style, { width: `${progress += nextProps.step}%`, display: ‘block‘ }) }); } }, nextProps.speed); this.setState({ timer: timer }); } else { clearInterval(this.state.timer); this.setState({ timer: null, style: Object.assign({}, this.state.style, { width: ‘100%‘, display: ‘none‘ }) }); } } render() { return ( <div> <div style={this.state.style} className={this.props.className}></div> <div style={{ display: ‘table‘, clear: ‘both‘ }}></div> </div> ) }} LoadingBar.propTypes = { className: PropTypes.string, speed: PropTypes.number, step: PropTypes.number, status: PropTypes.bool,} function mapStateToProps(state) { return {...state.loading};} export default connect(mapStateToProps)(LoadingBar)
App.jsx
import LoadingBar from ‘LoadingBar‘;const App = ({children}) => { return ( <div> <LoadingBar speed={5} step={2} /> {children} </div> );};App.propTypes = { children: PropTypes.object};export default App;
loadingReducer.js
export default function loading( state = { status: false }, action = {}) { switch (action.type) { case ‘SHOW_LOADING‘: return Object.assign({}, state, { status: true, }); case ‘HIDE_LOADING‘: return Object.assign({}, state, { status: false, }); default: return state }}
loadingActions.js
export function show() { return { type: ‘SHOW_LOADING‘ }}export function hide() { return { type: ‘HIDE_LOADING‘ }}
loadingMiddleware.js
import { show, hide } from ‘./loadingActions‘;const defaultTypeSuffixes = [‘REQUEST‘, ‘SUCCESS‘, ‘FAILURE‘]export default function loadingBarMiddleware(config = {}) { const typeSuffixes = config.typeSuffixes || defaultTypeSuffixes; return ({ dispatch }) => next => action => { next(action); if (action.type === undefined) { return; } const [PENDING, FULFILLED, REJECTED] = typeSuffixes; const isPending = `_${PENDING}`; const isFulfilled = `_${FULFILLED}`; const isRejected = `_${REJECTED}`; if (action.type.indexOf(isPending) !== -1) { dispatch(show()); } else if (action.type.indexOf(isFulfilled) !== -1 || action.type.indexOf(isRejected) !== -1) { dispatch(hide()); } }}
配置Store
import { createStore, applyMiddleware } from ‘redux‘;import { loadingMiddleware } from ‘loadingMiddleware‘;import rootReducer from ‘./reducers‘;const store = createStore( rootReducer, applyMiddleware(loadingMiddleware()))
配置RootReducer
import { combineReducers } from ‘redux‘;import { loadingReducer } from ‘./loadingReducer‘;const reducer = combineReducers({ loading: loadingReducer,});
寫了一個基於React+Redux的仿Github進度條