vue路由地址栏变化的问题

在做一个查询页面,希望达到下面的效果

  1. 用户筛选完条件后,点击查询按钮时同时更新地址栏参数
  2. 用户直接更改地址栏参数的时候,可以触发页面的重新渲染.

实现这个效果的根本目的是想在分享链接的时候把当前的参数也携带上,方便接收的同学看到相应的效果.

目前使用了route.replace和watch route来进行实现,不过在页面第一次打开的时候,会触发两次后端调用,感觉做的方式有问题。

示例代码:

export default {  
  watch: {  
    '$route'(to, from) {  
      //监听路由变化
      this.timeInst = [to.query.startTime, to.query.endTime]  
          this.selectedTestGroup = to.query.testGroup  
      this.selectedStatus = to.query.status  
      this.load()  
    }  
  },  
  
  mounted() {  
    this.load()  
  },
  
  methods: {  
  
    load() {  
  
      console.log("taskLog load")  
      //变更地址栏中的参数
      this.$router.replace({  
        path: this.$route.path, query:  
          {  
              startTime: this.timeInst[0],  
              endTime: this.timeInst[1],  
              testGroup: this.selectedTestGroup,  
              status: this.selectedStatus  
          }  
      })  
      this.loading= true  
      strategyApi.queryTaskLogs(  
            parseAndGetUnixTimestamp(this.timeInst[0]),  
      parseAndGetUnixTimestamp(this.timeInst[1]),  
      this.selectedTestGroup,  
      this.selectedStatus  
  )
}

两次的原因是因为第一次replace后导致route发生变化,进而又触发了一次load操作.

我想了下,可以通过添加一些判断逻辑避免两次加载的问题。不过还是想问下是否有更好的方式解决这种问题呢? 谢谢

修改后的代码示例

export default {
  name: 'strategy-task-logs',
  watch: {
    '$route'(to, from) {
      // react to route changes...
      this.timeInst = [to.query.startTime, to.query.endTime]
      this.selectedTestGroup = to.query.testGroup
      this.selectedStatus = to.query.status
      this.load()
    }
  },

  methods: {

    //用户点击时,push路由进而执行load
    search() {
      this.$router.push({
        path: this.$route.path, query:
          {
            startTime: this.timeInst[0],
            endTime: this.timeInst[1],
            testGroup: this.selectedTestGroup,
            status: this.selectedStatus
          }
      })
    },

    load() {
      console.log('taskLog load')
      this.loading = true
      strategyApi.queryTaskLogs(
        parseAndGetUnixTimestamp(this.timeInst[0]),
        parseAndGetUnixTimestamp(this.timeInst[1]),
        this.selectedTestGroup,
        this.selectedStatus
      )
      .then(response => {
        if (response.success) {
          this.logs = response.data
        }
      }).finally(() => {
        this.loading = false
      })
    }
  },

  mounted() {
    let currentPath = this.$route.fullPath
    this.$router.replace({
      path: this.$route.path, query:
        {
          startTime: this.timeInst[0],
          endTime: this.timeInst[1],
          testGroup: this.selectedTestGroup,
          status: this.selectedStatus
        }
    })
    let updatePath = this.$route.fullPath
    
    if (currentPath === updatePath) {
      this.load()
    }
  },


  data: function() {

    let startTime = _.isEmpty(this.$route.query.startTime) ? getStartOfToday() : this.$route.query.startTime
    let endTime = _.isEmpty(this.$route.query.endTime) ? getNow() : this.$route.query.endTime

    return {
      timeInst: [startTime, endTime],
      selectedTestGroup: _.isEmpty(this.$route.query.testGroup) ? '*' : this.$route.query.testGroup,
      selectedStatus: _.isEmpty(this.$route.query.status) ? '*' : this.$route.query.status,
    }
  }
}
已解决 悬赏分:40 - 解决时间 2021-11-28 18:53
反对 0举报 0 收藏 0

回答2

最佳
  • @

    你这个有点重复调用的意思了。mounted里就不要了,只监听route的改变,改变就调用接口。timeInst、selectedTestGroup 这些属性存在的意义需要考虑,因为已经可以从query获取到了。

    export default () {
      watch: {
        '$route': {
            handler () {
                this.load()
            }
        }
      },
      computed: {
        selectedStatus: {
          get () { return this.$route.query.status },
          set (value) {
            if (value !== this.$route.query.status) {
              let { query, path } = this.$route
              query = { ...query, status: value }
              this.$router.push({ path, query })
            }
          }
        }
      },
      mounted () {
        this.checkRoute()
      },
      methods: {
        checkRoute () {
          let { query: q, path } = this.$route.query
          let default = { startTime: 'xxx1', endTime: 'xxx2', testGroup: 'xxx3', status: 'xxx4'  }
          
          let keys = Object.keys(default)
          if (keys.every(k => q[k] !== undefined)) { // 所有参数都传递了,则调用一次load
            this.load()
          } else { // 有的参数没传递,则设置为默认值,此时直接改query就行会触发watch,不需要调用load
            let query = Object.assign({}, default, q)
            this.$router.push({ path, query })
          }
        },
        load () {
          let query = this.$route.query
          strategyApi.queryTaskLogs(
            parseAndGetUnixTimestamp(query.startTime),  
            parseAndGetUnixTimestamp(query.endTime),  
            query.testGroup,  
            query.status)
         }
      }
    
    }
    
    支持 0 反对 0 举报
    2021-11-28 11:09
  • @

    可以改成动态路由

    改变参数,直接跳转.

    支持 0 反对 0 举报
    2021-11-28 11:25