beforeChange in manual subscribe in knockoutjs with strange behavior

时间:2012-12-06 21:19:50

标签: knockout.js coffeescript ko.observablearray

在我的viewmodel中有一个文件列表,文件类型和未使用的文件类型:

viewModel =
  files: ko.observableArray([
        new File({name: "A1", id: 1})
        new File({name: "B1", id: 2})
        new File({name: "C1", id: 3})
        new File({name: "D1", id: 4})
    ])
  types:  ko.observableArray(dataTypes)
  typesUnused: ko.observableArray(dataTypes)

我创建了一个File类,其中包含type属性。 要填充列表未使用的文件类型,请为type属性订阅beforeChange和其他afterChange

class File
  constructor: (data) ->
    @name = data.name
    @id = data.id
    @type = ko.observable(null)

    # Updates array of types not used
    @type.subscribe ((oldValue) ->
      console.log "OLD: #{oldValue}"
      viewModel.typesUnused.remove (item) -> item is oldValue if oldValue
    ), @, "beforeChange"
    @type.subscribe (newValue) ->        
      console.log "NEW: #{newValue}"
      if newValue && viewModel.typesUnused.indexOf(newValue) < 0 
        viewModel.typesUnused.push newValue


这个想法是,无论何时更改文件类型,都会在更改发生之前触发事件,并在未使用的文件类型列表中添加旧类型。更改后将发生另一个事件,将从未使用的类型列表中删除新类型。

问题

  1. 所有文件都附带定义的文件类型数组中的第一个类型。在这种情况下,“jpeg”
  2. 通过更改文件类型,所有其他人都会受到更改!
  3. 从列表typesUnused中删除文件类型时,types列表也可能会更改!
  4. 请参阅:http://jsfiddle.net/4nyVE/2/

1 个答案:

答案 0 :(得分:2)

您的问题是typestypesUnused使用相同的数组dataTypes初始化。从typesUnused移除项目时,这也会影响types,因为它们包含对同一数组的引用。

此时,其他选项中当前选定的选项不再有效(不再在types中),因此该值设置为第一个选项。

您最好的选择可能是使用原始数组的副本初始化typesUnusedmyarray.slice(0)是一种简单的复制方式),例如:

typesUnused: ko.observableArray(dataTypes.slice(0))