use*_*733 13 javascript jquery-isotope reactjs
我正在检查React.js并试图弄清楚这个库如何与Isotope.js一起工作.React的文档说它可以很好地与其他库一起使用,但是将它与自己更改DOM的库一起使用似乎没有使用React的意义.
有人可以向我解释一下,如何在我使用Isotope.js作为布局的webapp中利用React?
Jam*_*oad 10
这是与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();
}
}
});
Run Code Online (Sandbox Code Playgroud)
我的 useRef、useState 和 useEffect 钩子解决方案。它还适用于动态生成的过滤器键和项目。诀窍是在组件安装后初始化 Isotope 并在每次过滤器关键字更改时调用其“排列”方法。
演示:https : //codepen.io/ilovepku/pen/zYYKaYy
const IsotopeReact = () => {
// init one ref to store the future isotope object
const isotope = React.useRef()
// store the filter keyword in a state
const [filterKey, setFilterKey] = React.useState('*')
// initialize an Isotope object with configs
React.useEffect(() => {
isotope.current = new Isotope('.filter-container', {
itemSelector: '.filter-item',
layoutMode: 'fitRows',
})
// cleanup
return () => isotope.current.destory()
}, [])
// handling filter key change
React.useEffect(() => {
filterKey === '*'
? isotope.current.arrange({filter: `*`})
: isotope.current.arrange({filter: `.${filterKey}`})
}, [filterKey])
const handleFilterKeyChange = key => () => setFilterKey(key)
return (
<>
<ul>
<li onClick={handleFilterKeyChange('*')}>Show Both</li>
<li onClick={handleFilterKeyChange('vege')}>Show Veges</li>
<li onClick={handleFilterKeyChange('fruit')}>Show Fruits</li>
</ul>
<hr />
<ul className="filter-container">
<div className="filter-item vege">
<span>Cucumber</span>
</div>
<div className="filter-item fruit">
<span>Apple</span>
</div>
<div className="filter-item fruit">
<span>Orange</span>
</div>
<div className="filter-item fruit vege">
<span>Tomato</span>
</div>
</ul>
</>
)
}
Run Code Online (Sandbox Code Playgroud)
你可以直接在React中操作dom.这允许集成现有的JS库或React无法很好地处理的自定义需求.
你可以在这里找到一个例子:
这是它的样子:
React与像Isotope这样的库集成的问题是,最终会有2个不同的库试图更新相同的dom子树.由于React使用差异,它有点假设它是单独使用dom.
因此,我们的想法可能是创建一个只渲染一次的React组件,并且永远不会自行更新.您可以通过以下方式确保:
shouldComponentUpdate: function() {
return false;
}
Run Code Online (Sandbox Code Playgroud)
有了这个你可以:
componentDidMount
,在React安装的dom节点上初始化同位素就这样.现在React将永远不会再次更新dom的这一部分,并且Isotope可以自由地操纵它,而不会干扰React.
另外,据我所知,Isotope并不打算与动态项目列表一起使用,因此有一个永不更新的React组件是有意义的.
这是詹姆斯发布的上述代码的更新版本:
如果您使用的是webpack,请记住要修改webpack的配置以使用Isotope。
import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';
import Isotope from 'isotope-layout';
// Container for isotope grid
class ItemGrid extends PureComponent {
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;
Run Code Online (Sandbox Code Playgroud)
只需将要保留在同位素中的项作为子项传递到ItemGrid组件中:
<ItemGrid>
{data.map(object => (
<Item key={object._id} name={object.name} imageUrl={object.imageUrl} />
))}
</ItemGrid>
Run Code Online (Sandbox Code Playgroud)
如果可以,请考虑使用react-masonry-component。
归档时间: |
|
查看次数: |
8733 次 |
最近记录: |