如何设计像电子商务网站这样的通用过滤器使用ReactJs?

时间:2017-08-30 07:45:52

标签: javascript reactjs redux rxjs lodash

我计划构建像Gbif这样的通用过滤器。 我的问题是如何解决这个问题。 我喜欢在这个项目中使用ReactJs。 为了设计这样的通用滤波器,我需要与React和redux一起研究其他技术。

我尝试仅使用React和redux设计此过滤器。

在我的方法中,我尝试在get_data方法的状态变量中维护查询参数,我从中获取服务器中的数据。当有人点击任何过滤器按钮,然后我从该过滤器组件传递自定义事件以及查询参数,并在get_data方法中处理此事件。在get_data方法中,我将此值保存在get_data状态参数中,并再次获取新的过滤数据。

现在上述方法的问题在于,随着参数数量的增加,维护变得非常困难。

我的get_data构造函数看起来像这样。

 constructor(props){
      super(props);
      this.state={
        params:{
          max:10,
          offset:0,
          taxon:[],
          sGroup:[],
          classification:undefined,
          userGroupList:[],
          isFlagged:undefined,
          speciesName:undefined,
          isMediaFilter:undefined,
          sort:"lastRevised",
          webaddress:""

        },
        title:[],
        groupName:[],
        userGroupName:[],
        view:1
      }


      this.props.fetchObservations(this.state.params)
      this.loadMore=this.loadMore.bind(this);
    };

我从过滤器组件获取数据的方式是这样的。

这是我的handleInput方法,它从一个过滤器中激活onSelect方法。

handleInput(value,groupName){
    this.setState({
      active:true
    })
    this.props.ClearObservationPage();
    var event = new CustomEvent("sGroup-filter",{ "detail":{
        sGroup:value,
        groupName:groupName
    }
  });
  document.dispatchEvent(event);
  };

我在get_data组件中处理此事件的方式看起来像这样。

sGroupFilterEventListner(e){
        const params=this.state.params;
        if(!params.sGroup){
          params.sGroup=[];
        }
        console.log("params.sGroup",params.taxon)
        params.sGroup.push(e.detail.sGroup)
        params.sGroup=_.uniqBy(params.sGroup)
        const groupName=this.state.groupName;
        var titleobject={};
        titleobject.sGroup=e.detail.sGroup;
        titleobject.groupName=e.detail.groupName;
        groupName.push(titleobject);
        let newgroupname=_.uniqBy(groupName,"sGroup")

        params.classification=params.classification;
        let isFlagged=params.isFlagged;
        let speciesName=params.speciesName;
        let MediaFilter=params.isMediaFilter;

        let taxonparams=params.taxon;
        taxonparams= taxonparams.join(",");
        let sGroupParams=params.sGroup;
            sGroupParams=sGroupParams.join(",");
        let userGroupParams=params.userGroupList;
         userGroupParams=userGroupParams.join(",");

        let newparams={
                  max:10,
                  sGroup:sGroupParams,
                  classification:params.classification,
                  offset:0,
                  taxon:taxonparams,
                  userGroupList:userGroupParams,
                  isFlagged:isFlagged,
                  speciesName:speciesName,
                  isMediaFilter:MediaFilter,
                  sort:params.sort

                }

        this.props.fetchObservations(newparams);
        this.setState({
                params:{
                  max:10,
                  sGroup:params.sGroup,
                  classification:params.classification,
                  offset:0,
                  taxon:params.taxon,
                  userGroupList:params.userGroupList,
                  isFlagged:isFlagged,
                  speciesName:speciesName,
                  isMediaFilter:MediaFilter,
                  sort:params.sort

                },
              groupName:newgroupname
        })
      }

我在componentDidMount和componentunmount方法中注册并取消注册了sGroupFilterEventListner。

目前我也没有考虑如果某人输入网址栏,过滤器面板会自动更改的情况。

请考虑以上所有情况并建议我采用相同的通用方法。感谢。

My Current Filter Panle看起来像这样 enter image description here

1 个答案:

答案 0 :(得分:2)

这是一个简单的例子(仅React,没有Redux)我用动态数量的过滤器(在filters数组中定义,但你自然可以从任何地方获得)。

const filters = [
  { id: "name", title: "Name", type: "string" },
  {
    id: "color",
    title: "Color",
    type: "choice",
    choices: ["blue", "orange"],
  },
  {
    id: "height",
    title: "Height",
    type: "choice",
    choices: ["tiny", "small", "big", "huge"],
  },
  {
    id: "width",
    title: "Width",
    type: "choice",
    choices: ["tiny", "small", "big", "huge"],
  },
];

const filterComponents = {
  string: ({ filter, onChange, value }) => (
    <input
      value={value || ""}
      onInput={e => onChange(filter.id, e.target.value)}
    />
  ),
  choice: ({ filter, onChange, value }) => (
    <select
      value={value || ""}
      onInput={e => onChange(filter.id, e.target.value)}
      size={1 + filter.choices.length}
    >
      <option value="">(none)</option>
      {filter.choices.map(c => (
        <option value={c} key={c}>
          {c}
        </option>
      ))}
    </select>
  ),
};

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { filters: {} };
    this.onChangeFilter = this.onChangeFilter.bind(this);
  }
  onChangeFilter(filterId, value) {
    const newFilterState = Object.assign({}, this.state.filters, {
      [filterId]: value || undefined,
    });
    this.setState({ filters: newFilterState });
  }
  renderFilter(f) {
    const Component = filterComponents[f.type];
    return (
      <div key={f.id}>
        <b>{f.title}</b>
        <Component
          filter={f}
          value={this.state.filters[f.id]}
          onChange={this.onChangeFilter}
        />
      </div>
    );
  }
  render() {
    return (
      <table>
        <tbody>
          <tr>
            <td>{filters.map(f => this.renderFilter(f))}</td>
            <td>Filters: {JSON.stringify(this.state.filters)}</td>
          </tr>
        </tbody>
      </table>
    );
  }
}

ReactDOM.render(<App />, document.querySelector("main"));
body {
  font: 12pt sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<main/>

(最初在https://codepen.io/akx/pen/JyemQQ?editors=0010

希望这可以帮助你。

相关问题