简体   繁体   中英

Vue.js - search form with query parameters

I am using Vue.js 2.6 with the vue-router component. I have a search form as follows:

<form class="search-form" @submit.prevent="search">
    <div class="form-group">
        <input type="text" class="form-control" v-model="term" placeholder="Search">
    </div>
</form>

And here is my script:

<script>
  export default {
    data() {
      return {
        term: this.$route.query.term,
        items: []
      }
    },
    created() {
      if (this.term != null) {
        this.search()
      }
    },
    watch: {
      '$route.query.term'() {
        this.term = this.$route.query.term
        this.search()
      }
    },
    methods: {
      search: function () {
        window.axios.get('/images/search', {
          params: {
            term: this.term
          }
        })
        .then(response => {
          this.$router.push({query: { 'term' : this.term}})
          this.items = response.data.collection.items
        })
        .catch(error => {
          return error
        })
      }
    }
  }
</script>

What I am trying to achieve with this code is the following:

  1. User submits form, the search() function is called. The URL is updated with the query param, eg /search?term=<term> . This is working but the search() function is being called twice.
  2. User carries out several searches, then presses the back button. The search field in the form is updated and the search is carried out. This is working but the search() function is being called twice.
  3. User manually enters query param in the URL bar. The search field in the form is populated and the search is carried out. This is working.

Where the search() function is being called twice, this is due to the watch() function, which is designed to watch changes to the URL bar. I am not sure how to combine this function correctly with the search() function.

In watch , you can compare new value with old value, and only perform search when new value is different with old value

watch: {
  '$route.query.term'(newVal, oldVal) {
    if (newVal != oldVal) {
      this.term = this.$route.query.term
      this.search()
    }
  }
},

To make it call only 1 for 1st case, you might want to separate button click handler with real search call

<script>
  export default {
    data() {
      return {
        term: this.$route.query.term,
        items: []
      }
    },
    created() {
      if (this.term != null) {
        this.performSearch()
      }
    },
    watch: {
      '$route.query.term': {
        handler: function(newVal, oldVal) {
          if (newVal != oldVal) {
            this.term = this.$route.query.term
            this.performSearch()
          }
        },
        immediate: true 
      }
    },
    methods: {
      search: function () {
        // this is call when user click search Button
        this.$router.push({query: { 'term' : this.term}})

      },
      performSearch() {
        // perform actual searcch
        window.axios.get('/images/search', {
          params: {
            term: this.term
          }
        })
        .then(response => {
          this.items = response.data.collection.items
        })
        .catch(error => {
          return error
        })
      }
    }
  }
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM