如何在bindingHandler内从ViewModel调用函数

How Do I Call A Function from ViewModel inside bindingHandler

本文关键字:ViewModel 调用 函数 内从 bindingHandler      更新时间:2023-09-26

我的viewModel中有一个方法,它调用ajax get方法来获取所有项。这一切都很完美。然后我有一个ko.bindingHandler,用于通过ajaxSubmit内联上传图像。这也可以,但问题是我必须复制代码,以获取上传图像的bindingHandler中的所有项目,否则图像一旦上传就不会更新。刷新页面解决了这个问题,但我想让视图使用新图像自动刷新。那么,真正的问题是,是否可以在bindingHandler中从viewModel调用函数?如有任何帮助,我们将不胜感激!

绑定处理程序:

ko.bindingHandlers.imageInLineUpload = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var options = ko.utils.unwrapObservable(valueAccessor()),
            property = ko.utils.unwrapObservable(options.property);
        $(element).change(function () {
            if (element.files.length) {
                if ((element.files[0].type === "image/png") || (element.files[0].type === "image/jpeg")) {
                    var $this = $(this);
                    $(element.form).ajaxSubmit({
                        url: $.API.url + "XYZ",
                        type: "POST",
                        dataType: "text",
                        success: function (data) {
                            toastr.success('Upload Successful.');
                            var viewModel= new MyViewModel ();
                            viewModel.GetObjects();
                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            toastr.error('Upload Failed. Please Try again!');
                        }
                    });
                }
                else {
                    toastr.error('Upload Failed. PNG and JPEG are the only supported formats.');
                }
            }
        });
    }
};

视图模型:

var MyViewModel = function () {     
   var self = this;     
   self.xyz = ko.observable("");    
   self.xyz  = ko.observable(""); 
   self.xyz = ko.observable("");
   self.GetObjects= function () {       
   // Ajax call to fetch objects.
   } 
   self.GetObjects();
};
ko.applyBindings(new MyViewModel ());

有几种方法可以做到这一点。真正"从bindinghandler调用viewModel函数"的方法是:

var viewModel = ko.dataFor(element);
viewModel.GetObjects()

这是可行的,但这是一个相当平庸的解决方案;它将绑定处理程序与这个特定的viewModel紧密地耦合在一起,这是一个隐含的依赖项;bindingHandler API没有明确表示需要这个函数。


另一种方法(在我看来,更好的方法)是将函数作为选项参数传递到bindingHandler中:

<div data-bind="imageInLineUpload: {getImagesCallback: GetObjects}"></div>

在绑定处理程序中:

var options = ko.utils.unwrapObservable(valueAccessor()),
    getImagesCallback =  options.getImagesCallback;
getImagesCallback();

(这与PW Kad的答案类似,但我认为指定一个单独的bindingKey来为不同的bindinghandler提供选项对于所需的参数来说是个坏主意,而且与只将对象传递给当前绑定处理程序相比,这是一种非常丑陋的敲除bindinghandlers的方法)


但实际上,如果您的绑定处理程序正在进行异步调用,我认为您需要重组一些东西。在我看来,绑定处理程序应该只做视图逻辑,而不是处理应该在ViewModel中的AJAX。

我过去使用的一种方法是将对函数的引用作为一个选项传递到绑定处理程序中,类似于我们在其他地方使用回调的方式-

<div data-bind="imageInLineUpload: someObservable, imageILUOptions: { callback: myFunction }"></div>

在绑定处理程序中,您可以访问这样的函数-

ko.bindingHandlers.imageInLineUpload = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var options = ko.utils.unwrapObservable(allBindingsAccessor).imageILUOptions;
        var callback = options.callback;
        // do something
        callback(someVar);

这允许您将任何函数传递到绑定中,并将其用作绑定内部的回调。这不是一个完美的解决方案,但应该能满足您的需要。