ReactJS 可以根据服务器端渲染 DOM 来初始化它的状态吗?
Can ReactJS initialize its state based on a server-side rendered DOM?
我 喜欢 做 isomorphic JavaScript in React 是多么容易。唯一让我困扰的是它的工作原理浏览器必须下载数据两次。首先在 DOM 标记中,然后在 JSON 格式中再次在运行时初始化状态。 DOM 中的所有数据都已经存在,React 难道不能仅基于此进行再水化吗?
我用自定义绑定处理程序 progressive enhancement in KnockoutJS 做了一些实验。我希望有一种方法可以实现与 React 类似的东西。
//Custom binding to load the values into the view model from the DOM
ko.bindingHandlers.PE = {
init: function(element, valueAccessor, allBindings) {
var bindings = allBindings();
if (typeof bindings.text === 'function') {
bindings.text($(element).text());
}
}
};
更新
将从 DOM 中读取值的逻辑放入 React 中似乎并不符合习惯。但是没有什么能阻止你写一点 JavaScript 来自己收集价值!鉴于 example above 你可以做类似下面的事情。
var comments = $('.media').map(function() {
return {
Author: $(this).find('.media-object').attr('src'),
Text: $(this).find('.media-body').text()
};
});
然后使用它来初始化 React 组件客户端。我对此很满意。
渲染是 React 中的一种单向转换。它没有在 DOM 中存储足够的信息来重建创建 DOM 的数据结构。 data-react-id
属性用于 React 的 diffing algorithm 但不用于存储有关用户数据的信息。
根据你的例子(data-react-id
这里是任意的,我手写的):
var Comment = React.createClass({
render: function() {
return (
<div className="comment">
<h3 className="commentAuthor">{this.props.comment.Author}</h3>
{this.props.comment.Text}
</div>
);
}
});
React.render(
<Comment comment={{"Author": "Shellie", "Text": "semper, dui lectus"}} />,
...
);
...
<!-- Output -->
<div class="comment" data-react-id=".x.0">
<h3 class="commentAuthor" data-react-id=".x.0.0">Shellie</h3>
<span data-react-id=".x.0.1">semper, dui lectus</span>
</div>
DOM 中没有关于字符串 "Shellie" 来自何处以及 "semper, dui lectus" 来自何处的信息。此示例产生相同的输出:
var Comment = React.createClass({
render: function() {
return (
<div className="comment">
<h3 className="commentAuthor">Shellie</h3>
semper, dui lectus
</div>
);
}
});
React.render(
<Comment />,
...
);
...
<!-- Output -->
<div class="comment" data-react-id=".x.0">
<h3 class="commentAuthor" data-react-id=".x.0.0">Shellie</h3>
<span data-react-id=".x.0.1">semper, dui lectus</span>
</div>
您真正想要做的是通过脚本标记将您用于呈现的服务器端数据存储在 javascript 变量中,然后从该客户端对象而不是从服务器初始化您的反应。
我 喜欢 做 isomorphic JavaScript in React 是多么容易。唯一让我困扰的是它的工作原理浏览器必须下载数据两次。首先在 DOM 标记中,然后在 JSON 格式中再次在运行时初始化状态。 DOM 中的所有数据都已经存在,React 难道不能仅基于此进行再水化吗?
我用自定义绑定处理程序 progressive enhancement in KnockoutJS 做了一些实验。我希望有一种方法可以实现与 React 类似的东西。
//Custom binding to load the values into the view model from the DOM
ko.bindingHandlers.PE = {
init: function(element, valueAccessor, allBindings) {
var bindings = allBindings();
if (typeof bindings.text === 'function') {
bindings.text($(element).text());
}
}
};
更新
将从 DOM 中读取值的逻辑放入 React 中似乎并不符合习惯。但是没有什么能阻止你写一点 JavaScript 来自己收集价值!鉴于 example above 你可以做类似下面的事情。
var comments = $('.media').map(function() {
return {
Author: $(this).find('.media-object').attr('src'),
Text: $(this).find('.media-body').text()
};
});
然后使用它来初始化 React 组件客户端。我对此很满意。
渲染是 React 中的一种单向转换。它没有在 DOM 中存储足够的信息来重建创建 DOM 的数据结构。 data-react-id
属性用于 React 的 diffing algorithm 但不用于存储有关用户数据的信息。
根据你的例子(data-react-id
这里是任意的,我手写的):
var Comment = React.createClass({
render: function() {
return (
<div className="comment">
<h3 className="commentAuthor">{this.props.comment.Author}</h3>
{this.props.comment.Text}
</div>
);
}
});
React.render(
<Comment comment={{"Author": "Shellie", "Text": "semper, dui lectus"}} />,
...
);
...
<!-- Output -->
<div class="comment" data-react-id=".x.0">
<h3 class="commentAuthor" data-react-id=".x.0.0">Shellie</h3>
<span data-react-id=".x.0.1">semper, dui lectus</span>
</div>
DOM 中没有关于字符串 "Shellie" 来自何处以及 "semper, dui lectus" 来自何处的信息。此示例产生相同的输出:
var Comment = React.createClass({
render: function() {
return (
<div className="comment">
<h3 className="commentAuthor">Shellie</h3>
semper, dui lectus
</div>
);
}
});
React.render(
<Comment />,
...
);
...
<!-- Output -->
<div class="comment" data-react-id=".x.0">
<h3 class="commentAuthor" data-react-id=".x.0.0">Shellie</h3>
<span data-react-id=".x.0.1">semper, dui lectus</span>
</div>
您真正想要做的是通过脚本标记将您用于呈现的服务器端数据存储在 javascript 变量中,然后从该客户端对象而不是从服务器初始化您的反应。