Facebook React鼓励您将可变(state
)和不可变(props
)状态分开:
尽量让您的组件尽可能多的无状态。通过这样做,您可以将状态隔离到最符合逻辑的位置,并最大限度地减少冗余,从而更容易对应用程序进行推理。
当状态改变时,您应该调用setState
来触发虚拟DOM diff,只有在需要时才会导致真正的DOM更新。
有一种方法可以通过调用forceUpdate
手动触发DOM更新,但不鼓励:
通常情况下,您应该尽量避免使用forceUpdate()
,并且只从this.props
和this.state
中的渲染()
读取。这使您的应用程序更加简单和高效。
但是,我看到的所有示例都忽略了这一建议,将模型和集合存储在props
中,并调用forceUpdate
:
甚至React自己的示例也使用了forceUpdate
:
然而,有没有更好的方法,它会带来什么好处?
我是骨干背后的开发者。做出反应。组件。我们使用setProps的原因是因为它仅由组件所有者(最大的父级)调用。在我看来,道具比状态更好地用于反应性更新(并传递给子组件),但是如果你能给我一些状态更好的原因,我很乐意开始朝着这个变化发展。
例如,有时我会将组件委托给其他组件,而transferPropsTo非常方便。使用状态会让实现这一目标变得更加困难。
在有更好的答案之前,让我引用React核心开发人员皮特·亨特的话:
使用骨干模型的最大胜利是它为您管理数据流。当您调用set()
时,它会通知您的应用数据已更改。使用React,您会发现这不太必要,因为您所需要做的就是通过回调通知拥有状态的组件,React确保所有子级都是最新的。因此,骨干的这一部分在IMO中用处不大(无论如何,人们倾向于以这种方式在React中使用骨干)。
您不必传递纯JSON(尽管我倾向于传递纯JSON,并且它对简单数据模型很有效),但是如果您保持对象不变,您将看到很多优势。
您只需在主干模型上调用toJSON()
,看看您对它的喜欢程度,而不是将模型传递给其他人。
(强调我的)
有趣的是,脊梁骨。反应组件是我发现的唯一一个使用toJSON
的示例,但出于某种原因,它也使用setProps
而不是setState
(这也是不鼓励的)。
我根据Pete Hunt的方法(没有setProps
,没有forceUpdate
)做了一个简单的混合:
define(function () {
'use strict';
var Backbone = require('backbone'),
_ = require('underscore');
var BackboneStateMixin = {
getInitialState: function () {
return this.getBackboneState(this.props);
},
componentDidMount: function () {
if (!_.isFunction(this.getBackboneState)) {
throw new Error('You must provide getBackboneState(props).');
}
this._bindBackboneEvents(this.props);
},
componentWillReceiveProps: function (newProps) {
this._unbindBackboneEvents();
this._bindBackboneEvents(newProps);
},
componentWillUnmount: function () {
this._unbindBackboneEvents();
},
_updateBackboneState: function () {
var state = this.getBackboneState(this.props);
this.setState(state);
},
_bindBackboneEvents: function (props) {
if (!_.isFunction(this.watchBackboneProps)) {
return;
}
if (this._backboneListener) {
throw new Error('Listener already exists.');
}
if (!props) {
throw new Error('Passed props are empty');
}
var listener = _.extend({}, Backbone.Events),
listenTo = _.partial(listener.listenTo.bind(listener), _, _, this._updateBackboneState);
this.watchBackboneProps(props, listenTo);
this._backboneListener = listener;
},
_unbindBackboneEvents: function () {
if (!_.isFunction(this.watchBackboneProps)) {
return;
}
if (!this._backboneListener) {
throw new Error('Listener does not exist.');
}
this._backboneListener.stopListening();
delete this._backboneListener;
}
};
return BackboneStateMixin;
});
它不关心你有什么样的型号或系列。
约定是主干模型进入道具
,它们的JSON通过mixin自动进入状态
。您需要覆盖getBackboneState(props)
以使其正常工作,还可以选择watchBackboneProps
告知mixin何时使用新值调用setState
。
用法示例:
var InfoWidget = React.createClass({
mixins: [BackboneStateMixin, PopoverMixin],
propTypes: {
stampModel: React.PropTypes.instanceOf(Stamp).isRequired
},
// Override getBackboneState to tell the mixin
// HOW to transform Backbone props into JSON state
getBackboneState: function (props) {
var stampModel = props.stampModel,
primaryZineModel = stampModel.getPrimaryZine();
return {
stamp: stampModel.toJSON(),
toggleIsLiked: stampModel.toggleIsLiked.bind(stampModel),
primaryZine: primaryZineModel && primaryZineModel.toJSON()
};
},
// Optionally override watchBackboneProps to tell the mixin
// WHEN to transform Backbone props into JSON state
watchBackboneProps: function (props, listenTo) {
listenTo(props.stampModel, 'change:unauth_like_count change:is_liked');
listenTo(props.stampModel.get('zines'), 'all');
},
render: function () {
// You can use vanilla JSON values of this.state.stamp,
// this.state.toggleIsLiked and this.state.primaryZine
// or whatever you return from getBackboneState
// without worrying they may point to old values
}
}
注意:mixin需要下划线1.6.0。
皮特的回答很棒。
骨干模型本质上是突变的,这(虽然本身不是问题)意味着在重新渲染时,您将没有旧版本的模型进行比较。这使得通过在组件的关键位置定义应该组件更新
方法来进行智能优化变得更加困难。(由于其他原因,例如实现撤消,您还失去了轻松存储旧版本模型的能力。)
调用forceUpdate
只会跳过应该组件更新
并强制组件重新呈现。请注意,调用渲染
通常很便宜,并且只有当渲染
的输出发生变化时,React才会触及DOM,所以这里的性能问题并不常见。然而,如果您可以选择使用不可变数据(包括像Pete建议的那样从到JSON()
传递原始模型属性对象),我强烈推荐它。
我一直在思考jvm安全的工作方式。原则是,jvm始终信任并运行任何本地代码。因此,从概念上讲,如果您的代码没有显式或隐式调用<code>checkpermission(permission)</code>,这意味着它永远不会失败任何安全验证。当然,所有这些验证调用通常都是在JavaAPI类中完成的,因此我们不需要为内置权限调用它们。 现在,只要您使用内置类(如<code>FileOutputStr
问题内容: 建议在HTML页面中使用表格(现在已经有了CSS)? 表格有什么用途?表具有哪些CSS所没有的功能? 问题答案: 一点都不。但是将表格用于表格数据。只是不要将它们用于一般布局。 但是,如果您显示表格数据(例如结果或什至是表格),请继续使用表格!
问题内容: Facebook React 鼓励您将可变()和不可变()状态分开: 尝试使尽可能多的组件保持无状态。通过这样做,您可以将状态隔离到最逻辑的位置,并最大程度地减少冗余,从而使推理应用程序更加容易。 当状态更改时,应该调用触发虚拟DOM diff,这仅在需要时才引起真正的DOM更新。 有 是 一种方法来触发DOM更新手动调用,但它是灰心: 通常情况下 ,你应该尽量避免的所有使用和只读,并
是否可以只使用附近连接的BLE,或者不切换到附近连接创建的WiFi直接网络? 对于我的问题,我使用的是P2P_STAR策略,在使用附近的连接时,不可能断开所有“客户端”与internet的连接。 谢谢你。
我用的是spring 5.3.16,spring boot 2.2.10.RELEASE,spring cloud 2.2.10.RELEASE用的是spring-cloud-网飞-zuul,那么,我可以只升级spring版本到5.3.18,而不升级其他框架吗?
我一直收到NoClassDefoundError错误。我试图使用JavaMail API发送电子邮件,但当我使用SMTPMessage类创建Message实例时发生错误。 我知道我需要激活库,但它还是不起作用。 错误发生在这段代码的第一行。 堆栈跟踪