vue-router 修改或添加新参数

12,424 阅读1分钟

需求

在学习用vue做项目中,有这样一个需求,在某个页面中有一个分页组件,组件的功能有一个是点击某一数字,需要往url中push参数,但原来url中可能有其他的参数,也有可能没有其他参数,有可能已经有关于页数的参数,也有可能没有,使用$router.push()的形式则会覆盖原有的query,因此开始了我的探索之路(可以直接看最后结论)

step 1 (查找其他方法)

主要试图找到其他方法,可以直接添加新参数或者修改已有参数,绕过需要获取已有参数的坑

很明显失败了,一个是没有找到其他方法,二是$router.push()也没有发现满足我需求的调用方法,因此确定必须要获取原有参数,进行修改或者新增,最后调用$router.push()完成任务

step 2 (确定思路)

经过思考,我觉得代码逻辑应该是这样:

methods: {
    changePage (num) {
        var _this = this,
            oldQuery = _this.$router.currentRoute.query,
            newQuery = _this.getNewQuery(oldQuery, 'page', num);
            
        _this.$router.push({
            query: newQuery
        })
    }
    
    getNewQuery (oldQuery, name, val) {
        var obj = {}, // 这里初始化一定是{}而不是null,否则会出错
            flag = false;
        
        for (key in oldQuery) {
            if (oldQuery.hasOwnProperty(key)) {
                if (key === name) {
                    // 这里是修改已有参数
                    obj[key] = val;
                    flag = true;
                } else {
                    obj[key] = oldQuery[key]
                }
            }
        }
        
        // 这里是新增参数
        if (!flag) {
            obj[name] = val
        }
        return obj;
    }
}

到此已经可以完成任务了

step3 (尝试优化,假如要添加或者修改多个参数)

这样是可以完成任务的,然后我又想了一下,如果是要修改或者是添加多个参数呢,可以把要修改或者添加的放到一个对象中,大概是这样

methods: {
    changePage (num) {
        var _this = this,
            oldQuery = _this.$router.currentRoute.query,
            obj = {
                page: num,
                category: 'all'
            },
            newQuery = _this.getNewQuery(oldQuery, obj);
            
        _this.$router.push({
            query: newQuery
        })
    }
    
    getNewQuery (oldQuery, new) {
        var obj = {}, // 这里初始化一定是{}而不是null,否则会出错
            flag = false;
        
        obj = ....(这里还没想清楚怎么写)
        
        return obj;
    }
}

这时突然发现,这不就是两个对象合并吗,好像有个原生方法可以直接用啊——Object.assign(obj1, obj2),如果能成功的话,那根本不用写个新函数啊(当初我还再想为啥vue-router不提供一个类似我上面实现的函数)

step4 (尝试Object.assign())

因为这里涉及到深浅拷贝的知识,我就顺便又学习了一下深浅拷贝对象深拷贝的两种方法

methods: {
    changePage (num) {
        Object.assign(_this.$router.currentRoute.query, {page: num})
    }
}

讲道理我感觉已经完成任务了,但实际情况是我打开devtool,发现$route.query确实和我想的一样变化,但是url没有变,可能直接修改$route.query参数不管用,必须调用$route.push()方法,因此再作调整(这里究竟为什么直接改query参数不管用,应该是涉及到了vue-router的源码实现,目前这阶段,我就先忽视了。。。):

final

methods: {
    changePage (num) {
       var _this = this,
        obj = JSON.parse(JSON.stringify(_this.$router.currentRoute.query)) // 这里我们需要的应该是值,因此必须转为深拷贝
      Object.assign(obj, {page: num})
      _this.$router.push({
        query: obj
      })
    }
}

成功!(不忘忘记巩固一下数组、对象各自的深浅拷贝方法啊)