如何通过共享 url 来共享 vue 组件状态?

时间:2021-05-06 09:38:18

标签: vue.js vue-component vue-router

我的设置

  1. 我有一个显示数据表的组件。

  2. 可以通过将内容输入到存储在组件 props 中的值来过滤数据。

  3. 我也有 vue-router 来在这个组件和其他组件之间路由。

我的愿望

  1. 我想通过为某个团队成员提供一个 url 来与他或她分享我过滤表的状态。

  2. 当访问 url 时,props 会从 url 中分配值,瞧,我得到了相同的列表。

  3. 参数并不是每次都需要。因此,如果我仅按其中一个字段进行过滤,则只需要该参数来传递 url。

我的问题

  1. 我该怎么做?
  2. 我没有看到哪些陷阱?

到目前为止我尝试过的...

...通过this.$router.push()改变道具来玩弄watch()函数;但我无法弄清楚一方面如何避免重新加载页面,另一方面如何不调整服务器配置(因为我希望路由也可以在没有任何参数的情况下工作)。

到目前为止我还没有弄清楚如何在路由器配置中定义动态 url ......有没有办法,或者你是否为每个可能的配置创建别名,如果你想每次传递一组不同的参数时间?

1 个答案:

答案 0 :(得分:1)

而不是像 /path/:parameter_1/:parameter_2 这样注册路由,您应该实际注册 /path 然后使用 this.$router.push('/path?parameter_1=xxx&parameter_2=yyy')

这是我的代码摘录 - 当页面/排序/rowsPerPage 更改以及初始呈现时,data-table 组件将发出 pagination 事件。由于我们只更改了 URL 查询值(URL 中 ? 之后的文本) - Vue 将重用该组件,因此我们监听 beforeRouteUpdate 对 URL 中的新参数做出反应并获取适当的数据:

  data () 
  {
    return {
      filters:
      {
        parameter_1: this.$route.query.parameter_1 || '',
        parameter_2: this.$route.query.parameter_2 || '',
      }
    }
  },
  watch:
  {
    filters:
    {
      deep: true,
      handler: 'filtrationHasChanged'
    }
  },
  beforeRouteUpdate (to, from, next) 
  {
    this.fetchData(to);
    next();
  },
  methods:
  {
      buildQuery (route) 
      {
        const query = route ? route.query : this.$route.query;
        let params = '?';
        if (query.parameter_1) params += '&parameter_1=' + query.parameter_1;
        if (query.parameter_2) params += '&parameter_2=' + query.parameter_2;
        return params;
      },
      fetchData (route) 
      {
        this.$ajax.get('/api_endpoint' + this.buildQuery(route)).then(response =>
        {
          // use the API response
        });
      },

      filtrationHasChanged (filters) 
      {
        const obj = Object.assign({}, this.$route.query);

        if (filters.parameter_1) 
        { 
          obj.parameter_1 = filters.parameter_1; 
        }
        else 
        { 
          delete obj.parameter_1; 
        }

        if (filters.parameter_2) 
        { 
          obj.parameter_2 = filters.parameter_2; 
        }
        else 
        { 
          delete obj.parameter_2; 
        }

        // check if old and new query are the same - VueRouter will not change the route if they are, so probably this is the first page loading
        if (this.isSameObject(query, obj)) 
        { 
          this.fetchData(); // page has been manually reloaded in the browser
        } 
        else 
        {
          this.$router.replace({
            ...this.$router.currentRoute,
            query: obj
          });
        }
      },

      isSameObject (a, b) 
      {
        let same = true;
        for (const key in a) 
        {
          if (a[key] != b[key]) 
          {
            same = false;
            break;
          }
        }
        // to handle the case when a KEY exists in B but not in A
        for (const key in b) 
        {
          if (a[key] != b[key]) 
          {
            same = false;
            break;
          }
        }
        return same;
      }
  }
相关问题