0%

表单提交

form 表单基本属性

form 属性列表

属性 说明
action 表单提交地址
method 表单提交方式, 常用的有 get / post
autocomplete 表单自动补全
novalidate 不验证表单
enctype 规定被提交数据的编码(默认:url-encoded); 当提交的表单中有文件域时, 应设置为 multipart/form-data

表单的同步提交和异步提交

常见的表单提交方式有 get / post, 通过 method 属性来设置

  • form 内的所有要提交的表单元素都必须具有 name 属性

表单的同步提交

form 表单默认的提交行为是同步提交, 且默认提交方式为 get

  • 意思是, 当 form 具有 submit 类型的表单元素时, 不设置 method, 点击提交按钮或者调用 form 元素的 submit() 方法表单也会提交
    1
    2
    3
    <form method="post" action="/register" id="register-form">

    </form>
  1. 同步提交方式页面会转圈锁死
  2. 同步提交服务端会将响应数据直接渲染到浏览器页面上覆盖掉原来的页面
  3. 同步提交在服务端没法操作 dom 元素, 不能给 dom 元素添加样式

表单的异步提交

使用 AJAX 方式提交表单就是异步提交

  • ⚠️ 异步提交需要先阻止表单的同步提交行为
    1
    2
    3
    4
    5
    6
    $('form').submit(function (e) {
    e.preventDefault()
    $.ajax({
    ......
    })
    })
  1. 异步提交页面不会刷新
  2. 异步提交服务端会将响应数据传递给 AJAX 响应处理函数

阻止表单的默认提交

event.preventDefault()

1
2
3
form.onsubmit = function (e) {
e.preventDefault()
}

get 提交表单

提交的数据会以 ?key=value&key1=value1 的形式出现在 url 地址中

post 提交表单

提交的数据可以在 控制面板 => NetWork => 请求地址 => Request => Form Data 中查看

有文件域的表单提交

⚠️ 带有文件域的表单提交

  • 类型必须是 post
  • 必须将表单的 enctype 设置为 multipart/form-data
    • 否则, 文件不传输
      1
      2
      3
      4
      5
      6
      <form action="/" method="post" enctype="multipart/form-data">
      <input type="text" name="name" /> <br>
      ...
      <input type="file" name="avatar" />
      <input type="submit" value="提交" />
      </form>

带文件域的表单同步提交

服务端 接收具有文件域的表单请求需要使用第三方包 formidable

  • 使用

    1
    $ yarn add formidable
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    const express = require('express');
    const formidable = require('formidable');
    const path = require('path')

    const app = express();

    app.get('/', (req, res) => {
    res.send('form.html')
    })

    app.post('/api/upload', (req, res, next) => {

    const form = formidable({ multiples: true }) // options

    form.parse(req, (err, fields, files) => {
    // err —— 可能发生的错误对象
    // fileds —— 普通的表单字段,是对象形式
    // files —— 文件内容数据信息,是对象形式
    if (err) {
    return next(err)
    }
    // res.json({ fields, files })
    const body = fileds
    body.image = '/uploads/' + path.basename(files.avatar.path)
    res.json(body)
    })
    })

    app.listen(3000, () => {
    console.log('Server is running......')
    })

  • options

    1
    2
    3
    4
    5
    const form = formidable({ 
    multiples: true,
    uploadDir: '/uploads', // 指定文件上传目录
    keepExtensions: true // 是否保留文件后缀名
    })

带文件域的表单异步提交

⚠️ $ajax 默认提交的数据 data: $(this).serialize() 中是 不带文件域内容 的,就是说默认不能提交文件内容

  • 如何解决?

    1. 用插件 ajaxFileUpload()

      • 先通过图片提交接口提交图片
      • 再通过 ajax 提交普通表单数据
      • 可以实现图片预览
    2. formData 对象

      • 文件域和普通表单数据组成 formData 对象一起提交
      • 可以通过 FileReader 实例对象实现图片预览
        1
        2
        3
        var formData = new FormData([可以传递 htmlFormElement 元素])
        // 把 file 追加到 formData 里
        formData.append('avatar', $('[type=file]')[0].files[0])
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        var formData = new FormData(document.querySelector("form"));

        $.ajax({
        url: "/ads/add",
        type: "POST",
        data: formData, // 带文件域的数据

        // 不处理数据, 当 data 的值为 formData 对象的时候, 一定要设置, 否则还是走同步提交
        processData: false,

        // 不设置内容类型,当提交一个 formdata 对象的时候,一定要设置,否则 jQuery 会默认把 content-type 设置为 x-www-urlencoded ,无法提交文件
        contentType: false,

        success: function (data) {

        }
        })
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        <body>
        <!--实现图片的实时预览 onchange改变元素后触发方法-->
        <from>
        文件: <input type="file" name="myFile" id="myFile" multiple onchange="getFileContext()"><br>
        <img id="img"><br>
        <input type="submit">
        </from>
        <script>
        function getFileContext() {
        var reader=new FileReader();
        //需要的参数是图片
        var file=document.querySelector("#myFile").files;
        // 没有返回值,将其结果储存在result中,无法判断文件是否读完
        reader.readAsDataURL(file[0]);
        reader.onload=function () {
        // 展示出来:得到的reader.result为二进制文件base64 data:image/jpeg;base64...
        console.log(reader.result);
        document.querySelector("#img").src=reader.result;
        }
        }
        </script>
        </body>

form 在 jQuery 中的方法

  • serialize()

    • 在 ajax post 请求中将用作提交的表单元素的值编译成 name=value&name1=value1 字符串
      1
      2
      var ret = $('form').serialize()
      console.log(ret)
  • serializeArray() (不好用)

    • 将用作提交的表单元素的值编译成拥有 name 和 value 对象组成的数组
  • submit()

    • 为 submit 事件绑定一个处理函数, 或触发元素上的 submit 事件
    • 当参数 function 没有给出时, 触发当前表单的 submit 事件, 并且执行默认的表单提交行为, 除非阻止表单默认行为
      1
      2
      3
      4
      5
      6
      7
      8
      $('form').submit(function (e) {
      // 阻止表单默认同步提交行为
      e.preventDefault()
      // 异步提交
      $.ajax({
      ......
      })
      })