source

일반 자바스크립트 jQuery.param()과 동등한 jQuery.param()

lovecheck 2023. 10. 19. 22:25
반응형

일반 자바스크립트 jQuery.param()과 동등한 jQuery.param()

jQuery.param()은 키-값 쌍의 배열을 가져와 HTML 요청에서 쿼리 문자열로 사용할 수 있는 문자열로 바꿉니다.예를들면,

a = {
      userid:1,
      gender:male
    }

로 전환될 것입니다.

userid=1&gender=male

서버측의 외부 API를 Google Apps 스크립트로 호출하려고 하는데 긴 쿼리 문자열이 필요합니다.jQuery param 기능을 사용하고 싶은데 구글에서 서버 쪽에서 jQuery를 사용하는 방법이 쉽지 않은 것 같습니다.

동일한 기능을 달성하는 평이한 자바스크립트 코드를 주실 수 있나요?

jQuery 구현이 여기에 있지만, 단순히 복사해서 '전통적'을 다루는 코드를 뜯어냄으로써 중요한 세부사항을 건너뛸 위험을 감수하고 싶지 않습니다.

순수 자바스크립트로도 가능하지만, 코드 라인을 더 많이 작성해야 합니다.시도해 보기:

테스트용 HTML 코드:

<p id="test"></p>

로드 시 실행할 자바스크립트:

a = {
      userid:1,
      gender: "male",
    }

url = Object.keys(a).map(function(k) {
    return encodeURIComponent(k) + '=' + encodeURIComponent(a[k])
}).join('&')

document.getElementById("test").innerHTML=url

결과는 다음과 같습니다.

userid=1&gender=male

JSFIDDLE에서 사용해보실 수 있습니다.NET, 작동합니다. 링크는 다음과 같습니다. http://jsfiddle.net/ert93wbp/

중첩된 객체와 배열을 변환할 수 있는 ES6 버전은 다음과 같이 사용됩니다.encodeURI(getUrlString({a: 1, b: [true, 12.3, "string"]})).

getUrlString (params, keys = [], isArray = false) {
  const p = Object.keys(params).map(key => {
    let val = params[key]

    if ("[object Object]" === Object.prototype.toString.call(val) || Array.isArray(val)) {
      if (Array.isArray(params)) {
        keys.push("")
      } else {
        keys.push(key)
      }
      return getUrlString(val, keys, Array.isArray(val))
    } else {
      let tKey = key

      if (keys.length > 0) {
        const tKeys = isArray ? keys : [...keys, key]
        tKey = tKeys.reduce((str, k) => { return "" === str ? k : `${str}[${k}]` }, "")
      }
      if (isArray) {
        return `${ tKey }[]=${ val }`
      } else {
        return `${ tKey }=${ val }`
      }

    }
  }).join('&')

  keys.pop()
  return p
}

여기서 대부분의 솔루션은 배열/객체 값에 실패합니다.

이를 통해 1차 레벨의 어레이/objects을 지원합니다.

const param = obj => Object.entries(obj).map(
    pair => Array.isArray(pair[1]) ?
        pair[1].map(x=>`${encodeURIComponent(pair[0])}[]=${encodeURIComponent(x)}`).join('&') :
        typeof pair[1] === 'object' ? 
        Object.entries(pair[1]).map(x=>`${encodeURIComponent(pair[0])}[${x[0]}]=${encodeURIComponent(x[1])}`).join('&') :
        pair.map(encodeURIComponent).join('=')).join('&')

예:

param({a:1,b:'b'})
"a=1&b=b"

param({a:1,b:2,c:[1,2],d:{e:'abc',f:4}});
"a=1&b=2&c[]=1&c[]=2&d[e]=abc&d[f]=4"

param({a:1,b:2,c:[1,2,'"'],d:{e:'a"b[c]',f:4}});
"a=1&b=2&c[]=1&c[]=2&c[]=%22&d[e]=a%22b%5Bc%5D&d[f]=4"

그러나 2단계(nesting)에서는 실패합니다.

param({a:1,b:{c:[1,2]}});
"a=1&b[c]=1%2C2"

업데이트:

IE11 지원이 필요하지 않다면 사용하시기 바랍니다.URLSearchParamsAPI. 이 답변 보기error:

function urlString(params)
{
    if (!params)
        return '';
    const urlParams = new URLSearchParams();
    for (const [name, value] of Object.entries(params))
        urlParams.append(name, value || '');
    return urlParams.toString();
};

@아마인넛의 대답은 굉장합니다.하지만 저는 단순화를 좀 합니다.

const obj = {
  userid: 1,
  gender: 'male'
}

const params = Object.keys(obj).map((k) => encodeURIComponent(k) + '=' + encodeURIComponent(obj[k])).join('&')

또는 es6 모듈을 사용하여 모듈화할 수 있습니다.

util.js

export default {
  params (obj) {
    return Object.keys(obj).map((k) => encodeURIComponent(k) + '=' + encodeURIComponent(obj[k])).join('&')
  }
}

다음과 같이 사용합니다.

import util from './util'

const q = {
  userid: 1,
  gender: 'male'
}

const query = util.params(q)

console.log(query)
ES6 gives us some nice primitives:

    // Function that parses an object of string key/value params to build up
    // a string of url params
    // requires an object with no nested values
    export function parseUrlParams(urlParams) {
        const joinByEquals = (pair) => pair.join('=')
        const params = Object.entries(urlParams).map(joinByEquals).join('&')
        if (params) {
            return `?${params}`
        } else {
        return ''
        }
    }

여기에서 실제로 보기: https://www.webpackbin.com/bins/-KnpOI6hb1AzTDpN3wS7

이것은 조금 실망스러웠습니다.여기서 어떤 솔루션도 JQuery와 동등한 JSON 개체에 대한 실제 "x-www-form-urlencoded" 데이터를 생성하는 데 실제로 작동하지 않는 것으로 보입니다.일부는 근접했지만 하위 항목에서 실패했습니다.JSON 개체에 대한 작업 버전을 얻기 위해 몇 가지 솔루션에서 코드를 추출했습니다.

function formData (obj) {
  return Object.keys(obj).map((k) => encodeURIComponent(k) + '=' + encodeURIComponent(JSON.stringify(obj[k]))).join('&')
}

참고로 2020년에는 x-www-form-urlencoded 데이터만 받아들이기 때문에 FyI는 FastSpring의 API에 이를 사용해야 했습니다.거의 10년 만에 API가 JSON만 받아들이지 않은 것은 이번이 처음이기 때문에 하루 종일 이 문제에 몰두했습니다 :(

여기 최신 버전이 있습니다.URLSearchParams @oriadam / @error변,원:

const urlString = (data) => {
    if (data == null) { return ""; }
    
    const urlParams = new URLSearchParams();
    const rbracket = /\[\]$/;

    const add = (name, valueOrFunction) => {
        const value = typeof valueOrFunction === "function" ? valueOrFunction() : valueOrFunction;
        urlParams.append(name, value == null ? "" : value);
    };

    const buildParams = (prefix, obj) => {
        if (Array.isArray(obj)) {
            obj.forEach((value, index) => {
                if (rbracket.test(prefix)) {
                    add(prefix, value);
                } else {
                    const i = typeof value === "object" && value != null ? index : "";
                    buildParams(`${prefix}[${i}]`, value);
                }
            });
        } else if (typeof obj === "object" && obj != null) {
            for (const [name, value] of Object.entries(obj)) {
                buildParams(`${prefix}[${name}]`, value);
            }
        } else {
            add(prefix, obj);
        }
    };

    if (Array.isArray(data) || data instanceof NodeList) {
        // If an array or NodeList was passed in, 
        // assume that it is a collection of form elements:
        data.forEach(el => add(el.name, el.value));
    } else {
        for (const [name, value] of Object.entries(data)) { 
            buildParams(name, value);
        }
    }

    return urlParams.toString();
};

이는 jQuery 3.5.1 소스를 기반으로 하므로 다음과 동일한 출력을 생성해야 합니다.$.param동일한 입력에 대해유일한 차이점은 공간이 다음과 같이 인코딩된다는 것입니다.+대신에%20.

저는 jQuery 테스트 케이스를 사용하여 Fiddle을 제공했는데, 모두 통과했습니다.


편집: 지원되지 않는 환경을 지원해야 하는 경우URLSearchParams클래스, 당신은 배열을 조합하여 사용해야 할 것입니다.encodeURIComponent다른 답변과 같이 method:

const urlString = (data) => {
    if (data == null) { return ""; }
    
    const urlParams = [];
    const rbracket = /\[\]$/;

    const add = (name, valueOrFunction) => {
        let value = typeof valueOrFunction === "function" ? valueOrFunction() : valueOrFunction;
        if (value == null) { value = ""; }

        urlParams.push(`${encodeURIComponent(name)}=${encodeURIComponent(value)}`);
    };

    const buildParams = (prefix, obj) => {
        if (Array.isArray(obj)) {
            obj.forEach((value, index) => {
                if (rbracket.test(prefix)) {
                    add(prefix, value);
                } else {
                    const i = typeof value === "object" && value != null ? index : "";
                    buildParams(`${prefix}[${i}]`, value);
                }
            });
        } else if (typeof obj === "object" && obj != null) {
            for (const [name, value] of Object.entries(obj)) {
                buildParams(`${prefix}[${name}]`, value);
            }
        } else {
            add(prefix, obj);
        }
    };

    if (Array.isArray(data)) {
        // If an array was passed in, 
        // assume that it is a collection of form elements:
        data.forEach(el => add(el.name, el.value));
    } else {
        for (const [name, value] of Object.entries(data)) { 
            buildParams(name, value);
        }
    }

    return urlParams.join("&");
};

업데이트된 테스트 Fiddle

export function param( params ) {
    const p = new URLSearchParams;
    for( const [ key, value ] of Object.entries( params ) ) {
        p.set( key, String( value ) );
    }
    return p.toString();
}

언급URL : https://stackoverflow.com/questions/25224887/plain-javascript-equivalent-of-jquery-param

반응형