先说一下我做项目中遇到的问题,假如我当前有一个页面地址:
xzy.com/#/home/new?group=256
当用户在没有登录的情况下访问该地址,页面需要路由到 /signin路径下。最开始想到的就是使用$location.path([path])方法。但是使用$location.path有一个蛋疼的问题,他会自动将 ‘? ’后边的参数也一块儿带着:
xzy.com/#/signin?group=256
由于angularjs接触时间不是很长,很长时间内都没找到具体的解决方案。最后无意间看到了$window.location.hash这个东西,瞬间就拯救了我,下面就仔细分析一下。
Angularjs 提供了一套自动路由的机制,对前端人员来说真是开发利器,使得我们不需要刷新页面,也可以进行页面跳转。但是在使用过程中会有很多让人觉得混乱的地方。其实是URI构成的理解还不到位。
借助于OData官网的文档,我们可以看看URI的组成。
其实这里边还少了一个部分:fragment(片段),表现形式就是:#xxx。英文里的hash其实就是 ‘#’符号。它是什么意思呢,来看一个官方的例子:
// given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
var hash = $location.hash();
// => "hashValue"
这个hash主要是用来告诉浏览器,保留当前地址,不要刷新页面,然后在当前地址中添加一个hash符号和一个标识符,上边例子中hashValue就是标识符。
明白了这些结构,我们就可以理解angular提供的一些方法的含义,比如说我们进行一个路由跳转的时候,用的最多的是 $location.path(“/xxx”) 以及angular提供的ng-href=”#xxx”。下面介绍这两种方式。
在这之前,你可能需要了解一点儿关于url中hash的知识,不清楚的可以看看这里:
$location.path() vs $location.hash() in angularjs
There are two parts to the route.
The first "hash" is really there just for browser compatibility and won't show if you are in HTML5 mode.
For example, given this URL:
http://localhost/spa.htm
If you set:
$location.path('/myPath');
you will get:
http://localhost/spa.htm#/myPath
In this case, the "hash" is just for the browser to hold the URL, the method is path. Note also when you call path without a preceding / it is added, i.e. 'myPath' becomes '/myPath'.
If you subsequently set:
$location.hash('myHash');
You will get:
http://localhost/spa.htm#/myPath#myHash
Finally, let's assume you did not set the path first, then you'll get:
http://locahost/spa.htm#/#myHash
If you are using HTML5 mode, the path is appended without the initial hash.
The first hash is used to append the route, the second is a reference to content on the page. For example, if you use the $anchorScroll service it will respond to what is placed in $location.hash() and not in $location.path().
To summarize:
**总结一下url的格式**
http://localhost/spa.htm#{path}#{hash}
1. 手动跳转
手动路由有两种方式:$location.path([path]) 和 $window.location.hash=’#/[path]’。
1. $location.path
$location.path([path])这个方法其实只是改变了URI PATH部分的值,所以, 跳转之前的url中 ‘?’后边query的部分会原封不动的append在新的url上。
比如跳转之前是这样:
http://10.103.211.59:8080/sample/A/B/?pid=12&uid=123
在使用了 $location.path(‘/C’)之后,就变成了这样:
http://10.103.211.59:8080/sample/C?pid=12&uid=123。
注:这里sample是所谓的context name,简单理解就是项目名。
2.$window.location.hash
$window.location.hash 相对于 $location.path更灵活一些,可以用来获取或设置页面的标签值,借助于定位锚,可以很方便的改变路由,即使页面中并不存在这样一个锚点。它可以直接对整个url进行调整,可以去掉 $location.path 无法去掉的累赘部分: query。
但是这里头有一个小坑注意一下,就是后边给hash的值,一定得是这样的格式:
#/xxxx/yyy?abc=13435
就是说在 ‘#’号之后得有个 ‘/’ 符号,来标识这是一个path。否则你在监听$routeChangeStart 事件的时候,会触发两遍。本人亲身体验,确实是这样,至于原因还没找到,只是看那个调用栈,是从jquery开始的事件分发,不知道为什么会调用两次,以后有时间查一下。
2. 自动跳转
ng-href就比较好用了,直接写在<a>
标签上,只不过原来的href属性被ng-href替换掉了,angular会自动为我们生成href属性,通过元素查看器可以看到运行时的值。这样页面跳转的时候,需要什么参数直接跟在路径后边,比如:
#ordermanagement?orderid=153355945
使用这种方式,你不但可以使用相对路径跳转,还可以使用绝对地址进行跳转。但是如果你不想在url上向用户暴漏太多参数的话,还是不要使用这种方式,而应该自己添加事件,事件中手动使用 $location.path([path]) 或者 $window.location.hash = #/[path]。
之前看国内的阿里云的前端技术分享,他们的阿里云目前就是在使用angularjs作为前端的框架。可以看到他们的url地址进行跳转的时候就是用类似于location hash的这种方式: