博客 / 詳情

返回

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

先看一個簡單的例子

比如這裏有一個簡單的 form 表單

<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

現在,隨便輸入點內容

image.png

如果提交,表單會觸發默認行為,直接以get方式提交到當前頁

image.png

可以看到這些參數正是我們輸入的參數。

表單的默認行為

通常我們都會把這些默認行為阻止掉,畢竟都不希望在提交表單會跳轉到另一個頁面,或者刷新整個頁面

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

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

表單提交的數據類型

根據數據類型來劃分,通常使用的表單提交數據格式大概有以下幾種

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

1.formdata

通常 formdata 的使用方式如下

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

但是對於 form 來説,大可以不必採用這樣的方式,直接通過以下方式獲取

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('&');
    }
})
user avatar codepencil 頭像
1 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.