如何優雅的獲取Form表單數據?

先看一個簡單的例子

好比這裏有一個簡單的 form 表單html

<form id="form">
    <input name="user" type="text">
    <div>
        <input type="radio" name="A" value="r1">r1
        <input type="radio" name="A" value="r2">r2
        <input type="radio" name="A" value="r3">r3
        <input type="radio" name="A" value="r4">r4
    </div>
    <div>
        <input type="checkbox" name="B" value="c1">c1
        <input type="checkbox" name="B" value="c2">c2
        <input type="checkbox" name="B" value="c3">c3
        <input type="checkbox" name="B" value="c4">c4
    </div>
    <button type="submit">login</button>
    <button type="reset">reset</button>
</form>

頁面以下前端

image.png

如今,隨便輸入點內容json

image.png

若是提交,表單會觸發默認行爲,直接以get方式提交到當前頁segmentfault

image.png

能夠看到這些參數正是咱們輸入的參數。數組

表單的默認行爲

一般咱們都會把這些默認行爲阻止掉,畢竟都不但願在提交表單會跳轉到另外一個頁面,或者刷新整個頁面app

form.addEventListener("submit", (ev) => {
    ev.preventDefault();
    // 本身發請求
})

那麼,我須要如何拿到這些提交的值呢?框架

表單提交的數據類型

根據數據類型來劃分,一般使用的表單提交數據格式大概有如下幾種this

  1. formdata格式,須要經過 new FormData 建立
  2. json格式,形如{ a:1,b:2,c=3 }
  3. url字符串拼接,形如 a=1&b=2&c=3

1.formdata

一般 formdata 的使用方式以下url

var formData = new FormData();
formData.append('username', 'xboxyan');
formData.append('password', '123456');

可是對於 form 來講,大能夠沒必要採用這樣的方式,直接經過如下方式獲取spa

var formData = new FormData(form); // form爲表單對象

因此,針對表單容器就不要再用 div 了!

爲了更加方便的使用,這裏簡單擴展一下 form 屬性

/* formdata */
Object.defineProperty(HTMLFormElement.prototype, 'formdata', {
    get() {
        return new FormData(this);
    }
})

這樣就能夠經過form.formdata來獲取了

image.png

FormData對象的值是不可見的,須要經過get方式才能看到

image.png

關於 FormData 的更多操做可參考 https://developer.mozilla.org...

2.jsondata

json 格式也是很是經常使用的一種數據傳遞方式了,不過原生 form 並無直接獲取的方式,只能本身封裝了。

這裏能夠直接在上面 FormData 的基礎上遍歷一次便可,因爲有些值會有多個,好比上面的多選框,這裏直接轉成了數組,具體實現以下

/* jsondata */
Object.defineProperty(HTMLFormElement.prototype, 'jsondata', {
    get() {
        const jsondata = {}
        const formdata = new FormData(this);
        formdata.forEach((value, key) => {
            if (!jsondata[key]) {
                jsondata[key] = formdata.getAll(key).length > 1 ? formdata.getAll(key) : formdata.get(key);
            }
        });
        return jsondata;
    }
})

這樣就能夠經過form.jsondata來獲取了

image.png

3.urldata

還有一種方式在get請求中會用到,就是 url拼接方式,這個原生也沒有直接的方案,能夠藉助上面jsondata轉換一下,這裏作了一個小改動,好比默認的多選是b=1&b=2&b=3&c=1,這裏改形成了b=1,2,3&c=1,具體實現以下

/* urldata */
Object.defineProperty(HTMLFormElement.prototype, 'urldata', {
    get() {
        const urldata = [];
        Object.entries(this.jsondata).forEach(([key, value]) => {
            urldata.push(key + '=' + (value.join ? value.join() : value))
        })
        return urldata.join('&');
    }
})

這樣就能夠經過form.urldata來獲取了

image.png

總結

經過以上3個方法,基本能夠知足平常開發的絕大部分需求,前提是 html 足夠規範,表單就必須是 form,單選就必須是 input radio等等,不少前端同窗或者說不少框架都喜歡用 div 來模擬,以致於這些原生特性就直接被拋棄掉了,豈不惋惜?

最後,附上以上所有源碼

/* jsondata */
Object.defineProperty(HTMLFormElement.prototype, 'jsondata', {
    get() {
        const jsondata = {}
        const formdata = new FormData(this);
        formdata.forEach((value, key) => {
            if (!jsondata[key]) {
                jsondata[key] = formdata.getAll(key).length > 1 ? formdata.getAll(key) : formdata.get(key);
            }
        });
        return jsondata;
    }
})
/* formdata */
Object.defineProperty(HTMLFormElement.prototype, 'formdata', {
    get() {
        return new FormData(this);
    }
})
/* urldata */
Object.defineProperty(HTMLFormElement.prototype, 'urldata', {
    get() {
        const urldata = [];
        Object.entries(this.jsondata).forEach(([key, value]) => {
            urldata.push(key + '=' + (value.join ? value.join() : value))
        })
        return urldata.join('&');
    }
})
相關文章
相關標籤/搜索