Mvvm KnockoutJS-ViewModel抽象

Mvvm KnockoutJS-ViewModel抽象,mvvm,knockout.js,viewmodel,abstraction,Mvvm,Knockout.js,Viewmodel,Abstraction,*更新*(见下文) 我了解KnockoutJS的基本知识。创建表视图模型时,可以使用 现在,我试图抽象表视图模型,以便可以创建具有相同行为(排序、编辑、分页等)的多个表。所以我的目标是这样的: HTML 我的第一次尝试是模仿KnockoutJS文档用于[Paged grid]示例的[simpleGrid]插件(@) 我不是很确定,但我认为抽象的基本概念在这个插件中没有得到很好的体现。当我试图将css类包含到元素中时,比如:,,等等,我发现使用数据绑定属性并不容易(不可能?) 数据绑定属性可能不应

*更新*(见下文)

我了解KnockoutJS的基本知识。创建表视图模型时,可以使用

现在,我试图抽象表视图模型,以便可以创建具有相同行为(排序、编辑、分页等)的多个表。所以我的目标是这样的:

HTML

我的第一次尝试是模仿KnockoutJS文档用于[Paged grid]示例的[simpleGrid]插件(@)

我不是很确定,但我认为抽象的基本概念在这个插件中没有得到很好的体现。当我试图将css类包含到
元素中时,比如:
,等等,我发现使用
数据绑定
属性并不容易(不可能?)

数据绑定
属性可能不应该用于这些东西,因为这些类不会改变——它们是更高抽象级别的一部分:我们应该使用jQuery.tmpl或下划线的模板系统插入这些类。但后来我得到一个错误,说[这个模板系统不支持使用
foreach
绑定](或者类似的东西)

因此,我的第二次尝试是按照应该实现的方式实现抽象:表属性(列等)位于表数据之外的另一个“抽象级别”:

  • 在实例化一个新的特定表视图模型时,使用“抽象”模板创建基本的
    html——我只是用下划线的.template做了这个
  • 让这个特定的viewmodel像往常一样使用上面的html
  • 在咖啡脚本中:

    do ->
      ko.dataTable =
        ViewModel: (config) ->
          @id = config.id
          @columns = config.columns
          @pageSize = config.pageSize ? 9999
          @sortColumn = ko.observable (config.sortColumn ? @columns[0].col)
          @sortOrder = ko.observable (config.sortOrder ? "asc")
          @data = ko.observableArray (config.data ? [])
          null
    
      ko.bindingHandlers.dataTable =
        init: (el, acc) ->
          viewModel = acc()
          $(el).find("div:first").html dataTableTemplateMaker viewModel
          # ??? [A] ko.applyBindings viewModel, $(el).find("table")[0]
          # ??? [B] controlsDescendantBindings: yes
          null
        update: (el, acc) ->
          viewModel = acc()
          # ??? [C]
          null
    
    然后:

    <div data-bind="dataTable: groupTable">
    
    。。。其中
    标记了我的困惑所在

    假设我不插入行
    [A]
    [B]
    。当然,KnockoutJS告诉我,我的特定viewmodel(插入到
    中)的html中的绑定都是乱七八糟的。如果我插入行
    [A]
    [B]
    ,那么它对初始数据有效(在
    [D]
    ),但之后就没有响应

    总而言之:我对抽象viewmodel这样简单的事情很困惑。在KnockoutJS中是否有一个标准的解决方案?(我在谷歌上搜索过,但找不到任何东西…)或者我只是把它搞砸了(很可能)?;)

    *更新*

    我解决了这个问题(但可能根本不是最好的/好的-你的意见是什么?),为了完整性:(一个浓缩版本-当然你可能还想单独观察行等等)

    HTML(是的,这是特意传递给绑定处理程序的字符串)

    
    
    咖啡脚本

    class主视图模型
    构造函数:->
    @viewModelPropertyHoldingTableViewModel=新的TableViewModel
    无效的
    类TableViewModel
    构造函数:(选项)->
    @columns=options.columns
    @rows=ko.observearray(options.rows?[]))
    [...]
    无效的
    tableTemplateMaker=\u0.template'
    [%\.map(tableViewModel.columns,函数(列){%]
    [%=column.title%]
    [% } %]
    [%\.map(tableViewModel.columns,函数(列){%]
    [% } %]
    '
    ko.bindingHandlers.myTableBinding=
    init:(元素,viewModelPropertyNameAccessor,\ uMainViewModel)->
    tableViewModelProperty=viewModelPropertyNameAccessor()
    tableViewModel=mainViewModel[tableViewModelProperty]
    $(元素).html tableTemplateMaker
    tableViewModelProperty:tableViewModelProperty
    tableViewModel:tableViewModel
    无效的
    m=新的主视图模型
    ko.applyBindings m
    m、 viewModelPropertyHoldingTableViewModel.data.push[…]
    
    为什么要重新发明轮子?:p


    为什么要重新发明轮子?:p


    你说“之后没有响应”是什么意思?你是在做
    var vm=new ViewModel()
    vm.groupTable.data(newData);
    ?实际上(!)我是在做
    vm.groupTable.data().push
    …但现在我明白这有多愚蠢;)是的,但你实际上可以做
    vm.groupTable.data.push
    。没有
    ()
    应该按预期工作。:)simplegrid实现的具体问题是什么?您提到了抽象,但您的实现似乎完全是“抽象的”作为简单的网格。不知道为什么要将viewmodel作为字符串传递,你真的不需要。另外,我建议下次不要在CS中显示代码,因为这会减轻社区的负担,让他们知道一种中间语言来帮助你。你说的“之后不响应”是什么意思你在做
    var vm=new ViewModel()
    vm.groupTable.data(newData);
    ?实际上(!)我在做
    vm.groupTable.data().push
    …但现在我明白这有多愚蠢;)是的,但你实际上可以做
    vm.groupTable.data.push
    。如果没有
    (),
    应按预期工作。:)您对simplegrid实现的具体问题是什么?您提到了抽象,但您的实现似乎与简单网格一样“抽象”。不确定为什么要将viewmodel作为字符串传递,实际上不需要这样做。另外,我建议下次不要在CS中显示代码,因为这样可以减轻社区为帮助您而必须了解中间语言的负担。
    do ->
      ko.dataTable =
        ViewModel: (config) ->
          @id = config.id
          @columns = config.columns
          @pageSize = config.pageSize ? 9999
          @sortColumn = ko.observable (config.sortColumn ? @columns[0].col)
          @sortOrder = ko.observable (config.sortOrder ? "asc")
          @data = ko.observableArray (config.data ? [])
          null
    
      ko.bindingHandlers.dataTable =
        init: (el, acc) ->
          viewModel = acc()
          $(el).find("div:first").html dataTableTemplateMaker viewModel
          # ??? [A] ko.applyBindings viewModel, $(el).find("table")[0]
          # ??? [B] controlsDescendantBindings: yes
          null
        update: (el, acc) ->
          viewModel = acc()
          # ??? [C]
          null
    
    <div data-bind="dataTable: groupTable">
    
    class ViewModel
      constructor: ->
        @groupTable = new ko.dataTable.ViewModel
          id: "grouptable"
          columns: [
            { col: "num",     title: "Groep", editable: yes }
            { col: "subject", title: "Vak" }
            { col: "year",    title: "Jaar" }
            { col: "level",   title: "Niveau" }
            { col: "day",     title: "Dag" }
            { col: "hour",    title: "Uur" }
            { col: "place",   title: "Lokaal", editable: yes }
          ]
          pageSize: 10
          sortColumn: "num"
          sortOrder: "asc"
          data: [] # [D]
    
    <div data-bind="myTableBinding: 'viewModelPropertyHoldingTableViewModel'"></div>
    
    class MainViewModel
      constructor: ->
        @viewModelPropertyHoldingTableViewModel = new TableViewModel <options>
        null
    
    class TableViewModel
      constructor: (options) ->
        @columns = options.columns
        @rows = ko.observableArray (options.rows ? [])
        [...]
        null
    
    tableTemplateMaker = _.template '
      <table>
        <thead>
          <tr>
            [% _.map(tableViewModel.columns, function (column) { %]
            <th>[%= column.title %]</th>
            [% } %]
          </tr>
        </thead>
        <tbody data-bind="foreach: rows">
          <tr>
            [% _.map(tableViewModel.columns, function (column) { %]
            <td data-bind="text: [%= column.id %]"></td>
            [% } %]
          </tr>
        </tbody>
      </table>
    '
    
    ko.bindingHandlers.myTableBinding =
      init: (element, viewModelPropertyNameAccessor, _, mainViewModel) ->
        tableViewModelProperty = viewModelPropertyNameAccessor()
        tableViewModel = mainViewModel[tableViewModelProperty]
        $(element).html tableTemplateMaker
          tableViewModelProperty: tableViewModelProperty
          tableViewModel: tableViewModel
        null
    
    m = new MainViewModel
    ko.applyBindings m
    
    m.viewModelPropertyHoldingTableViewModel.data.push [...]