Vuejs vue-router クエリパラメータの一部だけを取り除く

課題

  • Vuejs利用時に、以下のようにクエリパラメータを一部のみ取り除きたい
    • 検索したらURLにクエリパラメータが付与される
    • ボタンを押したら対応するクエリパラメータだけURLから削除される

f:id:kimulla:20191201185935g:plain

検証環境

  "dependencies": {
    "vue": "^2.5.2",
    "vue-router": "^3.0.1"
  }

解決方法

queryオブジェクトをvue-routerから取得し、クエリパラメータを除去して再設定する。

<template>
  <div>
  <div>
    <form @submit.prevent="$router.push({query: {q: q, type: type} })">
    <input type="text" v-model="q" />
    <input type="text" v-model="type" />
    <button type="submit">絞り込む</button>
    </form>
  </div>
  <div style="margin-top:30px">
    <button @click="deleteQuery('q')" type="button">X 絞り込みワード</button>
    <button @click="deleteQuery('type')" type="button">X タイプ</button>
  </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data () {
  return {
    q: null,
    type: null
  }
  },
  methods: {
    deleteQuery: function (key) {
      var query = Object.assign({}, this.$route.query)
      delete query[key]
      this.$router.push({query: query})
    }
  }
}
</script>

注意点

\$routeオブジェクトの戻り値のqueryをそのまま利用しないこと

以下のように\$routeオブジェクトの戻り値のqueryをそのまま利用すると、\$router.pushしたときにvue-routerがパラメータの変更を検出できず、URLが切り替わらない。

<script>
...
    deleteQuery: function (key) {
      var query = this.$route.query
      delete query[key]
      this.$router.push({query: query})
    }
</script>

どうやら、内部で$routeオブジェクトを比較してリクエストするかどうか判別してる様子。
参考: vue router ソースコード

なので、戻り値と同じオブジェクトを再設定すると、差分がないと勘違いしてしまう。 ややハマったので注意。