V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
waiaan
V2EX  ›  前端开发

以前没发现 form 表单这个特性

  •  
  •   waiaan · 2022-02-22 13:58:32 +08:00 · 2661 次点击
    这是一个创建于 1006 天前的主题,其中的信息可能已经有所发展或是发生改变。
    <form>
        <input type="button" onclick="submit()" value="提交"/>
    </form>
    

    在 html 里写如上代码,未定义任何 submit 方法,点击按钮后 form 表单会直接提交。 如果覆写 form 元素自带的 submit 方法

    HTMLFormElement.prototype.submit=function(){console.log(123)}
    

    此时点击按钮后 form 表单不再提交,控制台打印出 123 。 chrome 、ff 、edge 会如此,ie11 不会,这是浏览器新功能还是规范里规定的?

    第 1 条附言  ·  2022-02-22 14:32:35 +08:00
    感谢前来解答的 v 友,不过还是请仔细看原文。
    第 2 条附言  ·  2022-02-22 14:33:15 +08:00
    就是这个 submit 方法,它是如何调用的。
    第 3 条附言  ·  2022-02-22 15:30:25 +08:00
    18 楼解决了我的问题,感谢各位。
    32 条回复    2022-02-22 15:30:36 +08:00
    duke807
        1
    duke807  
       2022-02-22 14:00:51 +08:00 via Android
    一般不是應該給 onclick 賦值嗎
    mercury233
        2
    mercury233  
       2022-02-22 14:05:03 +08:00   ❤️ 1
    https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
    你这是把浏览器原生的 submit 函数覆盖了
    3dwelcome
        3
    3dwelcome  
       2022-02-22 14:08:44 +08:00
    上课没认真听吧,VUE 里有专门 submit.prevent 属性,来阻止表单的默认提交行为。
    waiaan
        4
    waiaan  
    OP
       2022-02-22 14:10:09 +08:00
    @mercury233
    浏览器原生 submit 方法是挂载在 window 上的还是 HTMLFormElement 原型上的?
    window 上的可以理解是全局函数,如果是 form 元素原型上的它是怎么调用的?还是说浏览器做了处理?
    waiaan
        5
    waiaan  
    OP
       2022-02-22 14:10:50 +08:00
    @3dwelcome
    见上面
    DoubleWu
        6
    DoubleWu  
       2022-02-22 14:30:15 +08:00
    W3C 标准中有如下规定:
    When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.
    译:当一个 form 元素中只有一个输入框时,在该输入框中按下回车应提交该表单。
    https://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2
    waiaan
        7
    waiaan  
    OP
       2022-02-22 14:31:40 +08:00
    @DoubleWu
    我这是一个按钮
    mercury233
        8
    mercury233  
       2022-02-22 14:36:39 +08:00
    3dwelcome
        9
    3dwelcome  
       2022-02-22 14:37:32 +08:00
    “就是这个 submit 方法,它是如何调用的。”

    form 自古以来就有 onsubmit 方法啊。

    和 onclick 一样,正常是挂载到 form 元素上的。

    不是浏览器新功能,是远古功能。
    waiaan
        10
    waiaan  
    OP
       2022-02-22 14:39:49 +08:00
    @3dwelcome
    ……我也没调用 onsubmit 方法,我调用的是没定义过的 submit 方法,它是怎么知道去找 form 的 submit 方法?
    waiaan
        11
    waiaan  
    OP
       2022-02-22 14:41:58 +08:00
    @3dwelcome
    这个 submit 方法也不是定义在 window 上的全局函数
    3dwelcome
        12
    3dwelcome  
       2022-02-22 14:44:24 +08:00
    @waiaan 正常所有的 form 提交,都是需要走 submit 方法的。

    也就是提到 form 元素的 onsubmit='console.log(123)'重载函数。

    和你那句 HTMLFormElement.prototype.submit=function 是一个意思。
    misaka19000
        13
    misaka19000  
       2022-02-22 14:46:26 +08:00   ❤️ 1
    额,看傻了。。。在以前没有 Ajax 通过 JS 调用 HTTP 请求的年代,不都是通过这个 input 按钮来提交 form 表单的吗?这个有什么奇怪的。。。
    waiaan
        14
    waiaan  
    OP
       2022-02-22 14:48:01 +08:00
    @3dwelcome
    是这样没错,但是
    ```js
    onclick="submit()"
    ```
    这个点击事件的 submit 方法它是怎么调用到的,我代码里没有定义过它,它也不是全局函数,它怎么知道我是要提交表单呢?而且我自己再定义一个 submit 函数,这个函数也不会被这个点击事件调用。
    waiaan
        15
    waiaan  
    OP
       2022-02-22 14:49:38 +08:00
    @misaka19000
    唉,你和 12 楼这位都没看仔细我的代码和问题。
    你说的自动提交是<input type="submit">这种
    codehz
        16
    codehz  
       2022-02-22 14:50:12 +08:00
    @3dwelcome onsubmit 是事件绑定(和 submit 方法没有直接联系
    3dwelcome
        17
    3dwelcome  
       2022-02-22 14:53:34 +08:00
    你只指"<input type="button" onclick="submit()" value="提交"/>"

    行为为什么会表现和<input type=''submit">一致?

    我猜可能就是 onclick 里的 submit()吧。
    codehz
        18
    codehz  
       2022-02-22 14:54:19 +08:00   ❤️ 3
    关于楼主的这个问题,你可以把 onclick 改成 debugger ,然后开 F12 看一下,它实际上有多个 with 上下文
    相当于所有在 onXXX 属性里执行的代码都会变成
    with(document) {
    with(form) {
    with(input) { //以此类推,就是每个上级元素
    xxx
    }
    }
    }
    的形式,我记得之前在 html spec 里看过,不知道哪位老哥可以给出引用
    3dwelcome
        19
    3dwelcome  
       2022-02-22 14:55:48 +08:00
    @codehz “onsubmit 是事件绑定(和 submit 方法没有直接联系”

    楼主这个 button 里 submit()函数方法,就是向上查找并调用了 form 里的 onsubmit 啊。
    waiaan
        20
    waiaan  
    OP
       2022-02-22 14:58:04 +08:00
    @3dwelcome
    17 楼说的没错,就是这个意思,因为我没有定义 submit 这个方法。
    ---
    楼主这个 button 里 submit()函数方法,就是向上查找并调用了 form 里的 onsubmit 啊。
    ---
    没太明白你说的向上查找是什么意思
    waiaan
        21
    waiaan  
    OP
       2022-02-22 14:59:29 +08:00
    codehz
        22
    codehz  
       2022-02-22 15:00:07 +08:00
    @3dwelcome 问题在于,你 onsubmit 如果改成一个返回 truthy 指(也就是可以转换成 true 的表达式),原本的 submit 依旧会被执行( console.log 刚好返回 undefined ,所以会自动阻止原本 submit 方法的执行(
    foolnius
        23
    foolnius  
       2022-02-22 15:01:57 +08:00
    https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLFormElement
    HTMLFormElement 不就包括了 submit()方法吗? IE5.5 都兼容
    codehz
        24
    codehz  
       2022-02-22 15:03:30 +08:00
    @waiaan 并不是,对于任意通过 onXXX 绑定的事件处理函数都有类似 with 的处理逻辑(不在 form 章节里,但是 html spec 太长了,不是很想找。。。),显然你这里用的是 oninput
    waiaan
        25
    waiaan  
    OP
       2022-02-22 15:08:55 +08:00
    @codehz
    打断点看了一下,确实如您所言。
    lawler
        26
    lawler  
       2022-02-22 15:14:41 +08:00   ❤️ 4
    formObject.submit() 是原生 JS 默认实现,所有浏览器都支持,包括 IE ,你测试 IE 不支持,不确定是什么问题。古老的代码中,经常会看到 onclick=return false ,就是为了屏蔽默认实现。而你 input 的 onclick 调用了 from 的默认实现。
    codehz
        27
    codehz  
       2022-02-22 15:18:54 +08:00   ❤️ 1
    @3dwelcome 说错了,submit 方法的默认行为是触发 submit 事件,然后根据是否 preventDefault 来决定是否执行提交行为,而 onXXX 事件绑定机制是当返回 falsy 值时 preventDefault ,因此当你同时定义 onsubmit 和 submit 方法时,两者将独立工作互不影响((通过 type=submit 按钮触发的会发送 submit 事件,然后如果没被 preventDefault 就执行原生提交程序(与 submit 函数无关);而通过 submit 方法手动调用的就会进入你自定义的函数上,也不会触发事件(除非你手动 dispatchEvent )
    waiaan
        28
    waiaan  
    OP
       2022-02-22 15:21:28 +08:00
    @codehz
    @lawler
    试了一下,自己定义一个名为 submit 的函数也没法在 onclick="submit()"里调用到了,它还是调用 form 的方法,reset 方法也是。
    codehz
        29
    codehz  
       2022-02-22 15:23:03 +08:00
    @waiaan 因为 with 最内侧的优先级最高,先找到的就调用了,全局函数是最外面的
    Rache1
        30
    Rache1  
       2022-02-22 15:24:27 +08:00   ❤️ 1
    😂 一会儿你还会发现有个 reset() 方法,也可以玩。
    waiaan
        31
    waiaan  
    OP
       2022-02-22 15:24:57 +08:00
    @codehz
    非常感谢!
    jifengg
        32
    jifengg  
       2022-02-22 15:30:36 +08:00
    @codehz 解释很棒!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2806 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 07:23 · PVG 15:23 · LAX 23:23 · JFK 02:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.