gpt4 book ai didi

javascript - 在 Facebook React 中使用混合与组件进行代码重用

转载 作者:IT王子 更新时间:2023-10-29 02:39:48 24 4
gpt4 key购买 nike

我开始在 Backbone 项目中使用 Facebook React,到目前为止一切顺利。
但是,我注意到我的 React 代码中出现了一些重复。

例如,我有几个类似表单的小部件,状态为INITIALSENDINGSENT。按下按钮时,需要验证表单,发出请求,然后更新状态。当然,状态与字段值一起保存在 React this.state 中。

如果这些是 Backbone View ,我会提取一个名为 FormView 的基类,但我的印象是 React 既不认可也不支持子类化来共享 View 逻辑(纠正我如果我错了)。

我见过两种在 React 中重用代码的方法:

在 React 中,mixin 和容器比继承更受青睐,我说得对吗?这是故意的设计决定吗? 对于第二段中的“表单小部件”示例,使用混合组件或容器组件是否更有意义?

Here's a gist with FeedbackWidget and JoinWidget in their current state .它们具有相似的结构、相似的 beginSend 方法,并且都需要一些验证支持(目前还没有)。

最佳答案

Update: this answer is outdated. Stay away from the mixins if you can. I warned you!
Mixins Are Dead. Long Live Composition

起初,我尝试为此使用子组件并提取 FormWidgetInputWidget。但是,我中途放弃了这种方法,因为我想更好地控制生成的 input 及其状态。

对我帮助最大的两篇文章:

事实证明,我只需要编写两个(不同的)mixin:ValidationMixinFormMixin
这是我将它们分开的方法。

验证混合

Validation mixin 添加了方便的方法来在您的某些状态属性上运行您的验证器函数,并将“错误”属性存储在 state.errors 数组中,以便您可以突出显示相应的字段。

来源 ( gist )

define(function () {

'use strict';

var _ = require('underscore');

var ValidationMixin = {
getInitialState: function () {
return {
errors: []
};
},

componentWillMount: function () {
this.assertValidatorsDefined();
},

assertValidatorsDefined: function () {
if (!this.validators) {
throw new Error('ValidatorMixin requires this.validators to be defined on the component.');
}

_.each(_.keys(this.validators), function (key) {
var validator = this.validators[key];

if (!_.has(this.state, key)) {
throw new Error('Key "' + key + '" is defined in this.validators but not present in initial state.');
}

if (!_.isFunction(validator)) {
throw new Error('Validator for key "' + key + '" is not a function.');
}
}, this);
},

hasError: function (key) {
return _.contains(this.state.errors, key);
},

resetError: function (key) {
this.setState({
'errors': _.without(this.state.errors, key)
});
},

validate: function () {
var errors = _.filter(_.keys(this.validators), function (key) {
var validator = this.validators[key],
value = this.state[key];

return !validator(value);
}, this);

this.setState({
'errors': errors
});

return _.isEmpty(errors);
}
};

return ValidationMixin;

});

用法

ValidationMixin有3个方法:validatehasErrorresetError
它期望类定义 validators 对象,类似于 propTypes:

var JoinWidget = React.createClass({
mixins: [React.addons.LinkedStateMixin, ValidationMixin, FormMixin],

validators: {
email: Misc.isValidEmail,
name: function (name) {
return name.length > 0;
}
},

// ...

});

当用户按下提交按钮时,我调用validate。调用 validate 将运行每个验证器并使用包含未通过验证的属性键的数组填充 this.state.errors

在我的 render 方法中,我使用 hasError 为字段生成正确的 CSS 类。当用户将焦点放在该字段内时,我调用 resetError 以删除错误突出显示,直到下一次 validate 调用。

renderInput: function (key, options) {
var classSet = {
'Form-control': true,
'Form-control--error': this.hasError(key)
};

return (
<input key={key}
type={options.type}
placeholder={options.placeholder}
className={React.addons.classSet(classSet)}
valueLink={this.linkState(key)}
onFocus={_.partial(this.resetError, key)} />
);
}

表单混合

表单混合处理表单状态(可编辑、正在提交、已提交)。您可以使用它在发送请求时禁用输入和按钮,并在发送请求时相应地更新您的 View 。

来源 ( gist )

define(function () {

'use strict';

var _ = require('underscore');

var EDITABLE_STATE = 'editable',
SUBMITTING_STATE = 'submitting',
SUBMITTED_STATE = 'submitted';

var FormMixin = {
getInitialState: function () {
return {
formState: EDITABLE_STATE
};
},

componentDidMount: function () {
if (!_.isFunction(this.sendRequest)) {
throw new Error('To use FormMixin, you must implement sendRequest.');
}
},

getFormState: function () {
return this.state.formState;
},

setFormState: function (formState) {
this.setState({
formState: formState
});
},

getFormError: function () {
return this.state.formError;
},

setFormError: function (formError) {
this.setState({
formError: formError
});
},

isFormEditable: function () {
return this.getFormState() === EDITABLE_STATE;
},

isFormSubmitting: function () {
return this.getFormState() === SUBMITTING_STATE;
},

isFormSubmitted: function () {
return this.getFormState() === SUBMITTED_STATE;
},

submitForm: function () {
if (!this.isFormEditable()) {
throw new Error('Form can only be submitted when in editable state.');
}

this.setFormState(SUBMITTING_STATE);
this.setFormError(undefined);

this.sendRequest()
.bind(this)
.then(function () {
this.setFormState(SUBMITTED_STATE);
})
.catch(function (err) {
this.setFormState(EDITABLE_STATE);
this.setFormError(err);
})
.done();
}
};

return FormMixin;

});

用法

它期望组件提供一个方法:sendRequest,它应该返回一个 Bluebird promise。 (修改它以与 Q 或其他 promise 库一起使用是微不足道的。)

它提供了方便的方法,例如isFormEditableisFormSubmittingisFormSubmitted。它还提供了一种启动请求的方法:submitForm。您可以从表单按钮的 onClick 处理程序中调用它。

关于javascript - 在 Facebook React 中使用混合与组件进行代码重用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21854938/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com