- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
嗯..我创建了一个上传组件,当用户上传图片时,该组件使用 FileReader API 显示图像预览。
但是,如果我在另一个组件中使用了 3 个组件,当我上传一张图片时,该图片也会在 3 个组件中重复。
例子:
... in render method
<UploadImage />
<UploadImage />
<UploadImage />
....
我的组件:
var React = require('react');
var Reflux = require('reflux');
// Actions
var actions = require('../../actions/Actions');
// Stores
var UploadStore = require('../../stores/ui/UploadStore');
var UI = require('material-ui');
var FlatButton = UI.FlatButton;
var Snackbar = UI.Snackbar;
var UploadImage = React.createClass({
mixins: [Reflux.connect(UploadStore, 'upload')],
propTypes: {
filename: React.PropTypes.string,
filesrc: React.PropTypes.string,
extensions: React.PropTypes.array.isRequired
},
getDefaultProps: function() {
return {
extensions: ['jpg', 'png', 'jpeg', 'gif']
};
},
_uploadImage: function () {
var file = {
file: this.refs.upload.getDOMNode().files[0] || false,
extensions: this.props.extensions
};
try {
actions.upload(file);
}
catch (e) {
console.log(e);
}
},
_uploadedImage: function() {
if (this.state.upload.filename) {
return (
<div className="upload-image">
<img src={this.state.upload.filesrc} />
<p>{this.state.upload.filename}</p>
</div>
);
}
},
render: function() {
return (
<div className="upload-image-container component-container">
<div className="upload-fields component-fields">
<h3>Imagem</h3>
<p>Arquivos PNG ou SVG no tamanho de XXXxYYYpx de até 50kb.</p>
<FlatButton label="Selecionar Imagem" className="upload-button">
<input
type="file"
id="imageButton"
className="upload-input"
ref="upload"
onChange={this._uploadImage} />
</FlatButton>
</div>
{this._uploadedImage()}
</div>
);
}
});
module.exports = UploadImage;
我的商店:
var Reflux = require('reflux');
var actions = require('../../actions/Actions');
var UploadStore = Reflux.createStore({
listenables: [actions],
data: {
filename: '',
filesrc: ''
},
getInitialState: function() {
return this.data;
},
onUpload: function (f) {
if (f) {
// Check extension
var extsAllowed = f.extensions;
if (this.checkExtension(extsAllowed, f.file.name)) {
// Crate the FileReader for upload
var reader = new FileReader();
reader.readAsDataURL(f.file);
reader.addEventListener('loadend', function() {
this.setData({
uploaded: true,
filename: f.file.name,
filesrc: reader.result
});
}.bind(this));
reader.addEventListener('error', function () {
actions.error('Não foi possível ler o seu arquivo. Por favor, verifique se enviou o arquivo corretamente.');
}.bind(this));
}
else {
actions.error('O arquivo que você está tentando enviar não é válido. Envie um arquivo nas seguintes extensões: ' + extsAllowed.join(', ') + '.');
}
}
else {
actions.error('File object not found.');
}
},
checkExtension: function (extensions, filename) {
var fileExt = filename.split('.').pop().toLowerCase();
var isSuccess = extensions.indexOf(fileExt) > -1;
if (isSuccess) return true;
return false;
},
setData: function(data) {
this.data = data;
this.trigger(data);
}
});
module.exports = UploadStore;
结果:
有什么想法吗?
谢谢!
最佳答案
不幸的是,商店的行为就像一个单例,即只有一个 UploadStore 实例。
您可以做的是引入一个额外的参数来区分上传。您的商店现在将接收一系列上传,但每个上传都标记有类别,您的组件也将有一个类别,并且仅从属于同一类别的商店中获取图像。这是使用 Reflux.connectFilter
混合宏完成的。
首先,我将上传的图像分成它自己的组件,如下所示:
var UploadedImage = React.createClass({
propTypes: {
upload: React.PropTypes.object.isRequired
},
render: function() {
return (
<div className="upload-image">
<img src={this.props.upload.filesrc} />
<p>{this.props.upload.filename}</p>
</div>
);
}
});
然后我们必须更改您的 UploadImage
组件中的一些内容,以便它按类别过滤:
var UploadImage = React.createClass({
// only select those uploads which belong to us
mixins: [
Reflux.connectFilter(UploadStore, "uploads", function(uploads) {
return uploads.filter(function(upload) {
return upload.category === this.props.category;
}.bind(this))[0];
})
],
propTypes: {
filename: React.PropTypes.string,
filesrc: React.PropTypes.string,
extensions: React.PropTypes.array.isRequired,
// an additional prop for the category
category: React.PropTypes.string.isRequired
},
_uploadImage: function () {
var file = {
file: this.refs.upload.getDOMNode().files[0] || false,
extensions: this.props.extensions
};
try {
// pass in additional parameter!
actions.upload(file, this.props.category);
}
catch (e) {
console.log(e);
}
},
render: function() {
return (
<div className="upload-image-container component-container">
<div className="upload-fields component-fields">
<h3>Imagem</h3>
<p>Arquivos PNG ou SVG no tamanho de XXXxYYYpx de até 50kb.</p>
<FlatButton label="Selecionar Imagem" className="upload-button">
<input
type="file"
id="imageButton"
className="upload-input"
ref="upload"
onChange={this._uploadImage} />
</FlatButton>
</div>
{this.state.uploads.map(function(upload, index) {
return <UploadedImage key={index} upload={upload}/>;
})}
</div>
);
}
});
您的商店现在拥有一组"file"对象,每个对象都标记有一个类别:
var UploadStore = Reflux.createStore({
listenables: [actions],
// data is now an array of objects
data: [],
getInitialState: function() {
return this.data;
},
// here we get the file + category
onUpload: function (f, category) {
if (f) {
// Check extension
var extsAllowed = f.extensions;
if (this.checkExtension(extsAllowed, f.file.name)) {
// Crate the FileReader for upload
var reader = new FileReader();
reader.readAsDataURL(f.file);
reader.addEventListener('loadend', function() {
this.setData(this.data.concat([{
uploaded: true,
filename: f.file.name,
filesrc: reader.result,
category: category /* adding category here */
}]));
}.bind(this));
reader.addEventListener('error', function () {
actions.error('Não foi possível ler o seu arquivo. Por favor, verifique se enviou o arquivo corretamente.');
}.bind(this));
}
else {
actions.error('O arquivo que você está tentando enviar não é válido. Envie um arquivo nas seguintes extensões: ' + extsAllowed.join(', ') + '.');
}
}
else {
actions.error('File object not found.');
}
},
checkExtension: function (extensions, filename) {
var fileExt = filename.split('.').pop().toLowerCase();
var isSuccess = extensions.indexOf(fileExt) > -1;
if (isSuccess) return true;
return false;
},
setData: function(data) {
this.data = data;
this.trigger(data);
}
});
最后,在您的 View 中,您可以像这样使用 UploadImage
组件:
我是即时编写代码的,因此可能存在一些问题 - 但更多的是关于概念。现在每个类别也可以上传多张图片,如果不需要,那么考虑用 HashMap 替换商店中的数组,以便键对应于类别 - 然后只能上传一张图片每个类别。
回复您的评论
也许您可以为商店使用工厂方法,例如:
var UploadStoreFactory = function() {
return Reflux.createStore({
/* your existing code as it was originally */
});
};
var UploadImage = React.createClass({
mixins: [Reflux.connect(UploadStoreFactory(), 'upload')],
/* your existing code as it was originally */
});
但我怀疑您的操作会触发上传存储的所有实例,但值得一试。但这带来了很多缺点,例如其他组件无法轻松收听此商店。
在this stackoverflow 提出了一个类似的问题,而且概念上正确的方法是为所有人使用一个桶/商店,并在商店中标记元素,以便您可以将它们分开。
请记住,商店也会清空和重新填充,例如,如果您创建一个包含产品和不同类别的网上商店,则每次用户切换到另一个类别时,您都会清除并重新填充 ProductStore
.如果您还有一个可能显示“您可能喜欢的产品”的侧边栏,那么我会将其建模为一个单独的商店,即 ProductSuggestionStore
,但两者都包含“Product”类型的对象。
如果商店在语义上表现不同但共享大量上传逻辑,您还可以尝试为您的商店构建基本原型(prototype)/类,然后扩展特定商店或将上传逻辑外包到服务类中。
如果您担心性能,即一次上传会导致所有组件重新呈现,那么您可以在 shouldComponentUpdate
中添加一个检查。
为什么只使用一个商店的一个很好的例子可能是用户想要关闭窗口但在您网站的某处上传仍在等待中,那么您的主应用程序 View 只需要检查一个商店。上传也可以很容易地排队,这样带宽就不会耗尽,因为所有上传都通过一个存储。
另外请记住,您可以让商店监听其他商店,例如 UploadHistoryStore
保留最近 10 次上传的带时间戳的记录。所有上传都进入同一个桶,但如果你有一个“最后 10 次上传”组件,它只需要听“UploadHistoryStore”
var UploadStore = Reflux.createStore({
/* ... upload stuff and trigger as usual ... */
});
var UploadHistoryStore = Reflux.createStore({
// keep the last ten uploads
historyLength: 10,
init: function() {
// Register statusStore's changes
this.listenTo(UploadStore, this.output);
this.history = [];
},
// Callback
output: function(upload) {
this.history.push({
date: new Date(), // add a date when it was uploaded
upload: upload // the upload object
}).slice(1, this.historyLength);
// Pass the data on to listeners
this.trigger(this.history);
}
});
关于javascript - RefluxJS "single"商店?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32959193/
在下面的方法中,如何将第一个Single的结果传递给第二个Single? 如现在所写,当它返回时,somethingId 是空的。如果我将返回的 Single.just(somethingId) 中的
我发现很多帖子都在回答类似的问题(例如“如何用 / 替换 \”或“如何替换 \\” by \”。我理解所有这些,但没有一个能解决我的特殊问题。这里是: 我正在从注册表中读取路径字符串,其中包含“///
注意:事实证明,toCompletable() 并非错误,而是调用代码。调用代码使得更改此方法使其工作(或不工作)。 我有以下方法。它返回一个 Single。有用。执行内部代码,以便 remoteDa
react-native repo here 中的一个文件中有一段代码如下图: export type Operation = & {instanceID: DebugID} & (
当使用带有 Single() 的 LINQ 时,我的代码行总是带有绿色下划线,并带有建议“替换为对 single 的单一调用”。这是什么意思?下面是产生该建议的一行代码示例: var user = d
讨论来自 this answer让我好奇。哪个更快: someEnumerable.Single(predicate); 或 someEnumerable.Where(predicate).Singl
我正在使用 Keycloak 作为单点登录 (SSO) 平台的 OP。我已经将我的两个 Web 应用程序连接到 Keycloak,以便使用单点登录功能。 此外,我已经制作了一个应用程序,当注销时将被重
我的步骤是: 创建单个值 x - 可能会占用一些 CPU 资源 使用值x来执行IO操作。这已经返回 Completable 返回x 所以我想这样做: Single result =
我想知道是否有人可以阐明这个问题,什么时候使用 Single.fromCallable( ()-> myObject ) 代替 Single.just(myObject) 根据文档,Single.fr
我有两个 Singles 来源,我将它们组合成一个 Single of Pair。 假设我们对这些来源有两种方法: private Single single1() {} private Single
我想将单个 Intel CPU 内核的速度与单个 nVidia GPU 内核的速度(即:单个 CUDA 代码、单个线程)进行比较。我确实实现了以下简单的二维图像卷积算法: void convoluti
我在实现 Ping Federate 时遇到此问题 Error - Single Sign-On Single sign-on authentication was unsuccessful (ref
我有几个 api 调用(Rx singles),我想将它们组合成一个 Single。我正在使用 Single.merge 尝试合并这些调用的结果,但是当我订阅响应时,我得到一个空数组,因为订阅已经发生
早上好。我的代码有问题 bootsfaces 。我需要我的 DataTable 支持单行选择,但不支持多行选择。但是,我的表格始终只使用多项选择。 这是我的代码: 我没有进行简单的选择,因为我引用了
我怎样才能像下面的代码那样使用字符串。 $str = 'Is yo"ur name O'reil"ly?'; 上面的代码只是一个例子..我需要使用包含单引号和双引号的大 html 模板。我尝试了 Ad
我有一组地理空间+时间数据和一些附加属性,我将在 map 上显示这些数据。该集合目前有几百万份文件,并且会随着时间的推移而增加。 每个文档都有以下字段: 位置:[geojson 对象] 日期:[日期对
我目前在 .NET 2.0 下使用 SharpZipLib,通过它我需要将单个文件压缩为单个压缩存档。为此,我目前正在使用以下内容: string tempFilePath = @"C:\Users\
我有 table create table1( column1 number(10, column2 number(10), column3 number(10) ); column1是主
考虑下面这段代码,我正在尝试使用 Executors.newFixedThreadPool(1).asCoroutineDispatcher()创建单线程调度程序;我想要 launch(singleT
我面临着困惑,举个例子 4 Single: val s1 : Single = service1.execute().subscribeOn(io()) val s2 : Single = servi
我是一名优秀的程序员,十分优秀!