Как установить параметры URL-запроса во Vue с помощью Vue-Router

117

Я пытаюсь установить параметры запроса с помощью 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 },
  ]
})
Саураб
источник

Ответы:

136

Вот пример в документации:

// 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

Итак, вы, кажется, правильно поняли этот пример кода. Но я думаю, что вам может потребоваться включить параметр или nameили path, чтобы у маршрутизатора был какой-то маршрут для перехода. Без nameили pathэто не выглядит очень значимым.

Это мое текущее понимание сейчас:

  • query не является обязательным для маршрутизатора - некоторая дополнительная информация для компонента для создания представления
  • nameили pathобязательно - он решает, какой компонент показывать в вашем <router-view>.

Возможно, этого не хватает в вашем примере кода.

РЕДАКТИРОВАТЬ: дополнительные сведения после комментариев

Вы пробовали использовать в этом случае именованные маршруты ? У вас есть динамические маршруты, и проще предоставить параметры и запрос отдельно:

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.

Мани
источник
Я также попытался указать путь, но это не остановило прокрутку до верхней части страницы, я также отредактировал вопрос с параметрами маршрутизатора, возможно, там требуется какое-то изменение.
Saurabh
Ваш параметр запроса предназначен для прокрутки в нужное место в документе? Нравится ваш другой вопрос о тегах привязки ?
Mani
Нет, я просто хочу добавить параметр запроса в URL, мне не нужна прокрутка здесь.
Saurabh
Я только что протестировал параметры в своей локальной настройке, параметры запроса работают нормально. Я могу перейти к новому маршруту и ​​получить доступ к параметрам запроса, как показано в моем обновленном ответе. Итак, проблема - вы не хотите прокручивать? Или проблема в том, что все приложение снова обновляется?
Mani
поэтому я нахожусь на той же странице, когда я выбираю какой-либо ввод, я хочу добавить их в URL-адрес, но когда я это делаю, происходит прокрутка. Для меня проблема со свитком. Я не пытаюсь перейти на другую страницу, я просто хочу быть на той же странице и незаметно добавлять / изменять параметры запроса URL.
Saurabh
17

Не перезагружая страницу или не обновляя дом, 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-адрес изменился, поэтому он не отражает URL-адрес после pushState.

ManUtopiK
источник
13

На самом деле вы можете просто отправить запрос следующим образом: this.$router.push({query: {plan: 'private'}})

По материалам: https://github.com/vuejs/vue-router/issues/1631

Жан д'арм
источник
13
«Но это также обновляет страницу»
digout
5
this.$router.push({ query: Object.assign(this.$route.query, { new: 'param' }) })
Бостон Кенн
источник
1
Мне больше всего понравился этот ответ. К сожалению, это вызываетError: Avoided redundant navigation to current location
Макс Коплан
Исправление:this.$router.push({ query: Object.assign({...this.$route.query}, { new: 'param' }) })
Макс Коплан
2
Но теперь, когда я думаю об этом, вы можете просто сделатьthis.$router.push({ query: {...this.$route.query,new: 'param'},) })
Макс Коплан
4

Для добавления нескольких параметров запроса это сработало для меня (отсюда 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' }) });
Борис
источник
3

Если вы пытаетесь сохранить одни параметры при изменении других, обязательно скопируйте состояние запроса маршрутизатора 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.

Андре М
источник
2

Чтобы установить / удалить сразу несколько параметров запроса, я использовал следующие методы как часть моих глобальных миксинов ( 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)
    },
вирус
источник
1

Обычно я использую для этого объект истории. Он также не перезагружает страницу.

Пример:

history.pushState({}, '', 
                `/pagepath/path?query=${this.myQueryParam}`);
Мостафа
источник
0

Вот мое простое решение для обновления параметров запроса в URL-адресе без обновления страницы. Убедитесь, что он подходит для вашего варианта использования.

const query = { ...this.$route.query, someParam: 'some-value' };
this.$router.replace({ query });
parker_codes
источник