Skip to content
This repository has been archived by the owner on Mar 25, 2019. It is now read-only.

Commit

Permalink
refactor: 使用flux模式开发
Browse files Browse the repository at this point in the history
  • Loading branch information
翰文 committed Apr 1, 2015
1 parent 89dd085 commit 770dda5
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 70 deletions.
4 changes: 3 additions & 1 deletion examples/simple.js
Expand Up @@ -11,7 +11,9 @@ function accept(file) {
}

React.render(
<Dropzone action="http://127.0.0.1:3000/" accept={accept}>
<Dropzone action="http://127.0.0.1:3000/"
accept={accept}
>
<div className="dz-message">
Drop files here or click to upload.<br/>
<span className="note">(This is just a demo dropzone. Selected files are
Expand Down
84 changes: 28 additions & 56 deletions lib/Dropzone.js
Expand Up @@ -5,11 +5,10 @@
* Dropzone
*/
var React = require('react');
var FileStore = require('./stores/FileStore');
var FileInput = require('./FileInput');
var DzPreview = require('./DzPreview');
var post = require('./utils/request').post;
var uid = require('./utils/uid');
var createThumbnail = require('./utils/createThumbnail');
var FileActions = require('./actions/FileActions');

var Dropzone = React.createClass({

Expand All @@ -19,88 +18,61 @@ var Dropzone = React.createClass({
paramName: 'file',
accept: function(file) {
return Promise.resolve(file);
}
},
data: {},
success: function() { },
error: function() { }
};
},

accept: function(file) {
return createThumbnail(file).then(function(thumbnail) {
file.thumbnail = thumbnail;
return file;
})
.then(this.props.accept)
.then(function() {
return file;
});
},

getInitialState: function() {
return {
files: []
files: FileStore.getAllFiles()
};
},

componentDidMount: function() {
FileStore.addChangeListener(this._onChange);
},

componentWillUnmount: function() {
FileStore.removeChangeListener(this._onChange);
},

clickFileInput: function() {
var input = this.refs.input;
input.getDOMNode().click();
},

previews: function() {
var files = this.state.files;
var remove = this.removeFile;
return files.map(function(file) {
return <DzPreview file={file} key={file.uid} remove={remove} />;
return Object.keys(files).map(function(uid) {
return <DzPreview file={files[uid]} key={uid} />;
});
},

removeFile: function(uid) {
console.log(uid);
},

addFile: function(file) {
var self = this;
var files = this.state.files;
file.uid = uid(8);
files.push(file);
this.accept(file)
.then(this.startUploadFile)
.catch(function fileRejected(msg) {
file.done = msg;
self.updateFilesState();
});
},

startUploadFile: function(file) {
if (!file) {
return;
}

var props = this.props;
var self = this;
post(props.action)
.attach(props.paramName, file, file.type)
.on('progress', function(e) {
file.percent = e.percent;
self.updateFilesState();
})
.end(function() {
file.done = true;
self.updateFilesState();
});
FileActions.upload(file, this.props.accept, {
action: this.props.action,
paramName: this.props.paramName,
success: this.props.success,
error: this.props.error,
data: this.props.data
});
},

updateFilesState: function(files) {
files = files || this.state.files;
_onChange: function() {
var files = FileStore.getAllFiles();
this.setState({files: files});
},

render: function() {
var props = this.props;
var previews = this.previews();
var fileNumber = this.state.files.length;
var fileNumber = Object.keys(this.state.files).length;
return (
<form className={props.className} onClick={this.clickFileInput}>
<FileInput name={props.paramName} ref="input" addFile={this.addFile} />
<FileInput name={props.paramName} ref="input" upload={this.addFile} />
{previews}
{ !fileNumber ? props.children : '' }
</form>
Expand Down
2 changes: 1 addition & 1 deletion lib/DzPreview.js
Expand Up @@ -43,7 +43,7 @@ var DzPreview = React.createClass({
return 'dz-preview dz-image-preivew dz-error dz-complete';
}

return 'dz-preivew dz-file-preview';
return 'dz-preview dz-processing dz-image-preview';
},

fileResult: function(file) {
Expand Down
12 changes: 8 additions & 4 deletions lib/FileInput.js
Expand Up @@ -13,7 +13,7 @@ var FileInput = React.createClass({
getDefaultProps: function() {
return {
name: 'file',
addFile: function() {}
upload: function() {}
};
},

Expand All @@ -25,15 +25,19 @@ var FileInput = React.createClass({
var fileList = this.getDOMNode().files;
var len = fileList.length;
for (var i = 0; i < len; i++) {
this.props.addFile(fileList.item(i));
var file = fileList.item(i);
this.props.upload(file);
}
},

render: function() {
var css = fileInputCss;
return (
<input type="file" name={this.props.name}
style={css} multiple="multiple" onChange={this.onChange} />
<input type="file"
name={this.props.name}
style={css}
multiple="multiple"
onChange={this.onChange}/>
);
}
});
Expand Down
6 changes: 0 additions & 6 deletions lib/FileQueues.js

This file was deleted.

77 changes: 77 additions & 0 deletions lib/actions/FileActions.js
@@ -0,0 +1,77 @@
/**!
* desc
* Copyright(c) Alibaba Group Holding Limited.
* MIT Licensed
*
* Authors:
* 翰文 <hanwen.sah@taobao.com> (http://shepherdwind.com)
*/
'use strict';

var DzDispatcher = require('../dispatcher/DzDispatcher');
var DzConstants = require('../constants/DzConstants');
var createThumbnail = require('../utils/createThumbnail');
var request = require('../utils/request');

var FileActions = {

upload: function(file, accept, config) {

createThumbnail(file)
.then(function(thumbnail) {
file.thumbnail = thumbnail;
return file;
})
.then(accept)
.then(function() {
DzDispatcher.dispatch({
actionType: DzConstants.FILE_ADD,
file: file
});

upload(file, config);
})
.catch(function(msg) {
DzDispatcher.dispatch({
actionType: DzConstants.FILE_REJECTED,
file: file,
msg: msg
});
});
}

};

function upload(file, config) {
request
.upload(file, config)
.on('progress', function(e) {
DzDispatcher.dispatch({
actionType: DzConstants.FILE_UPLOAD_PROGRESS,
uid: file.uid,
percent: e.percent
});
})
.end(function(err, ret) {
if (err || ret.status !== 200) {
var message = err ? err.message : ret.text;
DzDispatcher.dispatch({
actionType: DzConstants.FILE_UPLOAD_FAIL,
uid: file.uid,
error: message
});

config.error(message);
return;
}

DzDispatcher.dispatch({
actionType: DzConstants.FILE_UPLOAD_SUCCESS,
uid: file.uid,
body: ret.body
});

config.success(ret.body);
});
}
module.exports = FileActions;
8 changes: 8 additions & 0 deletions lib/constants/DzConstants.js
@@ -0,0 +1,8 @@
var keymirror = require('keymirror');
module.exports = keymirror({
FILE_ADD: null,
FILE_REJECTED: null,
FILE_UPLOAD_PROGRESS: null,
FILE_UPLOAD_SUCCESS: null,
FILE_UPLOAD_FAIL: null
});
6 changes: 6 additions & 0 deletions lib/constants/StatusConstants.js
@@ -0,0 +1,6 @@
var keymirror = require('keymirror');
module.exports = keymirror({
ADD: null,
REJECTED: null,
UPLOADING: null
});
3 changes: 3 additions & 0 deletions lib/dispatcher/DzDispatcher.js
@@ -0,0 +1,3 @@
var Dispatcher = require('flux').Dispatcher;

module.exports = new Dispatcher();
104 changes: 104 additions & 0 deletions lib/stores/FileStore.js
@@ -0,0 +1,104 @@
/**!

This comment has been minimized.

Copy link
@yiminghe

yiminghe Apr 9, 2015

Member

flux 是否适合组件?不同组件实例的数据由同一个 store 存储是否合适

This comment has been minimized.

Copy link
@shepherdwind

shepherdwind Apr 9, 2015

第一次写react,尝试一下flux而已。

不过后来是有一些问题。多个组件的情况比较麻烦,我后面改下吧。

* desc
* Copyright(c) Alibaba Group Holding Limited.
* MIT Licensed
*
* Authors:
* 翰文 <hanwen.sah@taobao.com> (http://shepherdwind.com)
*/
'use strict';

var DzDispatcher = require('../dispatcher/DzDispatcher');
var DzConstants = require('../constants/DzConstants');
var StatusConstants = require('../constants/StatusConstants');
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');
var uid = require('../utils/uid');

var CHANGE_EVENT = 'change';
var _files = {};

var FileStore = assign({}, EventEmitter.prototype, {

getAllFiles: function() {
return _files;
},

getAddedFiles: function() {
return Object.keys(_files).filter(function(uid) {
var file = _files[uid];
if (file.status === StatusConstants.ADD) {
return file;
}
});
},

addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
},

removeChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
},

emitChange: function() {
this.emit(CHANGE_EVENT);
}

});

function add(file) {
var _uid = uid();
file.uid = _uid;
file.status = StatusConstants.ADD;
_files[_uid] = file;
}

function reject(file, msg) {
add(file);
file.status = StatusConstants.REJECTED;
file.done = msg;
}

function success(uid) {
_files[uid].done = true;
}

function uploading(uid, percent) {
_files[uid].status = StatusConstants.UPLOADING;
_files[uid].percent = percent;
}

function fail(uid, msg) {
_files[uid].done = msg;
}

DzDispatcher.register(function(action) {
switch (action.actionType) {
case DzConstants.FILE_ADD:
add(action.file);
break;

case DzConstants.FILE_REJECTED:
reject(action.file, action.msg);
break;

case DzConstants.FILE_UPLOAD_PROGRESS:
uploading(action.uid, action.percent);
break;

case DzConstants.FILE_UPLOAD_SUCCESS:
success(action.uid);
break;

case DzConstants.FILE_UPLOAD_FAIL:
fail(action.uid, action.error);
break;

default:
}

FileStore.emitChange();
});

module.exports = FileStore;

0 comments on commit 770dda5

Please sign in to comment.