如何在Vue.js中从URL获取查询参数?

544

我如何在Vue.js中获取查询参数?

例如:

http://somesite.com?test=yay

我找不到获取数据的方法,是需要使用纯JS或某个库吗?


21
为什么这个被点踩了?我需要它用于Vue.js。如果有一些Vue库或内置的东西,那比原始的js更好。 - Rob
72
没有任何一份内容是近似复制的。[tag:vue.js] 是一个具有特定逻辑的框架,与纯 JavaScript 不同。 - Yerko Palma
27
没有使用vue-router,如何实现这个目标? - Connor Leech
@ConnorLeech 不确定为什么你想跳过vue-router,因为它是专为Vue设计的。请使用提供的API。 - kissu
14个回答

720
根据路由对象的文档,你可以从组件中访问到一个$route对象,它提供了你所需的内容。在这种情况下,
// from your component
console.log(this.$route.query.test) // outputs 'yay'

15
如果他没有使用vue-router,那么这将是一个重复的问题,因为他需要使用标准的JS方法。 - Jeff
1
问题在于Vue文档认为将组件与路由器耦合是不可取的。他们建议传递props,但似乎无法将查询参数动态地作为props传递。例如,在beforeEach守卫中执行类似于return next({name: 'login',query:{param1: "foo" },});的操作是无效的。在登录组件内,prop“param1”未定义。 - hraynaud
3
很遗憾,这仅适用于哈希部分(URL片段)中的URL查询参数,而不是像原帖所示的普通查询参数。以下是我认为适用于原帖的正确回答链接:https://dev59.com/6K7la4cB1Zd3GeqPi8Y3#52587655。 - Marcel
1
在Vue.js 3中怎么样? - Nanda Z
-bundler.js:220 未捕获的类型错误:无法读取未定义的属性(读取“query”) 在 Proxy.button_update (Update.vue:71:31) 在 _createElementVNode.onCl - CS QGB
链接现在已经失效了。请考虑使用新链接更新答案 https://v3.router.vuejs.org/api/#route-object-properties - undefined

97

没有使用vue-router,分割URL

var vm = new Vue({
  ....
  created() {
    let uri = window.location.href.split('?');
    if(uri.length == 2) {
      let vars = uri[1].split('&');
      let getVars = {};
      let tmp = '';
      vars.forEach(function(v) {
        tmp = v.split('=');
        if(tmp.length == 2)
          getVars[tmp[0]] = tmp[1];
      });
      console.log(getVars);
      // do 
    }
  },
  updated() {
  },
....

另一种解决方案为https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLHyperlinkElementUtils/search:

var vm = new Vue({
  ....
  created() {
    let uri = window.location.search.substring(1); 
    let params = new URLSearchParams(uri);
    console.log(params.get("var_name"));
  },
  updated() {
  },
....

9
location.search已准备好可用时,为什么要自己分割location.href?请参考:https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search 例如:var querypairs = window.location.search.substr(1).split('&'); 同时,通过'='分割查询名称-值对并不总是有效的,因为您也可以传递没有值的命名查询参数,例如:?par1=15&par2 在这种情况下,您的代码将引发异常,因为按'='分割会导致tmp数组只有一个元素。 - Arthur
3
抱歉不会抛出异常,但您也无法捕获par2。因为您基本上将“undefined”赋值给了“getVars ['par2']”。 - Arthur
GET方法是一个字符串(名称/值对),在URL中。 - erajuan
@Arthur 你说得对,我添加了一个验证并且加入了另一个解决方案。谢谢。 - erajuan
.substring(1) 看起来是不必要的。 - Tofandel
避免在Vue中使用路由器的用例是什么?有什么优点吗? - nosbor

95

尝试这段代码

var vm = new Vue({
  created() {
    let urlParams = new URLSearchParams(window.location.search);
    console.log(urlParams.has('yourParam')); // true
    console.log(urlParams.get('yourParam')); // "MyParam"
  },
});

4
非常优美的回答。谢谢!当然,没有使用 vue-router。 - Yamen Ashraf
URLSearchParams是一种纯JavaScript方法,它不是vuejs的帮助程序。 - Muhammad
1
@mrded为什么采用这种方法更好,考虑到Vue和显然已经在使用Vue Router? - Igor
2
@Igor 因为这是JS的本地方式,而且它可以在任何地方工作。Vue Router只是一个不必要的抽象。 - mrded
参与了Vue CDN的开发 => index.html?youParams=xxx - Bcktr
这里我要向你宣布,一些应用程序也在使用 SSR(例如 Nuxt),因此 window 不可用。这确实是一种糟糕的方法,迄今为止没有什么优雅的东西。请使用 Vue 生态系统提供的给定 API。Vue-router 是响应式的,并且考虑到了几个方面,如果创建它,那么有一个有效的原因。这不是为了好玩而做的事情。我希望没有人在这里使用 window.location.href,否则每个人都会摧毁他们的 SPA。 - kissu

59

为了帮助VueJS的新手更好地理解,以下是更详细的回答:

  • 首先定义你的路由对象,并选择适合的模式。你可以在路由列表中声明你的路由。
  • 接下来,你希望主应用程序知道路由存在,因此在主应用程序声明中声明它。
  • 最后,$route实例保存有关当前路由的所有信息。该代码将仅在控制台记录传递到URL中的参数。(*Mounted类似于document.ready,即在应用程序准备就绪时立即调用)

代码本身:

<script src="https://unpkg.com/vue-router"></script>
var router = new VueRouter({
    mode: 'history',
    routes: []
});
var vm =  new Vue({
    router,
    el: '#app',
    mounted: function() {
        q = this.$route.query.q
        console.log(q)
    },
});

3
对于那些非常新手的人来说:VueJS核心中并不包括VueRouter,因此您可能需要单独引入VueRouter: <script src="https://unpkg.com/vue-router"></script> - rustyx
2
{btsdaf} - Simon Forsberg
1
new Vue({ router, ... }) 不是有效的语法。 - Crescent Fresh
脚本部分使用了ES6,我认为这对新手来说会使情况变得更糟。要么完全采用ES6,使用适当的变量声明和箭头函数,要么使用传统的方式。 - Muhyee
@CrescentFresh 在 ES6 中,new Vue({ router, ... }) 是一种简写方式。在普通的 JavaScript 中是 new Vue({ 'router': router, ... })。 - Muhyee

51

另一种方法(假设您正在使用vue-router),是将查询参数映射到路由器中的一个属性。然后,您可以像在组件代码中处理任何其他属性一样处理它。例如,添加这个路由;

{ 
  path: '/mypage', 
  name: 'mypage', 
  component: MyPage, 
  props: (route) => ({ foo: route.query.foo }),  
}

然后在您的组件中,您可以像平常一样添加该属性;

props: {
  foo: {
    type: String,
    default: null,
  }
},

然后它将作为this.foo可用,您可以对其执行任何操作(例如设置观察程序等)。


5
太好了。拼图缺失的一块是启动。您可以这样做:this.$router.push({ name: 'mypage', query: { foo: 'bar' } }) - slf
2
这是最佳解决方案。这应该在顶部。根据我的意见,这应该被包括为最佳实践。 - knkbga
在我的情况下,最好且最简单的解决方案。谢谢! - Sqdz

43

Vue 3 组合式 API

(截至2021年,vue-router版本为4)

import {useRoute} from "vue-router";

//can use only in setup()
useRoute().query.test
或者
//somewhere in your src files
import router from "~/router";

//can use everywhere 
router.currentRoute.value.query.test  
或者
import {useRouter} from "vue-router";

//can use only in setup()
useRouter().currentRoute.value.query.test

1
提醒任何阅读此内容的人,第一个导入语句应该是从“vue-router”导入{ useRoute }。 - nth-child
我正在使用第三个示例。我尝试在setup()中使用console.log(useRouter().currentRoute.value.query.test),但是出现了错误:“未找到注入“Symbol([vue-router]: router)””。我安装了vue-router@next并导入了useRouter……有什么想法为什么会出现这个错误? - St. Jan
1
@WillyBurb 看起来你没有将 vue-router 注入到 Vue 中。回到文档中,搜索 app.use(router)。 - Alexandr
成功了,谢谢! - St. Jan
三种替代方案,使用自定义导入,而不是简单的“this.$route.query.test”。 - Victor Gavro
@VictorGavro "this.$route.query.test" 只适用于 vue2 语法,答案是专门为搜索 Vue3 组合 API 的人而设计的,正如我的解决方案的标题和代码注释所述。 - Alexandr

16
截至目前,正确的方式根据动态路由文档是:
this.$route.params.yourProperty

替代

this.$route.query.yourProperty

10
它们不是同一件事情!你应该使用“query”从URL获取查询。从文档中可以看到:除了 $route.params 之外,$route 对象还公开了其他有用的信息,如 $route.query(如果URL中有查询参数)。 - hatef
3
你的答案是错误的,这不是“正确的方法”。简单解释一下,使用{ path: '/user/:id' },URL /user/123?a=b&c=d 将会有 $route.params == { id: "123" }$route.query == { a: "b", c: "d" } - phil294
1
我看到你有一个误解,params 指的是 URL 中的参数,例如 /user/:username。你可以看到这里的 username 是一个 params,但是查询参数则像这样 /search/?q='new Vue js'。正如你所见,new Vue js 在此处是一个查询参数。而且,文档中没有任何证据证明你的答案是正确的。请告诉我在文档的哪一行中你看到了这些内容? - Iman Shafiei
当时文档是针对2.x版本的。你可以看到很多人点赞,所以在某个时候它是有效的。 - Marco
截至目前,编写循环的正确方式是使用if语句。 - nosbor
显示剩余3条评论

6
如果你正在使用vue3 composition api和vue-router,以下是如何操作的。
import { useRoute } from 'vue-router'

export default {
  setup() {
    const route = useRoute()
    console.log(route.query)
  }
}

你也可以使用 <script setup>,直接跳过 setup() 部分。 - kissu

6
如果您的网址看起来像这样:
somesite.com/something/123

在参数名为'id'的情况下(URL类似于/something/:id),尝试使用'123'作为参数:

this.$route.params.id

这不是一个查询参数。快速阅读一下这个链接:https://dev59.com/UFsV5IYBdhLWcg3wsQnf#frulEYcBWogLw_1bEi1w - kissu

6
您可以使用vue-router。以下是一个示例: URL: www.example.com?name=john&lastName=doe
new Vue({
  el: "#app",
  data: {
    name: '',
    lastName: '',
  },
  beforeRouteEnter(to, from, next) {
    if(Object.keys(to.query).length !== 0) { //if the url has query (?query)
      next(vm => {
        vm.name = to.query.name;
        vm.lastName = to.query.lastName;
      });
    }
    next();
  }
})

注意:beforeRouteEnter函数中,我们无法访问组件的属性,例如:this.propertyName。这就是为什么我将vm传递给next函数的原因。这是访问Vue实例的推荐方式。事实上,vm代表的就是Vue实例。


在最新的 Laravel + Vue 设置中,使用链接 site.com/route?query=test 时,在 beforeRouteEnter(to, from, next) 方法中通过 to 参数访问 query 参数时返回 undefined。有任何想法为什么会这样? - askepott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接