代码之家  ›  专栏  ›  技术社区  ›  JackTheKnife

KnockoutJS和PubSub更新视图之间的可观察数组

  •  0
  • JackTheKnife  · 技术社区  · 6 年前

    我有两个 modalviews - MyModalViewA (母公司)和 MyModalViewB

    MyModalViewA公司 产卵 MyModalViewB公司 ,作为自定义绑定,还有我需要更新的可观察数组。看起来像是:

    (function () {
    
                'use strict';
    
                var
                    window = __webpack_require__(/*! window */ 10),
                    _ = __webpack_require__(/*! _ */ 2),
                    $ = __webpack_require__(/*! $ */ 12),
                    ko = __webpack_require__(/*! ko */ 3),
                    key = __webpack_require__(/*! key */ 16),
    
                    Enums = __webpack_require__(/*! Common/Enums */ 4),
                    Utils = __webpack_require__(/*! Common/Utils */ 1),
    
                    Links = __webpack_require__(/*! Common/Links */ 13),
                    Remote = __webpack_require__(/*! Remote/User/Ajax */ 14),
    
                    kn = __webpack_require__(/*! Knoin/Knoin */ 5),
                    AbstractView = __webpack_require__(/*! Knoin/AbstractView */ 11),
                    AttachmentModel = __webpack_require__(/*! Model/Attachment */ 86)
                ;
    
        function MyModalViewA()
        {
           ...some observables...
           //data response which must be updated
           this.rows= ko.observableArray([]);
    
           this.getResults = Utils.createCommand(this, function() 
           {
             kn.showScreenPopup(__webpack_require__(/*! View/Popup/SearchUsers */ 171),[oData]);
           }
        }
    
     kn.constructorEnd(this);
    }
    
    module.exports = MyModelViewA;
    
    }());
    

    那么 MyModelViewB :

    (function () {
    
                'use strict';
    
                var
                    window = __webpack_require__(/*! window */ 10),
                    _ = __webpack_require__(/*! _ */ 2),
                    $ = __webpack_require__(/*! $ */ 12),
                    ko = __webpack_require__(/*! ko */ 3),
                    key = __webpack_require__(/*! key */ 16),
    
                    Enums = __webpack_require__(/*! Common/Enums */ 4),
                    Utils = __webpack_require__(/*! Common/Utils */ 1),
    
                    Links = __webpack_require__(/*! Common/Links */ 13),
                    Remote = __webpack_require__(/*! Remote/User/Ajax */ 14),
    
                    kn = __webpack_require__(/*! Knoin/Knoin */ 5),
                    AbstractView = __webpack_require__(/*! Knoin/AbstractView */ 11),
                    AttachmentModel = __webpack_require__(/*! Model/Attachment */ 86)
      ;
    
            function MyModalViewB()
            {
               ...some observables...
    
            this.doSearch = Utils.createCommand(this, function() 
            {
               MyModelViewB.findUsers(userId);
            }
    
            kn.constructorEnd(this);
            }
    
            MyModelViewB.findUsers = function (userId)
            {
                 //here I'm retriewing rows 
                 //and I need I need to update rows from MyModalViewA
            }
    
    
        module.exports = MyModelViewB;
    
        }());
    

    然后根据一个来自 Whats the best way of linking/synchronising view models in Knockout? 我试着用 PubSub 更新 this.rows= ko.observableArray([]); MyModelViewA .

    为此我补充了 var postbox = ko.observable(); 我的模型视图 我的模型视图 我已经加了

       postbox.subscribe(function(newValue) {
            this.rows.push(newValue);
        }, this);
    

    在那之后 MyModelViewB 我已经加了

    this.results = ko.observableArray([]);
    this.results.subscribe(function(newValue) {
        postbox.notifySubscribers(newValue);
    });
    

    但这两种观点都不明白 newValue MyModelViewB 不更新 我的模型视图 this.rows 当我将硬编码时可观察到 新价值 MyModelViewB

    在这一点上,我不确定我是否得到了正确的答案,从上述链接,使之发挥作用。

    我已经添加到模块包代码的顶部

    var postbox = new ko.subscribable();
    

    如下代码

    (function($) { $(function() {
        window.postbox = new ko.subscribable();
        });
    });
    

    试图声明可订阅时引发错误

    无法读取未定义的属性“subscribe”

    MyModalViewA公司 增加了PFX答案的简化版本:

        postbox.subscribe(function(newValue) {
                self.myTest(newValue);
    
                console.log('New value: ' + newValue);
            }, null, "NewRowAvailable"
        );
    

    在模块中 MyModalViewB公司 在下面 MyModelViewB.findUsers

    var newRow = "testing123";
    postbox.notifySubscribers(newRow, "NewRowAvailable");
    

    当我调试代码时,它显示 postbox Object {NewValueAvailable: } 但是 notifySubscribers 没有更新订阅。

    1 回复  |  直到 6 年前
        1
  •  1
  •   pfx    6 年前

    确保 postbox 实例是在两个视图模型之间共享的同一个实例,并且 notifySubscribers subcribe 方法遵循以下签名。

    notifySubscribers(eventData, eventName); 
    
    subscribe(function(eventData) { ... }, null, eventName);
    

    在下面你可以找到一个你想要达到的目标的简化版本。
    这里只传递了一个搜索结果,但可能更多的是通过数组。

    var postbox = ko.observable();
    
    function MyModalViewA()
    {
        var _self = this;
        _self.rows = ko.observableArray([
            { label: "foo" },
            { label: "bar" }    
            ]);
        
        postbox.subscribe(function(newValue) {         
              _self.rows.push(newValue);
          }, null, "PFX.NewRowAvailable"
          );
    };
    
    function MyModalViewB()
    {
        var _self = this;
        
        _self.search = function() {
        
            var newRow = { "label" : "baz" };
            postbox.notifySubscribers(newRow, "PFX.NewRowAvailable");      
        };
    };
    
    var vma = new MyModalViewA();
    ko.applyBindings(vma, $("#vma").get(0));
    
    var vmb = new MyModalViewB();
    ko.applyBindings(vmb, $("#vmb").get(0));
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    
    <div id="vma">
        <h3>ViewModel A</h3>
        <ol data-bind="foreach: rows">
            <li data-bind="text: label"></li>
        </ol>
    </div>
    
    <hr />
    
    <div id="vmb">    
        <h3>ViewModel B</h3>
        <button data-bind="click: search">search</button>
    </div>