【问题标题】:KnockoutJS - pushing object into observable array isn't databindingKnockoutJS - 将对象推入可观察数组不是数据绑定
【发布时间】:2014-08-11 15:09:27
【问题描述】:

我的视图模型是一个有场景的游戏,每个场景都有一些信息。

视图模型是一个普通的 JSON 对象,通过映射插件映射为可观察的。整个应用程序运行良好,所有数据绑定和其他功能都正常运行。但是……

我正在使用拖放来将消息添加到场景中,因此我在侧面呈现了空消息(不包含在场景消息数组中,而是作为独立对象),并且在放置拖动的消息时我'我把它推到了场景消息可观察数组中,当我查看我的游戏对象时,我可以看到已经添加了一条新消息,但在 ui 中没有任何效果,假设我们从 2 条消息开始数组,并且它们在应用程序的负载中呈现良好,现在我在数组中有 3 条消息,但在 ui 中只显示了 2 条。

以下是部分代码:

这是拖放代码-

(function () {
        var _dragged;
        ko.bindingHandlers.drag = {
            init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
                var dragElement = $(element);
                var dragOptions = {
                    helper: 'clone',
                    appendTo: 'body',
                    revert: true,
                    revertDuration: 0,
                    start: function () {
                        _dragged = ko.utils.unwrapObservable(valueAccessor().value);
                    },
                    cursor: 'default'
                };
                dragElement.draggable(dragOptions).disableSelection();
            }
        };

        ko.bindingHandlers.drop = {
            init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
                var dropElement = $(element);
                var dropOptions = {
                    drop: function (event, ui) {
                        valueAccessor().value.push(ko.mapping.fromJS(_dragged));
                    }
                };
                dropElement.droppable(dropOptions);
            }
        };
    })();

这个消息foreach与drop绑定-

<div id="sceneMessages" data-bind="foreach: game.ContentScenes()[0].ContentMessages(), drop: { value: game.ContentScenes()[0].ContentMessages() }">
    <span data-bind="text: id"></span>
    <br />
</div>

这是带有拖动的空的新消息 -

<ul data-bind="foreach: messagesTypes">
    <li data-bind="text: MessageType.name, drag: { value: $data }"></li>
</ul>

知道我在做什么吗?难道是因为映射插件?!正如我提到的,新消息已正确添加到数组中。

编辑:

实际上,我刚刚意识到,即使是没有拖放的简单推送也无法正常工作..

来自服务器的 JSON 看起来像这样:

"ContentScenes": [
{
  "ContentMessages": [
    {
      "PrivateMessageType": null,
      "MessageType": {
        "id": 1,
        "name": "Public"
      },
      "id": 7,
      "scene_id": 3,
      "parent_id": null,
      "time_offset": null,
      "from": null,
      "to": null,
      "msg_type": 1,
      "is_system": true
    },
    {
      "PrivateMessageType": null,
      "MessageType": {
        "id": 1,
        "name": "Public"
      },
      "id": 8,
      "scene_id": 3,
      "parent_id": null,
      "time_offset": null,
      "from": null,
      "to": null,
      "msg_type": 1,
      "is_system": true
    }
  ],
  "ContentResources": [],
  "id": 3,
  "game_id": 28,
  "name": null,
  "discussion_duration": null,
  "break_duration": null,
  "vote_duration": null,
  "is_template": true
},
{
  "ContentDilemmaOptions": [],
  "ContentMessages": [],
  "ContentResources": [],
  "id": 4,
  "game_id": 28,
  "name": null,
  "discussion_duration": null,
  "break_duration": null,
  "vote_duration": null,
  "is_template": false
}
],
"id": 28,
"mainImage": null,
"sideImage": null,
"description": "Game description",
"name": "Game Name",
"locale": null

这个 JSON 是这样映射的:

 var Scene = function (data){
        ko.mapping.fromJS(data,{},this);
        this.isCurrent = function(){
            return pageOptions.queryString("scene") == this.id();
        };
        this.url = function(){
            return _url + this.id();
        };
    }

 var mappingOptions = {
        'ContentScenes':{
            create:function(options){
                return new Scene(options.data);
            }
        },
        'ContentCharacters': {
            key: function(data) {
                return ko.utils.unwrapObservable(data.id);
            }
        }
    }

 var _gameJson = {

        game: ko.mapping.fromJS(_jsonObject,mappingOptions)
 }

  ko.applyBindings(_gameJson);

那么,知道我在做什么吗?

【问题讨论】:

    标签: knockout.js knockout-mapping-plugin


    【解决方案1】:

    嗯,感谢 KnockoutJS 的“方便”语法,我花了一段时间才注意到它

    这是documentation的引述:

    语法更方便。调用 KO 的 push 方法,只需要写 myObservableArray.push(...)。这比调用 通过编写底层数组的推送方法 myObservableArray().push(...).

    这意味着当你想将一个对象添加到数组中时,你不能以正常和直观的方式通过读取对象获取数组并像这样推送它:myArray() .push(obj),你应该得到 observable 对象并像这样推送到对象:myArray.push(obj)。太棒了!

    【讨论】:

      【解决方案2】:

      因此,当您初始化拖动时,您只是在加载时评估世界的状态,而不是在更新元素时​​...例如,这是我实现的方法

      ko.bindingHandlers.DragEmployee = {
          update: function (element, valueAccessor) {
              var dragElement = $(element);
              if (valueAccessor()) {
      
                  dragElement.toggleClass('draggable', true);
                  dragElement.kendoDraggable({
                      hint: function(e) {
                          return $("<label class='grabbedObject' style='font-weight: bold;'>" + $(e).text() + "</label>");
                      },
                      cursorOffset: { top: -4, left: -20 },
                      dragstart: function(e) { $(e.currentTarget).kendoAddClass('grabbed'); },
                      dragend: function (e) { $(e.currentTarget).kendoRemoveClass('grabbed'); }
                  });
              } else {
                  if (dragElement.data('kendoDraggable')) {
                      dragElement.toggleClass('draggable', false);
                      dragElement.data('kendoDraggable').destroy();
                  }
              }
          }
      
      };
      

      效果很好...但是我正在使用剑道的拖动功能...但这确实无关紧要。我只在 init 中保留我的 drop 方法,但是我传递给它的值是事件的属性......在我的情况下 ::

      $(e.draggable.element[0])
      

      然后,当我想获取绑定到这个元素的数据时

      ko.dataFor(e.draggable.element[0])
      

      Boom...然后我可以访问我正在绑定的整个模型。

      【讨论】:

      • 不幸的是,这不是我的问题,更新不能解决我的问题。我写的代码是这个小提琴的副本:jsfiddle.net/wilsonhut/2nj9J,它工作正常(看看我上面的编辑)
      猜你喜欢
      • 2017-11-25
      • 2012-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-02
      • 1970-01-01
      • 2012-04-24
      • 2012-07-29
      相关资源
      最近更新 更多