Ser*_*ets 23 javascript reactjs
我是React.js的新手,并且很难理解几个核心概念来决定我们应该将这个库用于我们的应用程序.我的主要问题是实际处理从服务器获取的模型中的更新.
想象一下,我有一个应该显示五种不同模型的页面.我已经按照本文所述的方式构建了它:http://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html,所以我有"root"组件所有5个模型通过并使用道具,他们将下载到持有此模型的组件.所以,现在更新了2个模型(我从我的模型代码中获取了这些事件,这些模型代码存在于反应组件之外),我需要在UI上反映这一点.做这个的最好方式是什么?
我正在考虑以下选项:
提前谢谢你,希望我能清楚地解释我的问题.
使用相同的组件再次调用renderComponent但不同的数据等同于调用component.setProps().因此要么将所有模型保持为最小公分母中的状态,要么在更改时再次调用setProps/renderComponent.
如果将数据作为道具传递到子组件,则可以简单地在更高级别进行更新,这将强制向使用相同属性对象的所有组件进行渲染。考虑以下简单示例:
var World = React.createClass({
render: function() {
return <strong>{this.props.name}</strong>;
}
});
var Hello = React.createClass({
clickHandler: function() {
this.setProps({ name: 'earth' });
},
render: function() {
return (
<div>
Hello <World name={this.props.name} />
<button onClick={this.clickHandler}>Click me</button>
</div>
);
}
});
Run Code Online (Sandbox Code Playgroud)
现在,当用户单击按钮时,您可以更改Hello
组件上的属性,但是由于您将相同的属性(或数据)对象传递给了子对象,因此他们将对其做出反应并相应地更新其影子DOM。
这是我的意思的小提琴:http : //jsfiddle.net/xkCKR/
如果您有外部数据对象,则可以将其传递到顶部组件。请记住,这并不意味着存在双向绑定:
// simple example of a data model
var Data = { name: 'world' };
var World = React.createClass({
render: function() {
return <strong>{this.props.data.name}</strong>;
}
});
var Hello = React.createClass({
clickHandler: function() {
this.setProps({
data: { name: 'earth' }
});
},
render: function() {
return (
<div>
Hello <World data={this.props.data} />
<button onClick={this.clickHandler}>Click me</button>
</div>
);
}
});
React.renderComponent(<Hello data={Data} />, document.body);
Run Code Online (Sandbox Code Playgroud)
之所以可行,是因为react使用属性的单向绑定。但是,如果说您的子组件将更新其属性,则它不会爬升到其父组件。为此,您将需要ReactLink插件或使用一个Backbone提供的pub / sub接口。
目前,我至少知道三种将新数据传递到组件的方法:
对于第三个选项,我受到了StevenH的回答的启发,并对其进行了扩展。请通过j sfiddle.net/kb3gN/12002/检查我的实现。
var Data = { value: 1 };
var dataChange = function(callback){
if(callback){
callback(Data);
setInterval(function(){
Data.value++;
callback(Data);
}, 1000);
}
return Data;
};
var World = React.createClass({
render: function() {
return <strong>{this.props.data.value}</strong>;
}
});
var Hello = React.createClass({
getInitialState: function() {
return {
data: this.props.dataChange()
};
},
componentDidMount: function() {
this.props.dataChange(this.updateHandler)
},
updateHandler: function(data) {
this.setState({
data: data
});
},
render: function() {
return (
<div>
Value: <World data={this.state.data} />
</div>
);
}
});
React.renderComponent(<Hello dataChange={dataChange} />, document.body);
Run Code Online (Sandbox Code Playgroud)
在jsfiddle.net/kb3gN/12007上还有一个扩展版本。
function ListenersService(){
var listeners = {};
this.addListener = function(callback){
var id;
if(typeof callback === 'function'){
id = Math.random().toString(36).slice(2);
listeners[id] = callback;
}
return id;
}
this.removeListener = function( id){
if(listeners[id]){
delete listeners[id];
return true;
}
return false;
}
this.notifyListeners = function(data){
for (var id in listeners) {
if(listeners.hasOwnProperty(id)){
listeners[id](data);
}
}
}
}
function DataService(ListenersService){
var Data = { value: 1 };
var self = this;
var listenersService = new ListenersService();
this.addListener = listenersService.addListener;
this.removeListener = listenersService.removeListener;
this.getData = function(){
return Data;
}
setInterval(function(){
Data.value++;
listenersService.notifyListeners(Data);
}, 1000);
}
var dataSevice = new DataService(ListenersService);
var World = React.createClass({
render: function() {
return <strong>{this.props.data.value}</strong>;
}
});
var Hello = React.createClass({
getInitialState: function() {
return {
data: this.props.dataService.getData()
};
},
componentDidMount: function() {
this.props.dataService.addListener(this.updateHandler)
},
updateHandler: function(data) {
this.setState({
data: data
});
},
render: function() {
return (
<div>
Value: <World data={this.state.data} />
</div>
);
}
});
React.renderComponent(<Hello dataService={dataSevice} />, document.body);
Run Code Online (Sandbox Code Playgroud)
此实现未完全遵循隔离组件的概念(因为Hello组件依赖于DataService API),但是可以进一步抽象,并且取决于应用程序开发人员其组件将遵循哪些特定于应用程序的约定。例如,请参见jsfiddle.net/kb3gN/12015中第一个示例和第二个示例的混合(halloDataStatic对象和halloDataDynamic回调)
注意:示例中使用的ListenersService遵循观察者模式,并且在许多情况下,模式本身比利弊多。但是除此之外,我想通过这些示例展示的是,有一种方法可以将数据与回调绑定
<div id="static"></div>
<div id="dynamic"></div>
<script>
function ListenersService(){
var listeners = {};
this.addListener = function(callback){
var id;
if(typeof callback === 'function'){
id = Math.random().toString(36).slice(2);
listeners[id] = callback;
}
return id;
}
this.removeListener = function( id){
if(listeners[id]){
delete listeners[id];
return true;
}
return false;
}
this.notifyListeners = function(data){
for (var id in listeners) {
if(listeners.hasOwnProperty(id)){
listeners[id](data);
}
}
}
}
function DataService(ListenersService){
var Data = { value: 1 };
var self = this;
var listenersService = new ListenersService();
this.addListener = listenersService.addListener;
this.removeListener = listenersService.removeListener;
this.getData = function(){
return Data;
}
setInterval(function(){
Data.value++;
listenersService.notifyListeners(Data);
}, 100);
}
var dataSevice = new DataService(ListenersService);
var halloDataDynamic = function(callback){
var data = dataSevice.getData();
if(callback){
dataSevice.addListener(function(data){
callback(data);
});
}
return data;
};
var halloDataStatic = dataSevice.getData();
var World = React.createClass({
render: function() {
return <strong>{this.props.data.value}</strong>;
}
});
var Hello = React.createClass({
getInitialState: function() {
var data;
if(typeof this.props.halloData === 'function'){
data = this.props.halloData(this.updateHandler)
}
else data = this.props.halloData;
return {
data: data
};
},
updateHandler: function(data) {
this.setState({
data: data
});
},
render: function() {
return (
<div>
Value {this.props.name}: <World data={this.state.data} />
</div>
);
}
});
</script>
React.renderComponent(<Hello halloData={halloDataStatic} name="static"/>, document.getElementById('static'));
React.renderComponent(<Hello halloData={halloDataDynamic} name="dynamic"/>, document.getElementById('dynamic'));
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
21875 次 |
最近记录: |