【问题标题】:How to set URL query params in Vue with Vue-Router如何使用 Vue-Router 在 Vue 中设置 URL 查询参数
【发布时间】:2017-03-15 21:49:47
【问题描述】:

我试图在更改输入字段时使用Vue-router 设置查询参数,我不想导航到其他页面,而只想修改同一页面上的 url 查询参数,我这样做:

this.$router.replace({ query: { q1: "q1" } })

但这也会刷新页面并将y位置设置为0,即滚动到页面顶部。这是设置 URL 查询参数的正确方法还是有更好的方法。


已编辑:

这是我的路由器代码:

export default new Router({
  mode: 'history',
  scrollBehavior: (to, from, savedPosition)  => {
    if (to.hash) {
      return {selector: to.hash}
    } else {
      return {x: 0, y: 0}
    }
  },
  routes: [
    ....... 
    { path: '/user/:id', component: UserView },
  ]
})

【问题讨论】:

    标签: javascript vue-router vue.js


    【解决方案1】:

    好的,所以我一直在尝试向我现有的网址添加一个参数,现在已经有一个星期的参数了,哈哈, 原网址:http://localhost:3000/somelink?param1=test1 我一直在尝试:

    this.$router.push({path: this.$route.path, query: {param2: test2} });
    

    此代码将删除 param1 并变为 http://localhost:3000/somelink?param2=test2

    为了解决这个问题,我使用了fullPath

    this.$router.push({path: this.$route.fullPath, query: {param2: test2} });
    

    现在我成功地在旧参数上添加了参数,结果是

    http://localhost:3000/somelink?param1=test1&param2=test2

    【讨论】:

      【解决方案2】:

      vue路由器在更新时不断刷新页面,最好的解决方案是

        const url = new URL(window.location);
        url.searchParams.set('q', 'q');
        window.history.pushState({}, '', url);
              
      

      【讨论】:

        【解决方案3】:

        您也可以只使用浏览器window.history.replaceState API。它不会重新安装任何组件,也不会导致冗余导航。

        window.history.replaceState(null, null, '?query=myquery');
        

        More info here.

        【讨论】:

          【解决方案4】:

          我的解决办法,不刷新页面也没有报错Avoided redundant navigation to current location

              this.$router.replace(
                {
                  query: Object.assign({ ...this.$route.query }, { newParam: 'value' }),
                },
                () => {}
              )
          

          【讨论】:

          • 这会导致页面滚动到顶部。
          【解决方案5】:

          这是我在不刷新页面的情况下更新 URL 中的查询参数的简单解决方案。确保它适用于您的用例。

          const query = { ...this.$route.query, someParam: 'some-value' };
          this.$router.replace({ query });
          

          【讨论】:

            【解决方案6】:

            我通常为此使用历史对象。它也不会重新加载页面。

            例子:

            history.pushState({}, '', 
                            `/pagepath/path?query=${this.myQueryParam}`);
            

            【讨论】:

              【解决方案7】:

              对于添加多个查询参数,这对我有用(从这里https://forum.vuejs.org/t/vue-router-programmatically-append-to-querystring/3655/5)。

              上面的答案很接近......虽然使用 Object.assign 它会改变 this.$route.query 这不是你想要做的......确保在执行 Object.assign 时第一个参数是 {}

              this.$router.push({ query: Object.assign({}, this.$route.query, { newKey: 'newValue' }) });
              

              【讨论】:

                【解决方案8】:

                如果你试图保留一些参数,同时更改其他参数,请务必复制 vue 路由器查询的状态,不要重复使用它。

                这行得通,因为您正在制作未引用的副本:

                  const query = Object.assign({}, this.$route.query);
                  query.page = page;
                  query.limit = rowsPerPage;
                  await this.$router.push({ query });
                

                虽然下面会导致 Vue Router 认为您正在重用相同的查询并导致 NavigationDuplicated 错误:

                  const query = this.$route.query;
                  query.page = page;
                  query.limit = rowsPerPage;
                  await this.$router.push({ query });
                

                当然,您可以分解查询对象,如下所示,但您需要了解页面的所有查询参数,否则您可能会在结果导航中丢失它们。

                  const { page, limit, ...otherParams } = this.$route.query;
                  await this.$router.push(Object.assign({
                    page: page,
                    limit: rowsPerPage
                  }, otherParams));
                );
                

                注意,虽然上面的示例适用于 push(),但它也适用于 replace()

                使用 vue-router 3.1.6 测试。

                【讨论】:

                  【解决方案9】:

                  无需重新加载页面或刷新 dom,history.pushState 就可以完成这项工作。
                  在你的组件或其他地方添加这个方法来做到这一点:

                  addParamsToLocation(params) {
                    history.pushState(
                      {},
                      null,
                      this.$route.path +
                        '?' +
                        Object.keys(params)
                          .map(key => {
                            return (
                              encodeURIComponent(key) + '=' + encodeURIComponent(params[key])
                            )
                          })
                          .join('&')
                    )
                  }
                  

                  因此,在组件中的任何位置,调用 addParamsToLocation({foo: 'bar'}) 以将当前位置与 window.history 堆栈中的查询参数一起推送。

                  要将查询参数添加到当前位置不推送新的历史记录条目,请改用history.replaceState

                  使用 Vue 2.6.10 和 Nuxt 2.8.1 测试。

                  小心这种方法!
                  Vue Router 不知道 url 发生了变化,所以 pushState 后没有反映 url。

                  【讨论】:

                    【解决方案10】:

                    要一次设置/删除多个查询参数,我最终将以下方法作为我的全局 mixins 的一部分(this 指向 vue 组件):

                        setQuery(query){
                            let obj = Object.assign({}, this.$route.query);
                    
                            Object.keys(query).forEach(key => {
                                let value = query[key];
                                if(value){
                                    obj[key] = value
                                } else {
                                    delete obj[key]
                                }
                            })
                            this.$router.replace({
                                ...this.$router.currentRoute,
                                query: obj
                            })
                        },
                    
                        removeQuery(queryNameArray){
                            let obj = {}
                            queryNameArray.forEach(key => {
                                obj[key] = null
                            })
                            this.setQuery(obj)
                        },
                    

                    【讨论】:

                      【解决方案11】:
                      this.$router.push({ query: Object.assign(this.$route.query, { new: 'param' }) })
                      

                      【讨论】:

                      • 我最喜欢这个答案。不幸的是,这导致Error: Avoided redundant navigation to current location
                      • 修复:this.$router.push({ query: Object.assign({...this.$route.query}, { new: 'param' }) })
                      • 但是现在我想你可以这样做this.$router.push({ query: {...this.$route.query,new: 'param'},) })
                      【解决方案12】:

                      其实你可以这样推送查询:this.$router.push({query: {plan: 'private'}})

                      基于:https://github.com/vuejs/vue-router/issues/1631

                      【讨论】:

                      • "但这也会刷新页面"
                      • 不确定 Vue2,但在 Vue3 中工作起来就像一个魅力(没有页面刷新)
                      【解决方案13】:

                      这是文档中的示例:

                      // with query, resulting in /register?plan=private
                      router.push({ path: 'register', query: { plan: 'private' }})
                      

                      参考:https://router.vuejs.org/en/essentials/navigation.html

                      正如那些文档中提到的,router.replace 的工作方式类似于 router.push

                      所以,您的示例代码中似乎正确。但我认为您可能还需要包含namepath 参数,以便路由器有一些导航到的路线。没有namepath,看起来意义不大。

                      这是我现在的理解:

                      • query 对于路由器是可选的 - 组件构建视图的一些附加信息
                      • namepath 是强制性的 - 它决定了要在 <router-view> 中显示的组件。

                      这可能是您的示例代码中缺少的东西。

                      编辑:cmets 之后的其他详细信息

                      您是否尝试过在这种情况下使用命名路由?你有动态路由,单独提供参数和查询更容易:

                      routes: [
                          { name: 'user-view', path: '/user/:id', component: UserView },
                          // other routes
                      ]
                      

                      然后在你的方法中:

                      this.$router.replace({ name: "user-view", params: {id:"123"}, query: {q1: "q1"} })
                      

                      从技术上讲,上面和this.$router.replace({path: "/user/123", query:{q1: "q1"}}) 之间没有区别,但是在命名路由上提供动态参数比编写路由字符串更容易。但在任何一种情况下,都应考虑查询参数。无论哪种情况,我都找不到处理查询参数的方式有什么问题。

                      进入路由后,您可以获取动态参数为this.$route.params.id,查询参数为this.$route.query.q1

                      【讨论】:

                      • 我也试过给出路径,但这并没有停止滚动到页面顶部,我也用路由器选项编辑了问题,可能那里需要一些改变。
                      • 您的查询参数是否打算滚动到文档中的正确位置?喜欢您在anchor tags 上的其他问题吗?
                      • 不,我只是想在 URL 中添加查询参数,我不想在这里滚动。
                      • 我刚刚测试了本地设置中的选项,查询参数正常工作。如我更新的答案所示,我能够导航到新路线并访问查询参数。所以,问题是 - 你不希望它滚动?还是问题是整个应用又刷新了?
                      • 所以我在同一页面上,当我选择一些输入时,我想将它们添加到 URL 中,但是当我这样做时,会发生滚动。滚动是我的问题。我不想导航到其他页面,我只想在同一页面上并无缝地添加/修改 url 查询参数。
                      猜你喜欢
                      • 2018-08-14
                      • 2017-07-02
                      • 2022-12-13
                      • 2020-08-12
                      • 1970-01-01
                      • 2020-11-05
                      • 2022-12-22
                      • 2020-08-11
                      • 1970-01-01
                      相关资源
                      最近更新 更多