前言
最近做了一个项目,由于是Electron嵌入web应用,因此进入web应用时的地址栏参数是不可控的,web应用在路由跳转的时候顺带了一些查询参数,像这样:
#/home?title=xxxx&id=12345,
通过withrouter之后的location.search拿到了
?title=xxxx&id=12345
但是在Electron中它的地址是这样的:
?jkljkll#/home??title=xxxx&id=12345
于是便拿不到我们需要的值了,此时我们又需要修改很多代码,来适应这个地址,那么又没有一种最好的办法能够不修改代码,在之前的应用开发中就考虑到所有情况呢?
从location开始思考
search在前hash在后,location.search能够直接拿到查询参数
先随便输入一个地址,我们只需要关注hash和search即可 www.jianshu.com/p/33deff6b8…
location 对象可以得到以下信息: hash: "#123213"
pathname: "/p/33deff6b8a63"
search: "?a=1231313"
当search在前,hash在后面时,此时 hash 和 search 是分开的,location.search能够直接拿到查询参数
当search在hash后面,search必须从location.hash中做处理后才能取到
变化一下如果在地址后面又添加查询参数?a=1&b=2 www.jianshu.com/p/33deff6b8…
hash: "#123213?a=1&b=2"
hash: "#123213?a=1&b=2"
search: ""
当hash出现,它就吞并了所有内容,连查询参数也无法显示出来,全部都在location.hash中
我们能把search放在前面吗
在单页应用的世界里,如果每次跳转都将search放在前面那么就会导致页面刷新,这样的话就违背了单页的原则
如果是多页应用跳转的话则可以将search放在前面
VueRouter和ReactRouter对于地址栏参数的解析方式
VueRouter能够快速解析出hash中的search,而react-router和原生的hash一样,必须自己去处理
但是对于路由参数两者都能快速解析出来
Vue Router
能够将 location.search 从 location.hash 解析出来,但是它只能解析hash中的search
this.$route.query // {a: "123213"}
Vue Router 里面的 query 类似于请求中的 get,而 params 类似于请求中的 post 能够不在地址栏显示就能够完成参数传递
React Router
const reactHistory = useHistory()
useHistory 创建的对象,它的 location 属性与原生基本没有差别
location:
hash: "#1231?23213"
pathname: "/"
search: "?213123"
state: undefined
push: ƒ push(path, state)
replace: ƒ replace(path, state)
const reactLocation = useLocation()
location,使用 hooks 或者 withRouter,可以拿到,基本与 history.location 相同
hash: '#1231?23213'
pathname: '/'
search: '?213123'
state: undefined
const reactParams = useParams()
路由参数
<Route path='/about/:id'>
<About />
</Route>
<Link to="/about/1">About</Link>
console.log(reactParams)
{id: "1"}
查询参数的最佳方案
需要根据自己的实际情况进行选择
尽量少地添加查询参数,或者全部使用路由参数
在Vue中可以使用类似与POST的方式传参,比较优雅,地址栏不会有乱七八糟的东西
对于React就使用多个路由参数,这样的缺点是必须按照顺序一一对应
/?:id/?:title/?:bb
天塌下来也从hash中取,保证hash中只有一个?
ps: 提前封装好地址解析参数也很重要哦
最后希望和大家一起讨论更好的方案,说的不对的地方清大家指出来