如何使用Javascript建立查询字串


Answers:


-24

一段时间之前,我试图寻找该问题的答案,但最终我写了我自己的函数,该函数从表单中提取值。

它不是完美的,但符合我的需求。

function form_params( form )
{
    var params = new Array()
    var length = form.elements.length
    for( var i = 0; i < length; i++ )
    {
        element = form.elements[i]

        if(element.tagName == 'TEXTAREA' )
        {
            params[element.name] = element.value
        }
        else if( element.tagName == 'INPUT' )
        {
            if( element.type == 'text' || element.type == 'hidden' || element.type == 'password')
            {
                params[element.name] = element.value
            }
            else if( element.type == 'radio' && element.checked )
            {
                if( !element.value )
                    params[element.name] = "on"
                else
                    params[element.name] = element.value

            }
            else if( element.type == 'checkbox' && element.checked )
            {
                if( !element.value )
                    params[element.name] = "on"
                else
                    params[element.name] = element.value
            }
        }
    }
    return params;
}

form_params返回参数的(键->值)映射。输入是表单元素(DOM元素)

它不处理允许多选的字段。


44
是我还是这根本不回答问题?他要的是查询字符串,而不是映射数组。
杰克·威尔逊

2
@JakeWilson是的,这个答案只能回答一半。数组仍然需要进入查询字符串格式。
哈奇·摩尔

8
哇,那时候我一定是JS的菜鸟。使用new Array()初始化字典。但是话又说回来,代码看上去比我今天写的一些废话还干净得多!
hasen

2
@hasen也许您会考虑编辑此答案,或者,嗯,删除它?每当我滚动到它时,它都有越来越多的
否决票

1
@ArturKlesun是的,不。我不在乎 您可以尝试让提出问题的人拒绝接受此答案。
哈森

220

2k20更新:将Josh解决方案与URLSearchParams.toString()结合使用

旧答案:


没有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]);})

8
我见过的最好的解决方案-非常简洁。不过,有几点警告。1)在.map()中,应同时对k和params [k]进行编码,例如,encodeURIComponent(k)和encodeURIComponent(params [k])。2)允许您在查询字符串中具有一个以上命名参数实例。如果要使用此功能,则必须使用数组而不是对象(大多数应用程序将不需要或不需要该对象)。
John Deighan

9
3)并非所有浏览器都支持箭头功能语法(需要ES5)。如果要支持所有浏览器(并对部分进行编码),请将上面的.map()替换为.map(function(k){返回encodeURIComponent(k)+'='+ encodeURIComponent(params [k]);})
John Deighan

1
美丽。真的很美。
Mikko Ohtamaa

9
“ jQuery不够用”
Eugene Pankov

1
@ user1738579我编辑了答案,还包括您的非ES5示例。
泰勒·埃德米斯顿

134

如果您使用的是jQuery,则可能需要查看jQuery.param() http://api.jquery.com/jQuery.param/

例:

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

13
这实际上是正确的答案!表单的查询字符串为$.param($('#myform').serializeArray())
杰西2014年

7
@Jesse,这将是相同的结果:$('#myform').serialize()
菜刀

94
jQuery !== JavaScript
gphilip 2014年

14
@gphilip这就是为什么我从“如果您正在使用jQuery ...”开始响应的原因。否则,如果您想在香草JS中实现它,则可以在jQuery.param()这里查看github.com/jquery/jquery/blob/master/src/serialize.js的实现:)
KlemenTušar16年

2
与我的回答不同,该对象支持嵌套对象,例如someStr=value1&someObj[a]=5&someObj[b]=6&someArr[]=1&someArr[]=2
Klesun

113

URLSearchParams API在所有现代浏览器中均可用。例如:

const params = new URLSearchParams({
  var1: "value",
  var2: "value2",
  arr: "foo",
});
console.log(params.toString());
//Prints "var1=value&var2=value2&arr=foo"


3
最好的答案在这里。只是添加它,您params.append(key, value)以后可以在更复杂的场景中添加新的搜索参数。
Mingwei Zhang

4
请注意,未定义和null值包括在最终字符串中:x=null&y=undefined
pomber

2
另外,如果您已有URL对象(例如,const url = new URL("https://stackoverflow.com")),则可以设置其查询字符串url.search = new URLSearchParams({foo: "bar"})url.searchParams.append("foo", "bar")
Miguel Pynto

需要注意的是TS会警告有关使用一个普通的对象,但它仍然能正常工作
Vadorequest

@pomber有什么好主意可以过滤掉那些未定义的项目?
Dan Gayle

53

这不会直接回答您的问题,但这是一个通用函数,它将创建一个包含查询字符串参数的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

1
在流行的javascript框架之一(例如jquery,mootools等)中,是否有任何与此内置函数类似的内置函数?
塞缪尔

更强大的本机JavaScript解决方案位于stackoverflow.com/a/1714899/1269037
Dan Dascalescu,2013年

有史以来最奇怪的实现,为什么new Array实际上需要将其用作对象时需要初始化呢?o,O
乌穆特·西林

@UmutSirin大声笑是的,我当时对Javascript并不了解很多。xD我想我把它当作PHP数组来对待。如果需要,可以自由重构。
迈克尔

@Michael Haha,是的。我刚刚发送了修改。谢谢您的回答!
乌穆特·西林

22

使用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"

17

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"


10

不,我不认为标准的JavaScript内置了该功能,但是Prototype JS具有该功能(当然大多数其他JS框架也具有此功能,但我不知道它们),他们称其为序列化

我可以推荐Prototype JS,它还可以。我真正注意到的唯一缺点是它的大小(几百kb)和范围(很多有关ajax,dom等的代码)。因此,如果您只想要表单序列化程序,那就太过分了;严格来说,如果只想要Ajax功能(主要是我用过的功能),那就太过分了。除非您非常小心,否则您可能会发现它确实有点“神奇”(就像扩展它与Prototype JS函数所接触的每个dom元素只是为了查找元素一样),在极端情况下会变慢。


只是想知道是否有内置的东西。似乎应该有。我讨厌原型,但我不反对您:)

在设计JavaScript时,尚未发现Ajax,因此仅解析表单以获取查询字符串(提交时将自行创建查询字符串)可能没有多大意义。如今,确实如此……顺便说一句,与script.aculo.us相比,原型很好。:)
Stein G. Strindhaug


6

如果您不想使用库,则应涵盖大多数/所有相同的表单元素类型。

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('&');
}

谢谢!我当时正面临着与原始海报相同的问题,而您的功能正是我所需要的。
dagw,2009年

4

您实际上不需要使用原型就可以执行此操作的表单。只需使用Object.toQueryString函数

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'

4
当然,您已经回答了将近10年前,但是现在不推荐使用此代码。
SEoF '18年

4

你可以做到这一点时下FormData,并URLSearchParams没有超过任何需要循环。

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

不过,较早的浏览器将需要使用polyfill。


3

我并不完全确定自己,我回想起jQuery在一定程度上做到了,但是它根本无法处理层次记录,更不用说以php友好的方式了。

我确实知道的一件事是,在构建URL并将产品粘贴到dom中时,不要仅仅使用string-glue来做到这一点,否则您将对一个方便的分页器敞开心opening。

例如,某些广告软件会从运行Flash的任何内容中内嵌版本字符串。当它禁止通用的简单字符串时,这很好,但是,这太幼稚了,对于安装了Gnash的人来说,它很混乱,因为gnash的版本字符串恰好包含完整的GPL版权许可,并带有URL和<a href>标签。在您的字符串胶水广告生成器中使用此功能,会导致页面打开并在dom中出现不平衡的HTML。

这个故事的主旨:

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

不:

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

Google需要学习这个技巧。我试图报告问题,他们似乎不在乎。


对了 文件撰写是那么 1995年,反正。


2

对于那些喜欢jQuery的人,您可以使用表单插件:http : //plugins.jquery.com/project/form,其中包含一个formSerialize方法。


2

可能有点多余,但我发现的最干净的方法是基于此处的一些答案:

const params: {
   key1: 'value1',
   key2: 'value2',
   key3: 'value3',
}

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

return fetch('my-url', {
  method: 'POST',
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  body: query,
})

资源


1

这些答案非常有帮助,但是我想添加另一个答案,这可能有助于您建立完整的URL。这可以帮助你的concat基地urlpathhashparameters

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

我知道这是很晚的答案,但是效果很好...

var obj = {
a:"a",
b:"b"
}

Object.entries(obj).map(([key, val])=>`${key}=${val}`).join("&");

注意:object.entries将返回键,值对

上面一行的输出将是a = a&b = b

希望它能帮助某人。

快乐编码...


0

回答您的问题可能为时已晚。
我有同样的问题,我不想继续添加字符串以创建URL。因此,我开始使用$ .param,如技术专家所述。
我还找到了一个URI.js库,可以轻松为您创建URL。有几个示例可以为您提供帮助:URI.js文档
这是其中之一:

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

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>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.