React.js和Isotope.js

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)

  • 看来它没有用,请您重新审视小提琴。 (2认同)
  • 我们可以重温一下小提琴吗? (2认同)

Sea*_*Lee 7

我的 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)


Seb*_*ber 6

你可以直接在React中操作dom.这允许集成现有的JS库或React无法很好地处理的自定义需求.

你可以在这里找到一个例子:

https://github.com/stample/gulp-browserify-react-phonegap-starter/blob/master/src/js/home/homeComponents.jsx#L22

这是它的样子:

图片


React与像Isotope这样的库集成的问题是,最终会有2个不同的库试图更新相同的dom子树.由于React使用差异,它有点假设它是单独使用dom.

因此,我们的想法可能是创建一个只渲染一次的React组件,并且永远不会自行更新.您可以通过以下方式确保:

shouldComponentUpdate: function() { 
    return false; 
}
Run Code Online (Sandbox Code Playgroud)

有了这个你可以:

  • 使用React生成同位素项html元素(您也可以在没有React的情况下创建它们)
  • 打开componentDidMount,在React安装的dom节点上初始化同位素

就这样.现在React将永远不会再次更新dom的这一部分,并且Isotope可以自由地操纵它,而不会干扰React.

另外,据我所知,Isotope并不打算与动态项目列表一起使用,因此有一个永不更新的React组件是有意义的.


Hub*_*ert 6

这是詹姆斯发布的上述代码的更新版本:

如果您使用的是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