KnockoutJS - 从另一个模型视图更新可观察到的

KnockoutJS - update observable from another modelview

我有一个现有的 ComposePopupView() 模型视图,其中包含 observable

this.attachments = ko.observableArray([]);

和下面的方法

ComposePopupView.prototype.addDropboxAttachment = function (oDropboxFile)
{
    var
        oAttachment = null,
        iAttachmentSizeLimit = Utils.pInt(Settings.settingsGet('AttachmentLimit')),
        mSize = oDropboxFile['bytes']
    ;

    oAttachment = new ComposeAttachmentModel(
        oDropboxFile['link'], oDropboxFile['name'], mSize
    );

    oAttachment.fromMessage = false;
    oAttachment.cancel = this.cancelAttachmentHelper(oDropboxFile['link']);
    oAttachment.waiting(false).uploading(true).complete(false);

    this.attachments.push(oAttachment);

    this.attachmentsPlace(true);

    if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize)
    {
        oAttachment.uploading(false).complete(true);
        oAttachment.error(Translator.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG'));
        return false;
    }

    Remote.composeUploadExternals(function (sResult, oData) {

        var bResult = false;
        oAttachment.uploading(false).complete(true);

        if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
        {
            if (oData.Result[oAttachment.id])
            {
                bResult = true;
                oAttachment.tempName(oData.Result[oAttachment.id]);
            }
        }

        if (!bResult)
        {
            oAttachment.error(Translator.getUploadErrorDescByCode(Enums.UploadErrorCode.FileNoUploaded));
        }

    }, [oDropboxFile['link']]);

    return true;
};

然后我创建了另一个名为 UsersDocumentsPopupView() 的模型视图,我在其中访问上述方法

DropBox = __webpack_require__(/*! View/Popup/Compose */ 31)
....
DropBox.prototype.addDropboxAttachment(aFiles[0]);

但是它抛出一个错误

Cannot read property 'attachments' of undefined

然后我决定添加 observable

this.attachments = ko.observableArray([]);

到我的modelview再累做

this.attachment.push(oAttachment);

其中 oAttachment 是从 aFiles 数组中获取的对象,但我仍然遇到相同的错误。

我的问题是我如何或者是否可以从一个执行另一个模型视图的模型视图更新 observable attachments

PS。 当我在 ComposePopupView() 中执行下面的代码时,它工作正常

var aFiles = [JSON.parse('{"isDir": false,  "name": "koala.jpg", "bytes": 780831,"link": "http://localhost/data/koala.jpg","id": "id:UxmT1S5QcFAAAAAAAAAACw"}')];

if (aFiles && aFiles[0] && aFiles[0]['link'])
{
  console.log("Test");
  self.addDropboxAttachment(aFiles[0]);
}

那么在这种情况下,如何将数据 aFilesUsersDocumentsPopupView() 传递到 ComposePopupView() 模型视图?

attachmentsComposePopupView.

实例 上的 属性

addDropboxAttachmentComposePopupView 原型上的一个方法,必须在 this 上下文中调用 instance 中的 ComposePopupView为了工作。

有几种方法可以解决这个问题。例如:

  • 最有可能:您还没有创建实例:

    DropBox = __webpack_require__(/*! View/Popup/Compose */ 31);
    const dropBox = new DropBox();
    dropBox.addDropboxAttachment(aFiles[0]);
    
  • 可能:您已经创建了一个实例但无法访问它:在您的构造函数中传递对您要引用的实例的引用。

  • 您是否只打算创建 一个 ComposePopupView 实例?看看 "Singleton" 模式。例如:

    // "Private" to the module
    const MySingletonClass = function() { /* ... */ }
    MySingletonClass.prototype.someMethod = function () { };
    
    let singletonInstance = null;
    
    // Only expose a way to get the instance:
    export const getSingletonInstance = function() {
      if (!singletonInstance) singletonInstance = new MySingletonClass();
      return singletonInstance;
    }
    
    // In another module:
    import { getSingletonInstance } from "./MySingletonClass";
    
    const dropBox = getSingletonInstance();
    dropBox.someMethod(aFiles[0]);
    
  • 计划创建 多个 共享 attachments 数据的实例?使其成为静态值。

我最终使用了 Knockout 的 pub/sub 功能。

下面的基本示例:

var postbox = ko.observable();

function MyModalViewA()
{
    var _self = this;
    var test = new Array();
    _self.rows = ko.observableArray([]);

    postbox.subscribe(function(newValue) {         
          _self.rows.push(newValue);
          //test = test.concat(newValue);
          console.log("Rows " + JSON.stringify(test));
      }, null, "NewRowAvailable"
      );
};

function MyModalViewB()
{
    var _self = this;

    _self.search = function() {

        var newRow = JSON.parse('{ "label" : "abc" }');
        postbox.notifySubscribers(newRow, "NewRowAvailable");      
    };
};

var vma = new MyModalViewA();
ko.applyBindings(vma, $("#vma").get(0));

var vmb = new MyModalViewB();
ko.applyBindings(vmb, $("#vmb").get(0));

第一个视图模型订阅特定主题,第二个视图模型通过该主题的邮箱进行通知。彼此没有直接依赖关系。

当然,邮箱不需要是全局的,可以传递到视图模型构造函数中,或者只是在自执行函数中创建。

样本:http://jsfiddle.net/xpvt214o/708647/

此外,邮箱可以只是一个 ko.subscribable()(包含在 ko.observable 函数中)。