【问题标题】:How to change the url parameter value without affecting other parameter values如何在不影响其他参数值的情况下更改url参数值
【发布时间】:2018-01-24 03:53:42
【问题描述】:

我正在尝试根据单击的按钮将 URL 参数值之一更改为 true 或 false。

在这里说我有一个网址

127.0.0.1:8080/cars/model?id=2003&styleAttrSaved=false&copyfalse=copy

我想根据我单击的按钮将值 styleAttrSaved 更改为 true 或 false 而不会影响任何其他参数,因此一旦我更改了值,url 将保持不变,仅更改该值。

这是我尝试做的。

$('.submitForm').click(function(){
    var currentUrl = window.location.href;
    var cleanUrl = currentUrl.substring(0,currentUrl.indexOf('&')

    if($(this).attr('data-des') == true){
      var savedUrl = "&styleAttrSaved=true";
    } else {
      var savedUrl = "&styleAttrSaved=false";
    } 
        var finalUrl = cleanUrl+savedUrl;
    history.pushState(null,null,finalUrl);
});


<button class="submitForm" data-des="true">Submit true</button>
<button class="submitForm" data-des="false">Submit false</button>

在代码中,我尝试使用子字符串方法替换值。我在这里面临的问题是,如果我使用这种方法,整个 URL 都会改变

例如,如果我有网址

127.0.0.1:8080/cars/model?id=2003&styleAttrSaved=false&copyfalse=copy

应用上述功能后,这是我返回的 URL

127.0.0.1:8080/cars/model?id=2003&styleAttrSaved=true

在上面的输出 url 中你可以看到 styleAttrSaved 的值发生了变化,但是其他参数值 copyfalse=copy 在新 url 的输出中不再可用。我不想从 URL 中删除其他参数,但我应该只更改 URL 中一个参数的值,以便 url 保持不变,并且像这样将 styleAttrSaved 的值更改为 true

127.0.0.1:8080/cars/model?id=2003&styleAttrSaved=true&copyfalse=copy

我该怎么做?

【问题讨论】:

  • cleanUrl = currentUrl.substring(0,currentUrl.indexOf('&amp;') 之后,cleanUrl?id=2003 结尾。然后你附加到它。你期待什么?

标签: javascript jquery url


【解决方案1】:

您可以使用URLSearchParams 轻松为您更改参数。目前在 IE 和 Safari 移动版中不支持它,但有一个 polyfill 供他们使用

var myURL = "127.0.0.1:8080/cars/model?id=2003&styleAttrSaved=false&copyfalse=copy";

let parsedURL = new URL(`http://${myURL}`);

parsedURL.searchParams.set("styleAttrSaved", true);

console.log(parsedURL.toString());

【讨论】:

    【解决方案2】:

    尝试以下常用方法:

    var url= '127.0.0.1:8080/cars/model?id=2003&styleAttrSaved=false&copyfalse=copy';
    
    function changeParam(url,paramName,paramValue){
    	var qind = url.indexOf('?');
    	var params = url.substring(qind).split('&');
    	var query = '';
    	for(var i=0;i<params.length;i++) {
    		var tokens = params[i].split('=');
    		var name = tokens[0];
    		var value = tokens[1];
    		if(name == paramName) {
    			value = paramValue;
    		}
    		if(query == '') {
    			query = name + '=' + value;
    		} else {
    			query = query + '&' + name + '=' + value;
    		}
    	}
    	return url.substring(0,qind) + query;
    }
    
    console.log(changeParam(url,'styleAttrSaved','true'));

    【讨论】:

      【解决方案3】:

      这是因为你得到'&'的第一个索引你必须找到'&'的第二个索引

      function getIndex(url, subStr, indexValue) {
         return url.split(subStr, indexValue).join(subStr).length;
      }
      var currentUrl = window.location.href;
      var preUrl = currentUrl.substring(0,getIndex(currentUrl,"&",1));
      var afterurl = currentUrl.substring(getIndex(currentUrl,"&",2),currentUrl.length);
      if($(this).attr('data-des') == true){
            var savedUrl = "&styleAttrSaved=true";
          } else {
            var savedUrl = "&styleAttrSaved=false";
          } 
              var finalUrl = cleanUrl+savedUrl+afterurl;
          history.pushState(null,null,finalUrl);
      });
      

      【讨论】:

        【解决方案4】:

        根据调用次数/这些 URL 字符串可以获取多长时间,这应该是可行的。我没有测试过它,所以我不知道它究竟是如何 工作的,但它很快。

        我的基本想法是从 uri string => object 转换,您可以在其中更改键的值,然后从 object=>uri tail string 返回(您显然知道 URL 的第一部分,或者它存储在您可以使用的地方)。

        这个问题对我来说很有趣,所以我可能会回来修改一下我发现我更喜欢的方式。

        请记住,您可以像这样在获得的 URL 字符串上运行 String.replace(如果您只想更改该部分,这可能会提高性能)

        urlString.replace(/styleAttrSaved=(true|false)/, 'styleAttrSaved='+false
        

        更复杂的解决方案

        let url = '127.0.0.1:8080/cars/model?id=2003&styleAttrSaved=false&copyfalse=copy';
        //Base URL String
        function buildObjFromUrlParams(urlString){
          let matches = urlString.match(/\?(.*)/)[1], retObj={};
          //the matches only of anything on the URL after the ? character. Maybe a better Regex but this was the one I came up with based on a single sample
          retObj = matches.split('&').reduce(function(cum, cur){
            //split the matches by the & symbol, run them through the reduce function
            let [key, val] = cur.split('=');
            //Let the key equal the first index value, and val the second, from the current loop item split by the '=' character
            cum[key]=val;
            //set the key on the cumulative object equal to the value 
            // Note you may want to run a uridecode call on the value
            return cum;
            //return the object for use in next iterator
          }, retObj); //start off with an empty Object.
          
          return retObj;
          //You could realistically replace retObj with the matches.split... call up top, but I did this for personal readability
          
        }
        
        function buildUriTailFromObj(obj){
          let keys = Object.keys(obj), retStr = '';
          //declare the object's keys + the return string
          retStr = keys.map(function(key){
            //set the return string to the map of each key value 
            return key+'='+obj[key];
            //return the string made by combining the value of the string, the equal sign, and the object value.
            //NOTE may want ot add a uriencode call on the obj[key]
          }).join('&');// join the mapped string array by the & symbol
          
          return retStr;
          
        }
        
        let urlObj = buildObjFromUrlParams(url);
        urlObj.styleAttrSaved=true;
        
        
        buildUriTailFromObj(urlObj);

        【讨论】:

          【解决方案5】:

          您更新后的网址不完整的原因是您获取原始查询字符串的方式。

          var cleanUrl = currentUrl.substring(0,currentUrl.indexOf('&'));
          

          分配从href&amp; 字符的第一个实例(零索引)之前的所有字符。

          依赖于特定查询参数顺序的解决方案可能有点脆弱。考虑另一种更新这部分 URL 的方法:

          function buildParameterObject(query) {
              var parameters = {};
              var querySegments = query.slice(1).split("&");      
              querySegments.forEach(function(segment) {
                  var prop = segment.split("=")[0];
                  var val = segment.split("=")[1] || "";
                  parameters[prop] = val;
              });
              return parameters;  
          }
          
          function buildQueryString(parameters) {
              var query = "";
              if (parameters === null || typeof parameters !== "object") {
                  return query;
              }
              var keys = Object.keys(parameters);
              if (keys.length === 0) {
                  return query;
              }
              var querySegments = [];
              Object.keys(parameters).forEach(function(parameter) {
                  var segment = parameter;
                  if (parameters[parameter].length > 0) {
                      segment += "=" + parameters[parameter];
                  }
                  querySegments.push(segment);
              });
              query = "?" + querySegments.join("&");
          
              return query;
          }
          
          function buildUpdatedQueryStringWithParameter(parameterName, newValue) {
              var parameters = buildParameterObject(window.location.search);
              parameters[parameterName] = newValue;
              return buildQueryString(parameters);
          }
          

          简而言之,前面的代码做了以下事情:

          • 获取查询字符串
          • 将其转换为对象
          • 修改提供的值或将提供的参数和值添加为新的键/值对
          • 将对象转换回查询字符串
          • 返回结果字符串

          因此,在您的代码中,您可以调用buildUpdatedQueryStringWithParameter,将您的参数名称和新值作为参数传递,然后使用您想要的结果字符串(例如与history.pushState() 结合使用)。

          【讨论】:

            【解决方案6】:

            就个人而言,我会重新考虑您的设计。您可能希望能够在需要时更改其中的任何一个。使用可以设置任何获取 URL 属性的面向对象的代码。

            function GetHandler(queryString){
              var searchStr = queryString || location.search;
              searchStr = searchStr.replace('?', '');
              var searchArray = searchStr.split('&');
              this.searchObj = {};
              for(var i=0,s,l=searchArray.length; i<l; i++){
                s = searchArray[i].split('='); this.searchObj[decodeURIComponent(s[0])] = decodeURIComponent(s[1]);
              }
              this.getPropVal = function(prop){
                return this.searchObj[prop];
              }
              this.setPropVal = function(prop, val){
                this.searchObj[prop] = val;
                return this;
              }
              this.removeProp = function(prop){
                var o = {};
                for(var i in this.searchObj){
                  if(i !== prop)o[i] = this.searchObj[i];
                }
                this.searchObj = o;
                return this;
              }
              this.buildSearchStr = function(){
                var a = [], so = this.searchObj;
                for(var i in so){
                  a.push(encodeURIComponent(i)+'='+encodeURIComponent(so[i]));
                }
                return a.join('&');
              }
            }
            
            var getHandler = new GetHandler('?id=2003&styleAttrSaved=false&copyfalse=copy');
            console.log(getHandler.searchObj);
            getHandler.setPropVal('styleAttrSaved', true);
            getHandler.searchObj.id = 'Anything You Want Here';
            console.log(getHandler.searchObj);
            console.log(getHandler.buildSearchStr());

            如果您希望它基于当前页面获取 URL,只需删除 GetHandler 参数即可。单击“Run code sn-p”按钮后向下滚动到底部以查看您想要的结果。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-03-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多