我正在检查React.js并试图弄清楚这个库如何与Isotope.js一起工作。 React的文档说它可以很好地与其他库一起使用,但是将它与自己更改DOM的库一起使用似乎没有使用React的意义。
有人可以向我解释,如何在我的使用Isotope.js作为布局的网络应用程序中利用React?
你可以直接在React中操作dom。这允许集成现有的JS库或React无法很好地处理的自定义需求。
你可以在这里找到一个例子:
这是它的样子:
React与像Isotope这样的库集成的问题是,最终会有2个不同的库试图更新相同的dom子树。由于React使用差异,它有点假设它是单独使用dom。
因此,我们的想法可能是创建一个只渲染一次的React组件,并且永远不会自行更新。您可以通过以下方式确保:
shouldComponentUpdate: function() {
return false;
}
有了这个你可以:
componentDidMount
上,初始化由React安装的dom节点上的同位素就这样。现在React将永远不会再次更新dom的这一部分,并且Isotope可以自由地操纵它,而不会干扰React。
另外,据我所知,Isotope并不打算与动态项目列表一起使用,因此有一个永不更新的React组件是有意义的。
这是与Masonry的工作版本,您应该发现它很容易移植到Isotope(或使用Masonry :))http://jsfiddle.net/emy7x0dc/1/。
以下是使其工作的代码的关键(并允许React完成其工作)。
var Grid = React.createClass({
displayName: 'Grid',
getInitialState: function(){
return {
masonry: null
}
},
// Wrapper to layout child elements passed in
render: function () {
var children = this.props.children;
return (
<div className="grid">
{children}
</div>
);
},
// When the DOM is rendered, let Masonry know what's changed
componentDidUpdate: function() {
if(this.state.masonry) {
this.state.masonry.reloadItems();
this.state.masonry.layout();
}
},
// Set up Masonry
componentDidMount: function() {
var container = this.getDOMNode();
if(!this.state.masonry) {
this.setState({
masonry: new Masonry( container )
});
} else {
this.state.masonry.reloadItems();
}
}
});
这是James发布的上述代码的更新版本:
如果你正在使用webpack,请记得使用modify your webpack config处理Isotope。
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Isotope from 'isotope-layout';
// Container for isotope grid
class ItemGrid extends Component {
constructor(props) {
super(props);
this.state = { isotope: null };
}
render() {
return(
<div className="item-grid">
{this.props.children}
</div>
)
}
// set up isotope
componentDidMount() {
const node = ReactDOM.findDOMNode(this);
if (!this.state.isotope) {
this.setState({
isotope: new Isotope( node )
});
} else {
this.state.isotope.reloadItems();
}
}
// update isotope layout
componentDidUpdate() {
if (this.state.isotope) {
this.state.isotope.reloadItems();
this.state.isotope.layout();
}
}
}
export default ItemGrid;
只需将要保留在同位素内的项目作为子项传递到ItemGrid组件中:
<ItemGrid>
{data.map((object) => {
return <Item
key={object._id}
name={object.name}
imageUrl={object.imageUrl} />
})}
</ItemGrid>
如果可以,请考虑使用react-masonry-component。
您需要在componentDidMount上创建新的Isotope对象,并在componentDidUpdate上重新加载项目。
用我的mixin搞清楚:)
我让Isotope在React工作,跟随Amith在this link的快速教程。关键是在onClick函数中处理过滤:
class Parent extends Component {
constructor(props) {
super(props);
this.onFilterChange = this.onFilterChange.bind(this);
}
// Click Function
onFilterChange = (newFilter) => {
if (this.iso === undefined) {
this.iso = new Isotope('#filter-container', {
itemSelector: '.filter-item',
layoutMode: "fitRows"
});
}
if(newFilter === '*') {
this.iso.arrange({ filter: `*` });
} else {
this.iso.arrange({ filter: `.${newFilter}` });
}
}
render() {
return(
// Filter Buttons
<ul id="portfolio-flters">
<li data-filter="*" onClick={() => {this.onFilterChange("*")}}>All</li>
<li data-filter="filter-one" onClick={() => {this.onFilterChange("filter-one")}}>One</li>
<li data-filter="filter-two" onClick={() => {this.onFilterChange("filter-two")}}>Two</li>
</ul>
// Isotope Grid & items
<div id="filter-container">
<div className='filter-item filter-one'>
// Item Content
</div>
<div className='filter-item filter-two'>
// Item Content
</div>
</div>
)
}
}
它现在的工作方式与我在静态jQuery网站上的工作方式完全相同。如果希望过滤器按钮在激活时更改外观,则只需更新onFilterChange函数中的本地状态,然后根据该按钮渲染按钮。