42

我有一个必须在提交时执行 javascript 函数的表单,然后该函数将数据发布到我的 php 发送邮件文件并发送邮件。但它只适用于火狐。表单操作在 IE 中似乎没有做任何事情,我的问题是:这是从表单操作中从外部文件调用函数的正确方法:

action="javascript:simpleCart.checkout()"

simpleCart 是 .js 文件, checkout() 是函数。

提示赞赏,努力理解为什么它可以在 Firefox 中工作,但不能在 IE、chrome 或 safari 中工作。

<form name=form onsubmit="return validateFormOnSubmit(this)" enctype="multipart/form-data" action="javascript:simpleCart.checkout()" method="post">
4

4 回答 4

54

没有广泛支持设置为 JavaScript 函数的表单操作,我很惊讶它在 FireFox 中工作。

action最好的方法是为您的 PHP 脚本设置表单;如果您需要在提交之前做任何事情,您可以添加到onsubmit

编辑原来你不需要任何额外的功能,这里只是一个小改动:

function validateFormOnSubmit(theForm) {
    var reason = "";
    reason += validateName(theForm.name);
    reason += validatePhone(theForm.phone);
    reason += validateEmail(theForm.emaile);

    if (reason != "") {
        alert("Some fields need correction:\n" + reason);
    } else {
        simpleCart.checkout();
    }
    return false;
}

然后以您的形式:

<form action="#" onsubmit="return validateFormOnSubmit(this);">
于 2012-05-09T17:19:15.910 回答
48

绝对有效。

    <form action="javascript:alert('Hello there, I am being submitted');">
        <button type="submit">
            Let's do it
        </button>
    </form>
    <!-- Tested in Firefox, Chrome, Edge and Safari -->

因此,简短的回答是:的,这是一个选择,而且是一个不错的选择。它说“提交后,请不要去任何地方,只需运行此脚本” - 非常中肯。

一个小小的改进

为了让事件处理程序知道我们正在处理哪种表单,传递 sender 对象似乎是一种显而易见的方式:

    <form action="javascript:myFunction(this)">  <!-- should work, but it won't -->

但不是什么会有意义,而是this指向 Window 对象。显然javascript:链接存在于一个单独的范围内。因此,我建议使用以下格式,它仅多了 13 个字符,而且效果很好:

    <form action="javascript:;" onsubmit="myFunction(this)">  <!-- now you have it! -->

...现在您可以正确访问发件人表单。(你可以写一个简单的“#”作为动作,这很常见——但它有提交时滚动到顶部的副作用。)

同样,我喜欢这种方法,因为它毫不费力且不言自明。没有“return false”,没有 jQuery/domReady,没有重型武器。它只是做它看起来做的事情。当然其他方法也行得通,但对我来说,这是武士之道。

关于验证的说明

只有当它们的事件处理程序返回真实的东西时,表单才会被提交onsubmit,因此您可以轻松地运行一些先发制人的检查:

    <form action="/something.php" onsubmit="return isMyFormValid(this)">

现在isMyFormValid将首先运行,如果它返回 false,服务器甚至不会被打扰。不用说,您也必须在服务器端进行验证,这是更重要的一个。但是为了快速方便的早期检测,这很好。

于 2015-12-26T02:20:30.487 回答
3

自从提出这个问题以来已经快 8 年了,但我会冒险给出一个以前没有给出的答案。OP说这不起作用:

action="javascript:simpleCart.checkout()"

OP 说,尽管尝试了他得到的所有好建议,但这段代码仍然失败。所以我冒险猜测一下。动作checkout()作为simpleCart类的静态方法调用;但也许checkout()实际上是一个实例成员,而不是static。这要看他是怎么定义checkout()的。

顺便说一句,simpleCart大概是一个类名,按照惯例,类名的首字母大写,所以让我们在这里使用那个约定。让我们使用名称SimpleCart

这是一些示例代码,说明了定义checkout()为实例成员。这是在 ECMA-6 之前的正确方法:

function SimpleCart() {
    ...
}
SimpleCart.prototype.checkout = function() { ... };

许多人使用了不同的技术,如下所示。这很流行,并且有效,但我反对它,因为实例应该在 , 上定义prototype一次,而以下技术定义成员 onthis并在每次实例化时重复这样做。

function SimpleCart() {
    ...
    this.checkout = function() { ... };
}

这是ECMA-6中的一个实例定义,使用官方class

class SimpleCart {
    constructor() { ... }
    ...
    checkout()    { ... }
}

与ECMA-6 中的静态定义进行比较。区别就一个字:

class SimpleCart {
    constructor() { ... }
    ...
    static checkout()    { ... }
}

这是旧方式的静态定义,在 ECMA-6 之前。请注意,该checkout()方法是在函数之外定义的。它是函数对象的成员,而不是原型对象,这就是它成为static的原因。

function SimpleCart() {
    ...
}
SimpleCart.checkout = function() { ... };

this由于它的定义方式,静态函数对于关键字引用的内容会有不同的概念。请注意,实例成员函数是使用this关键字调用的:

this.checkout();

使用类名调用静态成员函数:

SimpleCart.checkout();

问题是 OP 希望将调用放入 HTML 中,它将在全局范围内。他不能使用关键字this,因为this它会引用全局范围(即window)。

action="javascript:this.checkout()" // not as intended
action="javascript:window.checkout()" // same thing

在 HTML 中使用实例成员函数没有简单的方法。您可以结合 JavaScript 做一些事情,在类的静态范围内创建一个注册表,然后调用代理静态方法,同时将参数传递给该代理,该代理将索引提供给您的实例的注册表,然后拥有代理调用实际的实例成员函数。像这样的东西:

// In Javascript:
SimpleCart.registry[1234] = new SimpleCart();

// In HTML
action="javascript:SimpleCart.checkout(1234);"

// In Javascript
SimpleCart.checkout = function(myIndex) {
    var myThis = SimpleCart.registry[myIndex];
    myThis.checkout();
}

您还可以将索引存储为元素的属性。

但通常更容易在 HTML 中什么都不做,而在 JavaScript 中使用.addEventListener()并使用该.bind()功能。

于 2019-12-07T08:42:45.397 回答
1

我总是在 html 文档的头部包含 js 文件,并且它们在操作中只是调用 javascript 函数。像这样的东西:

action="javascript:checkout()"

你试试这个?

不要忘记在 html 头中包含脚本引用。

我不知道在Firefox中起作用的原因。问候。

于 2012-05-09T17:26:05.493 回答