【问题标题】:reactjs conditional component methods based on configuration objectreactjs 基于配置对象的条件组件方法
【发布时间】:2014-12-18 08:45:00
【问题描述】:

我正在设置一个可排序的可过滤表,并且我正在尝试制作它,以便我可以在组件上定义对象以构建所有必要的功能。

我想拿这个,

RailsTable = React.createClass
  mixins: [
    Backbone.React.Component.mixin
  ]

  setSearchTermFilter: (e)->
    search_term = e.target.value
    @setState(search_term: search_term)

  setGroupNumberFilter: (e)->
    rail_group = parseInt(e.target.value)
    @setState(rail_group: rail_group)

  setSystemNameFilter: (e)->
    system_name = e.target.value
    @setState(system_name: system_name)

  filteredResults: ->
    filteredResults = @getCollection()
    filteredResults = filteredResults.bySearchTerm(@state.search_term)
    filteredResults = filteredResults.byRailGroup(@state.rail_group)
    filteredResults = filteredResults.bySystemName(@state.system_name)

    filteredResults.sortDirection = @state.sortDirection
    filteredResults.sortBy(@state.sortAttribute)
    filteredResults



  render: ->
    blah

把它变成这样,

RailsTable = React.createClass
  mixins: [
    Backbone.React.Component.mixin
    Evue.Mixins.FilterMixin
  ]

  filterTypes:
    'search_term'  : ''
    'system_name'  : ''
    'rail_group'   : 0

  render: ->
    blah

我认为这很好,但问题出现在 mixin 中。我需要遍历 filterTypes 对象并基于它创建函数。因此,如果我有 search_term,那么我需要一个 setSearchTermFilter 函数,但是每个表都会有不同的属性,所以我需要根据我输入的内容来创建它们。

这是我想要的想法,但不起作用,

Evue.Mixins.FilterMixin =

  getInitialState: ->
    @searchTypes

  @filterTypes.each (filterObject)->
    setFilterObject: (newFilterObject)->
      @setState(filterObject: newFilterObject)

我什至不知道这是否可行,我真的认为我只是在接近这个错误。

【问题讨论】:

    标签: function coffeescript reactjs


    【解决方案1】:

    让我们瞄准这个设计。 mixin 是专门为组件创建的,这使得它更加动态(包括具有动态功能)。

    RailsTable = React.createClass
      mixins: [
        Backbone.React.Component.mixin
        Evue.Mixins.makeFilterMixin {
          'search_term'  : ''
          'system_name'  : ''
          'rail_group'   : 0
        }
      ]
      render: ->
        blah
    

    首先,我们必须创建这个函数,并获取过滤器的名称,包括初始的蛇形大小写和 PascalCase。

    Evue.Mixins.makeFilterMixin = (filters) ->
      mixin = {}
      filterNames = Object.keys filters
      filterNamesToPascal = {}
    
      filterNames.forEach (name) ->
        filterNamesToPascal[name] = pascalCase(name)
    

    初始状态函数很简单。

      mixin.getInitialState = ->
        state = {}
        for name in filterNames
          state[name] = filters[name]
        state
    

    这是我们第一次使用 filterNamesToPascal 的地方。对于 search_term 过滤器,filterFnName 将类似于 "bySearchTerm"。然后我们将状态值传递给它,并继续循环过滤。

      mixin.filteredResults = ->
        filteredResults = @getCollection()
        for filter in filterNames
          filterFnName = "by" + filterNamesToPascal[filter]
          filteredResults = filteredResults[filterFnName](this.state[filter])
    
        filteredResults.sortDirection = @state.sortDirection
        filteredResults.sortBy(@state.sortAttribute)
        filteredResults
    

    这是我们需要一个返回 mixin 的函数的主要原因。要即时创建像setSearchTermFilter 这样的函数,我们需要直接在mixin 上设置它们。我们使用默认值的构造函数将其转换回正确的类型。这适用于 String 和 Number 等原始构造函数。您放弃了对数字类型强制使用整数的能力。为此,您必须拥有一个功能齐全的架构。

      filterNames.forEach (name) ->
        constructor = filters[name]?.constructor || String
        mixin["set" + filterNamesToPascal[name] + "Filter"] = (e) ->
          update = {}
          update[name] = constructor e.target.value
          @setState update
      mixin    
    

    最后,还有一个简单的实用函数,用于对 PascalCase 进行snake_case。

    pascalCase = (s) ->
      words = s.split("_").map (x) ->
        x[0].toUpperCase() + x.slice(1)
      words.join("")
    

    【讨论】:

    • 非常感谢!那么我需要将 { search_term: '', rail_group: 0 } 对象放入 mixin 中还是可以将其留在组件中?我把它放在组件上,但我认为你这样做是为了更好的代码结构。此外,我最终创建了函数“setStringFilter”和“setIntegerFilter”。当我有各种类型的未来输入时,这可能更安全,对吧?无论哪种方式,感谢您的回复。
    • 将字符串翻译成函数也安全吗?我听说这样做可能不安全,但我不知道。
    • @BlaineHatab 是的,你需要将它传递给 mixin;我解释了原因。是的,简单性和灵活性之间总是需要权衡取舍。字符串没有被翻译成函数,它们被翻译成属性名。在这种情况下,它们不是用户提供的,并且最终无法覆盖导致意外行为或错误的其他内容,因此它是安全的。
    • 再次感谢您。我仍然不是 100% 确定你为什么需要将它传递给 mixin。我要问的唯一原因是我根据组件上的 @filterTypes 对象自动生成一些 html。不过,如果我将它传递给 mixin,我认为我无法做到这一点。
    • 您可以将对象存储在一个变量中,并在多个地方使用它。您需要使用它来创建 mixin 的原因是因为 mixin 提供的功能依赖于该对象。
    猜你喜欢
    • 2018-10-27
    • 2017-11-06
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 2021-09-07
    • 1970-01-01
    相关资源
    最近更新 更多