web-dev-qa-db-ja.com

Javascriptでクエリ文字列を作成する方法

フォームを取り、クエリパラメータを返すことができるJavascriptに何かが組み込まれているのではないかと思うだけです。例: "var1 = value&var2 = value2&arr [] = foo&arr [] = bar ..."

私は何年もこれを疑問に思っていました。

133
John II

JQueryなし

var params = {
    parameter1: 'value_1',
    parameter2: 'value 2',
    parameter3: 'value&3' 
};

var esc = encodeURIComponent;
var query = Object.keys(params)
    .map(k => esc(k) + '=' + esc(params[k]))
    .join('&');

ES5を必要とする矢印関数構文をサポートしないブラウザーの場合、.map...行を

    .map(function(k) {return esc(k) + '=' + esc(params[k]);})
184
Artur Klesun

JQueryを使用している場合は、jQuery.param()http://api.jquery.com/jQuery.param/ をチェックアウトできます。

例:

var params = {
    parameter1: 'value1',
    parameter2: 'value2',
    parameter3: 'value3' 
};
​var query = $.param(params);
document.write(query);
132
techouse

これはあなたの質問に直接答えるものではありませんが、クエリ文字列パラメータを含むURLを作成する汎用関数を次に示します。パラメータ(名前と値)は、URLに含めるために安全にエスケープされます。

function buildUrl(url, parameters){
  var qs = "";
  for(var key in parameters) {
    var value = parameters[key];
    qs += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&";
  }
  if (qs.length > 0){
    qs = qs.substring(0, qs.length-1); //chop off last "&"
    url = url + "?" + qs;
  }
  return url;
}

// example:
var url = "http://example.com/";

var parameters = {
  name: "George Washington",
  dob: "17320222"
};

console.log(buildUrl(url, parameters));
// => http://www.example.com/?name=George%20Washington&dob=17320222
54
Michael

現在、このAPI、特に RLSearchParams API があります。与えられた例の場合:

const params = new URLSearchParams();
const formvals = {
   var1: "value",
   var2: "value2",
   arr: "foo",
};
for (const [key, val] of Object.entries(formvals)) {
   params.append(key, val);
}
console.log(params.toString());
// var1=value&var2=value2&arr=foo

注:これは かなり互換性がある 最近のChromeとFirefoxですが、必要な場合は注意してください互換性が部分的であるため、MicrosoftおよびAppleブラウザーで動作します。

24
Josh

JQueryでは、$.paramでこれを行うことができます

$.param({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })

// -> "action=ship&order_id=123&fees%5B%5D=f1&fees%5B%5D=f2&label=a+demo"
21
manish_s

ES2017(ES8)

Object.entries() を使用して、オブジェクトの[key, value]ペアの配列を返します。たとえば、{a: 1, b: 2}の場合、[['a', 1], ['b', 2]]を返します。 IEだけではサポートされていません(サポートされません)。

コード:

const buildURLQuery = obj =>
      Object.entries(obj)
            .map(pair => pair.map(encodeURIComponent).join('='))
            .join('&');

例:

buildURLQuery({name: 'John', gender: 'male'});

結果:

"name=John&gender=male"
12
Przemek

いいえ、標準のJavaScriptには標準のJavaScriptが組み込まれているとは思いませんが、Prototype JSにはその機能があります(他のほとんどのJSフレームワークにもありますが、わかりません)。 シリアライズ

Prototype JSをお勧めしますが、それはまったく問題ありません。私が本当に気づいた唯一の欠点は、サイズ(数百kb)とスコープ(ajax、domなどのコードがたくさんあること)です。したがって、フォームシリアライザーのみが必要な場合はやり過ぎです。厳密に言えば、Ajax機能のみが必要な場合(主に私が使用したものです)、やり過ぎです。注意しない限り、「マジック」を少しやりすぎてしまうことがあります(要素を見つけるためにPrototype JS関数に触れるすべてのdom要素を拡張するなど)。

10

クエリ文字列 が役立ちます。

だからあなたはできる

const querystring = require('querystring')

url += '?' + querystring.stringify(parameters)
7
ImLeo

ライブラリを使用したくない場合、これはほとんど/すべての同じフォーム要素タイプをカバーするはずです。

function serialize(form) {
  if (!form || !form.elements) return;

  var serial = [], i, j, first;
  var add = function (name, value) {
    serial.Push(encodeURIComponent(name) + '=' + encodeURIComponent(value));
  }

  var elems = form.elements;
  for (i = 0; i < elems.length; i += 1, first = false) {
    if (elems[i].name.length > 0) { /* don't include unnamed elements */
      switch (elems[i].type) {
        case 'select-one': first = true;
        case 'select-multiple':
          for (j = 0; j < elems[i].options.length; j += 1)
            if (elems[i].options[j].selected) {
              add(elems[i].name, elems[i].options[j].value);
              if (first) break; /* stop searching for select-one */
            }
          break;
        case 'checkbox':
        case 'radio': if (!elems[i].checked) break; /* else continue */
        default: add(elems[i].name, elems[i].value); break;
      }
    }
  }

  return serial.join('&');
}
6

Prototypeでこれを行うためのフォームは実際には必要ありません。 Object.toQueryString function を使用するだけです:

Object.toQueryString({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })

// -> 'action=ship&order_id=123&fees=f1&fees=f2&label=a%20demo'
5

私は完全には確信が持てません。jQueryがある程度それをやったことを思い出しますが、phpに優しい方法で言うまでもなく、階層レコードをまったく処理しません。

私が確かに知っていることの1つは、URLを作成して製品をDOMに貼り付けるとき、文字列接着剤を使用してそれを行うだけではありません。さもないと、便利な改ページを開くことになります。

たとえば、特定の広告ソフトウェアは、フラッシュを実行するもののバージョン文字列をインライン化します。これは一般的な単純な文字列である場合は問題ありませんが、Gnashのバージョン文字列にはURLを含む完全なGPL著作権ライセンスが含まれるため、Gnashをインストールした人にとっては非常に単純で混乱を招くことになりますおよび<a href>タグ。これを文字列接着剤の広告ジェネレーターで使用すると、ページが開いて不均衡なHTMLがdomに表示されます。

物語の教訓:

   var foo = document.createElement("elementnamehere"); 
   foo.attribute = allUserSpecifiedDataConsideredDangerousHere; 
   somenode.appendChild(foo); 

しない:

   document.write("<elementnamehere attribute=\"" 
        + ilovebrokenwebsites 
        + "\">" 
        + stringdata 
        + "</elementnamehere>");

Googleはこのトリックを学ぶ必要があります。私は問題を報告しようとしましたが、彼らは気にしないようです。

3
Kent Fredric

Steinが言うように、プロトタイプJavaScriptライブラリを http://www.prototypejs.org から使用できます。 JSを含めると、非常に簡単です。$('formName').serialize()は、必要なものを返します!

3
Shyam

JQueryを好む人には、フォームプラグイン http://plugins.jquery.com/project/form を使用します。これにはformSerializeメソッドが含まれます。

2
Cugel

最近では、FormDataURLSearchParamsを使用して、何もループすることなくこれを実行できます。

const formData = new FormData(form);
const searchParams = new URLSearchParams(formData);
const queryString = searchParams.toString();

ただし、古いブラウザにはポリフィルが必要です。

1
Björn Tantau

これらの回答は非常に役立ちますが、完全なURLを作成するのに役立つ別の回答を追加したいと思います。これにより、ベースurlpathhash、およびparametersを連結できます。

var url = buildUrl('http://mywebsite.com', {
        path: 'about',
        hash: 'contact',
        queryParams: {
            'var1': 'value',
            'var2': 'value2',
            'arr[]' : 'foo'
        }
    });
    console.log(url);

Npm https://www.npmjs.com/package/build-url からダウンロードできます

デモ:

;(function () {
  'use strict';

  var root = this;
  var previousBuildUrl = root.buildUrl;

  var buildUrl = function (url, options) {
    var queryString = [];
    var key;
    var builtUrl;
    var caseChange; 
    
    // 'lowerCase' parameter default = false,  
    if (options && options.lowerCase) {
        caseChange = !!options.lowerCase;
    } else {
        caseChange = false;
    }

    if (url === null) {
      builtUrl = '';
    } else if (typeof(url) === 'object') {
      builtUrl = '';
      options = url;
    } else {
      builtUrl = url;
    }

    if(builtUrl && builtUrl[builtUrl.length - 1] === '/') {
      builtUrl = builtUrl.slice(0, -1);
    } 

    if (options) {
      if (options.path) {
          var localVar = String(options.path).trim(); 
          if (caseChange) {
            localVar = localVar.toLowerCase();
          }
          if (localVar.indexOf('/') === 0) {
              builtUrl += localVar;
          } else {
            builtUrl += '/' + localVar;
          }
      }

      if (options.queryParams) {
        for (key in options.queryParams) {
          if (options.queryParams.hasOwnProperty(key) && options.queryParams[key] !== void 0) {
            var encodedParam;
            if (options.disableCSV && Array.isArray(options.queryParams[key]) && options.queryParams[key].length) {
              for(var i = 0; i < options.queryParams[key].length; i++) {
                encodedParam = encodeURIComponent(String(options.queryParams[key][i]).trim());
                queryString.Push(key + '=' + encodedParam);
              }
            } else {              
              if (caseChange) {
                encodedParam = encodeURIComponent(String(options.queryParams[key]).trim().toLowerCase());
              }
              else {
                encodedParam = encodeURIComponent(String(options.queryParams[key]).trim());
              }
              queryString.Push(key + '=' + encodedParam);
            }
          }
        }
        builtUrl += '?' + queryString.join('&');
      }

      if (options.hash) {
        if(caseChange)
            builtUrl += '#' + String(options.hash).trim().toLowerCase();
        else
            builtUrl += '#' + String(options.hash).trim();
      }
    } 
    return builtUrl;
  };

  buildUrl.noConflict = function () {
    root.buildUrl = previousBuildUrl;
    return buildUrl;
  };

  if (typeof(exports) !== 'undefined') {
    if (typeof(module) !== 'undefined' && module.exports) {
      exports = module.exports = buildUrl;
    }
    exports.buildUrl = buildUrl;
  } else {
    root.buildUrl = buildUrl;
  }
}).call(this);


var url = buildUrl('http://mywebsite.com', {
                path: 'about',
                hash: 'contact',
                queryParams: {
                        'var1': 'value',
                        'var2': 'value2',
                        'arr[]' : 'foo'
                }
        });
        console.log(url);
1
Hien Nguyen
var params = { width:1680, height:1050 };
var str = jQuery.param( params );

console.log(str)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
1

おそらくあなたの質問に答えるには遅すぎます。
同じ質問があり、URLを作成するために文字列を追加し続けたくありませんでした。そこで、 techhouse の説明に従って$ .paramを使い始めました。
URLを簡単に作成できる URI.js ライブラリも見つかりました。あなたを助けるいくつかの例があります: URI.js Documentation
次のいずれかです。

var uri = new URI("?hello=world");
uri.setSearch("hello", "mars"); // returns the URI instance for chaining
// uri == "?hello=mars"

uri.setSearch({ foo: "bar", goodbye : ["world", "mars"] });
// uri == "?hello=mars&foo=bar&goodbye=world&goodbye=mars"

uri.setSearch("goodbye", "Sun");
// uri == "?hello=mars&foo=bar&goodbye=Sun"

// CAUTION: beware of arrays, the following are not quite the same
// If you're dealing with PHP, you probably want the latter…
uri.setSearch("foo", ["bar", "baz"]);
uri.setSearch("foo[]", ["bar", "baz"]);`
0
SaraNa