防止垃圾邮件历史记录中的搜索更改

时间:2016-09-01 20:06:39

标签: angularjs hyperlink routes

我正在使用#!/OrderList?id=123这样的链接,它会显示所有订单的列表以及订单123的更多详细信息。使用reloadOnSearch=false并观看$routeUpdate它可以正常工作,但只有一个事情:所有这些链接都被放入浏览器历史记录中,而我更喜欢只有一个这样的链接。例如,而不是

#!/OrderList?id=123
#!/OrderList?id=124
#!/OrderList?id=125
#!/AnotherList?id=678
#!/AnotherList?id=679

每个组的最后一个成员,即

#!/OrderList?id=125
#!/AnotherList?id=679

我知道$location.replace(),但是当通过跟随链接进行更改时,我看不到将它放在哪里。我试图将它放在$scope.$on("$routeUpdate", ...)中,但它没有做任何事情,可能是因为路线已经改变时为时已晚。

我既不使用router-ui也不使用HTML5模式(只是简单angular-route)。

我很害怕,我不清楚我坚持使用href而不是自定义处理程序。我希望链接能够与鼠标中键和书签以及所有内容一起使用。 ng-hrefng-click的组合可以做我想要的,但我发现simple solution使用普通链接。

4 个答案:

答案 0 :(得分:3)

看起来您可能想要使用ng-click功能更新URL查询参数而不是依赖链接,然后调用类似下面的函数来更新参数...使用替换状态,历史记录应该只跟踪当前值。我没有测试过这个案例,所以如果你试试,请告诉我它是否有效。

        function changeUrlParam (param, value) {
            var currentURL = window.location.href;
            var urlObject = currentURL.split('?');
            var newQueryString = '?';

            value = encodeURIComponent(value);

            if(urlObject.length > 1){
                var queries = urlObject[1].split('&');

                var updatedExistingParam = false;
                for (i = 0; i < queries.length; i++){
                    var queryItem = queries[i].split('=');

                    if(queryItem.length > 1){
                         if(queryItem[0] == param){
                            newQueryString += queryItem[0] + '=' + value + '&';
                            updatedExistingParam = true;
                         }else{
                            newQueryString += queryItem[0] + '=' + queryItem[1] + '&';
                         }
                    }
                }
                if(!updatedExistingParam){
                    newQueryString += param + '=' + value + '&';
                }
            }else{
                newQueryString += param + '=' + value + '&';
            }
            window.history.replaceState('', '', urlObject[0] + newQueryString.slice(0, -1));
        }

答案 1 :(得分:2)

也许您可以做的是,而不是常规<a ng-href="#!/OrderList?id={{your.id}}">Link to your ID</a>您可以创建一个带有ng-click指令的链接,该指令绑定到一个函数,该函数检索数据并将其传递给视图。

您的HTML

`<span ng-click="loadListItem(your.id)">Link to your ID</span>`

<div id="your-item-data">
    {{item.id}} - {{item.name}}
</div>

您的控制器

myApp.controller('someController', function($scope) {
    $scope.loadListItem(itemId) = function (
        var myItem;

        // Get item by 'itemId' and assign it to 'myItem' var

        $scope.item = myItem;
    );
});

这样您就可以检索控制器中的项目数据并将其传递给您的视图,而不是更改您的网址。

您没有提供有关控制器/服务实施的详细信息,但我希望这会有所帮助。

答案 2 :(得分:2)

我认为你跟$scope.$on("$routeUpdate", ...)事情走在了正确的轨道上。但是,不是$routeUpdate,而是尝试绑定$routeChangeStart

$scope.$on("$routeChangeStart", function(event, nextRoute, currentRoute){
  if (nextRoute.yourCriteria === currentRoute.yourCriteria){
    //do your location replacement magic
  }
});

如果需要,您甚至可以在路径定义中定义dontUpdateHistory布尔属性,然后在run块中检查该属性:

myApp.config(function($routeProvider){
  $routeProvider.when('/whatever' {
    templateUrl: 'whatever',
    dontUpdateHistory: true  //something like this
  });
}).run(function($rootScope){
  $rootScope.on('$routeChangeStart', function(event, nextRoute, currentRoute){
  if (nextRoute.dontUpdateHistory){
    //do your location replacement magic
  }
});

我还没有测试过这一点,但希望它可以解决这个问题。

答案 3 :(得分:0)

我对任何答案都不满意,经过一些调试后我发现了这个解决方案:

.run(function($rootScope, $location) {
    var replacing;

    $rootScope.$on("$locationChangeStart", function(event, newUrl, oldUrl) {
        if (oldUrl === newUrl) return; // Nobody cares.

        // Make urls relative.
        var baseLength = $location.absUrl().length - $location.url().length;
        newUrl = newUrl.substring(baseLength);
        oldUrl = oldUrl.substring(baseLength);

        // Strip search, leave path only.
        var newPath = newUrl.replace(/\?.*/, "");
        var oldPath = oldUrl.replace(/\?.*/, "");

        // Substantial change, history should be written normally.
        if (oldPath !== newPath) return;

        // We're replacing, just let it happen.
        if (replacing) {
            replacing = false;
            return;
        }

        // We're NOT replacing, scratch it ...          
        event.preventDefault();

        // ... and do the same transition with replace later.
        $rootScope.$evalAsync(function() {
            $location.url(newUrl).replace();
            replacing = true;
        });
    });
})