首页 > 解决方案 > 将一些指令传递给函数

问题描述

我正在尝试对执行 ajax 请求的主要形式的 js 代码进行重复数据删除,我最初执行一个 php 函数,该函数生成任何表单 onsubmit 函数,将不同的代码作为参数传递,但似乎不太好。在我尝试使用 javascript 函数之后,对于简单的变量,我做到了,例如:

// <script> inside of the page generate by php (and in some cases in html received by other ajax request)
$('#f_man-marker_edit-marker').on('submit', function(e){
    TM.editMarker(e, $(this), 'man-marker_edit-marker');
});

...
// in other js file
TM.editMarker = function (e, form, ajax_request) {
    // stop browser from submitting form!
    e.preventDefault();

    // Abort any pending request
    if (request) request.abort();

    // Let's select and cache all the fields
    let inputs = form.find("input, select, button, textarea");

    // Serialize the data in the form
    let serializedData = form.serialize();

    // Let's disable the inputs for the duration of the Ajax request.
    // Note: we disable elements AFTER the form data has been serialized.
    // Disabled form elements will not be serialized.
    inputs.prop("disabled", true);

    request = $.ajax({
        url: "ajax.php?req=" + ajax_request,
        type: "post",
        data: serializedData,
        dataType: "html"
    });

    request.done(function (response) {
        $("#ajaxoutput2").empty().append(response);
        $("#ResultModal2").modal("show");
    });

    request.fail(function (jqXHR, textStatus, errorThrown) {
        console.error(
            "Ajax " + ajax_request + " request failed. The following error occurred: " +
            textStatus, errorThrown
        );
    });

    request.always(function () {
        inputs.prop("disabled", false);
    });

};

现在错过了传递 request.done 指令作为参数,但我没有找到一个好的和可行的方法来做到这一点。把它们放在一个函数中给了我未定义的变量响应,也将它添加为参数。更确切地说,我尝试过:

$('#f_man-marker_edit-marker').on('submit', function(e){
                    let req_done = function (response) {
                        $("#ajaxoutput2").empty().append(response);
                        $("#ResultModal2").modal("show");
                    };
                    TM.editMarker(e, $(this), 'man-marker_edit-marker', req_done());
                });

...
// in other js file
TM.editMarker = function (e, form, ajax_request, req_done()) {
...
    request.done(function (response) {
        req_done(response);
    });
...
};

那是行不通的。是否可以按原样传递指令并让它们工作或必须在函数中?如果必须在一个函数中,那么正确的方法是什么?使用 eval() 可能是可能的,但似乎非常气馁,我暂时没有尝试过。

编辑:我尝试更好地解释:我尝试做的是有一个 php 或 js 函数来调用并作为参数传递唯一改变的东西,例如在我将在项目中执行的数百个类似表单上很好,将避免数千或数万行重复代码,并且可能的重构或未来改进更简单、更快。我从 php 开始,例如:

...
// "f_man-marker_add-marker" is the id of the form, "man-marker_add-marker" is the id of the ajax request, $man_marker_jap1 contain that instructions printed inside of request.done function (they can be different on any form)

TM\UI\JSHelper::jqueryAjaxPost(
            "f_man-marker_add-marker", "man-marker_add-marker", $man_marker_jap1);

.....
// in the file of TM\UI\JSHelper:

...
/**
     * Generate a jquery ajax of type post and datatype html
     * will call the url ajax.php?req=$request_name
     * and request.done will do what define in $done_content
     *
     * @param string $form_id Id of the form
     * @param string $request_name Name of the ajax request parameter
     * @param string $done_content Content of request.done
     */
    public static function jqueryAjaxPost(string $form_id, string $request_name, string $done_content){
        echo <<<HTML

$("#$form_id").submit(function(event){

    // Prevent default posting of form - put here to work in case of errors
    event.preventDefault();

    // Abort any pending request
    if (request) { request.abort(); }

    let form = $(this);

    // Let's select and cache all the fields
    let inputs = form.find("input, select, button, textarea");

    // Serialize the data in the form
    let serializedData = form.serialize();

    // Let's disable the inputs for the duration of the Ajax request.
    // Note: we disable elements AFTER the form data has been serialized.
    // Disabled form elements will not be serialized.
    inputs.prop("disabled", true);

    request = $.ajax({
        url: "ajax.php?req=$request_name",
        type: "post",
        data: serializedData,
        dataType: "html"
    });

    request.done(function (response){
        $done_content
    });

    request.fail(function (jqXHR, textStatus, errorThrown){
        console.error(
            "Ajax $request_name request failed. The following error occurred: "+
            textStatus, errorThrown
        );
    });

    request.always(function () {
        inputs.prop("disabled", false);
    });

});

HTML;
    }

但没有 js“问题”(如果正确完成),因为生成的代码是特定于表单和“完整 js”而无需调用其他外部函数。然后我想主要在仅 js 的文件中执行此操作(逻辑上看起来更正确,而不是从 php 生成所有 js)并且除了 request.done 的内容必须更改之外还可以,所以我打开这篇文章来询问什么是最好和正确的方法。相反,如果没有更好的方法来做我主要在 js 中需要的事情,并且不太糟糕的方法似乎仍然存在于 php 一代中,请告诉我。

EDIT2:我做了其他测试并找到了一个不使用 eval 的工作解决方案(我不知道好不好):

// inside a <script> of part of page generated by php or html code received from ajax request
$('#f_man-marker_edit-marker').on('submit', function(e){
    let req_done = function (response) {
        $("#ajaxoutput2").empty().append(response);
        $("#ResultModal2").modal("show");
    };
    TM.jqueryAjaxPost(e, $(this), 'man-marker_edit-marker', req_done);
});

...
// in other js-only file
/**
 * Basic jquery ajax request of type post from form
 * where changes only request.done content
 * @param e Event received from onsubmit of the form
 * @param form Receive the element with $(this)
 * @param ajax_request Name of the ajax request send to php
 * @param req_done Instruction to do on request.done
 */
TM.jqueryAjaxPost = function (e, form, ajax_request, req_done) {

    // stop browser from submitting form!
    e.preventDefault();

    // Abort any pending request
    if (request) request.abort();

    // Let's select and cache all the fields
    let inputs = form.find("input, select, button, textarea");

    // Serialize the data in the form
    let serializedData = form.serialize();

    // Let's disable the inputs for the duration of the Ajax request.
    // Note: we disable elements AFTER the form data has been serialized.
    // Disabled form elements will not be serialized.
    inputs.prop("disabled", true);

    request = $.ajax({
        url: "ajax.php?req=" + ajax_request,
        type: "post",
        data: serializedData,
        dataType: "html"
    });

    request.done(function (response) {
        req_done(response);
    });

    request.fail(function (jqXHR, textStatus, errorThrown) {
        console.error(
            "Ajax " + ajax_request + " request failed. The following error occurred: " +
            textStatus, errorThrown
        );
    });

    request.always(function () {
        inputs.prop("disabled", false);
    });

};

这是好的还是有更好的方法和/或可能的改进?

EDIT3:我还尝试使用其他参数做一些事情:

TM.deleteMarker = function (id) {
    let req_done = function (response, parArray) {
        $("#ajaxoutput").empty().append(response);
        $('#link_open-marker' + parArray[id]).remove();
    };
    TM.jqueryAjaxGet('man-marker_delete-marker&id=' + id, req_done, {id: id});
};

/**
 * Basic jquery ajax request of method get and datatype html
 * @param ajax_request Name of the ajax request send to php and get parameters, it will be
 * will be added to the end of the url
 * @param req_done Instruction to do on request.done
 * @param parArray Additional parameters used in req_done
 */
TM.jqueryAjaxGet = function (ajax_request, req_done, parArray = {}) {
    // Abort any pending request
    if (request) {
        request.abort();
    }

    request = $.ajax({
        url: "ajax.php?req=" + ajax_request,
        method: "get",
        dataType: "html"
    });

    request.done(function (response) {
        req_done(response, parArray);
    });

    request.fail(function (jqXHR, textStatus, errorThrown) {
        console.error(
            "Ajax " + ajax_request + " request failed. The following error occurred: " +
            textStatus, errorThrown
        );
    });
};

不要给出错误或警告,除了

$('#link_open-marker' + parArray[id]).remove();

所以我想我对 parArray 做错了,但我不明白是什么,有人可以帮我解决(或者如果不好的话,可以用不同的方式解决)吗?

感谢您的任何回复,并为我糟糕的英语感到抱歉。

标签: javascriptphpjquery

解决方案


我不太确定我是否正确理解了你的问题,但如果它是关于在你的方法之外完成回调,你有两种可能的方法来做到这一点。

使用闭包:

TM.editMarker = function (e, form, ajax_request, doneHandler) {
   ...

   request.done(function (response) {
        $("#ajaxoutput2").empty().append(response);
        $("#ResultModal2").modal("show");

        if(doneHandler !== undefined)
             doneHandler();
    });
}

TM.editMarker(e, $(this), 'man-marker_edit-marker', function() {
   console.log("done");
});

使用承诺:

TM.editMarker = function (e, form, ajax_request) {
   ...

   var prom= jQuery.Deferred();
   request.done(function (response) {
        $("#ajaxoutput2").empty().append(response);
        $("#ResultModal2").modal("show");

        prom.resolve();
    });

    return prom.promise();
}

TM.editMarker(e, $(this), 'man-marker_edit-marker').then(function() {
   console.log("done");
});

编辑回答:

好的,所以您要做的是通过 ajax 响应执行 javascript 函数。您可以通过执行以下操作来实现此目的:

$.ajax({
    url: "somejs.js",
    context: document.body,
    success: function(responseText) {
        eval(responseText);
    }
});

然而,这真的很脏,也不是好的做法,因为 javascript 通常是 UI 操作命令。将 UI 内容保留在前端,仅从后端返回原始数据/json。你能给我一个响应的例子,然后我可以给你一个如何解决它的例子。


推荐阅读