javascript - 将一些指令传递给函数
问题描述
我正在尝试对执行 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 做错了,但我不明白是什么,有人可以帮我解决(或者如果不好的话,可以用不同的方式解决)吗?
感谢您的任何回复,并为我糟糕的英语感到抱歉。
解决方案
我不太确定我是否正确理解了你的问题,但如果它是关于在你的方法之外完成回调,你有两种可能的方法来做到这一点。
使用闭包:
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。你能给我一个响应的例子,然后我可以给你一个如何解决它的例子。
推荐阅读
- bash - 为什么jq输出的是字符串而不是数组?
- css - 汉堡菜单(3 行)未出现在全尺寸屏幕中
- sql - 根据另一个表中的最大值对列求和
- terraform - 查找函数返回 - 给定键未标识此集合值中的元素
- google-chrome - ChromeDriver 更新后启动 CLI 应用程序时接收 (Errno::ECONNREFUSED) 和 (Net::ReadTimeout)
- r - Cron 在通过 bash 脚本运行 Rscript 时遇到问题
- c# - 如何在统一的脚本中启用/禁用重力?
- python - 重试与 MongoEngine 的连接
- javascript - Promise.All 在我的承诺完成之前返回错误
- java - 应用程序无法识别令牌输入 - 自动化