VueJS 中的模型 URL 参数

Posted

技术标签:

【中文标题】VueJS 中的模型 URL 参数【英文标题】:Model URL parameter in VueJS 【发布时间】:2021-11-02 11:07:22 【问题描述】:

从https://***.com/a/62859896/4534 开始,我只想操作一个范围输入元素并使用该值更新 URL。

// https://github.com/vuejs/vue-router/blob/dev/examples/route-props/Hello.vue
var Hello = Vue.component('Hello', 
  template: `
  <div>
  <h2 class="hello">Hello agility  $attrs </h2>
  <input min=0 max=100 v-model="agility" type="range">
  </div>
  `,
  props: 
    agility: 
      type: Number,
      default: 25
    
  
);

const router = new VueRouter(
  // mode: 'history',
  routes: [
     path: '*', component: Hello, props: true ,
     path: '/:agility', component: Hello, props: true ,
  ]
)

new Vue(
  router,
  template: `
    <div id="app">
      <router-view></router-view>
    </div>
  `
).$mount('#app')
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app"></div>

如果没有提供值,我希望将默认值 25 附加到 URL,例如https://dabase.com/tips/web/2021/Minimal-VueJS-route-bind/#25

如果有没有 vue-router 的更简单的方法来做到这一点,我会全力以赴!

【问题讨论】:

【参考方案1】:

我在没有 vue-router 的情况下解决了! ?

在这里,我们使用从 URL 哈希部分获得的数据设置数据:

  created: function() 
    var hash = window.location.hash.substr(1)
    if (hash) 
        this.agility = hash
        
  ,

当数据发生变化时,更新 URL 哈希部分

   watch: 
    agility: function (newValue) 
      window.location.hash = newValue
    
  ,

【讨论】:

据我所知,手表非常昂贵。有没有更好的办法? @KickButtowski 你有没有证据表明手表在性能方面的成本很高?我认为在设计而非性能方面,最好使用计算属性而不是观察者。 @hendry 如果用户在 URL 中手动更改哈希会怎样?出于这个原因,我也会以某种方式收听hashchange事件。 看看我的回答,这是做同样事情的更有效和更干净的方式。 ***.com/a/69144716/9640177【参考方案2】:

虽然解决方案有效,但存在两个问题:

Hello 组件改变了它自己的agility 属性。这不应该发生(Vue 在控制台中生成警告),而是应该发出一个事件,以便在上游更改属性。这样一来,值始终只存储在一个位置,修改该位置的值会在其他任何地方修改它。 如果 url 的 hash 发生变化,由于用户手动输入新的 url 或单击链接,输入中的值将不会更新

为了解决第一个问题,我们不会在agility 属性上使用v-model,因为我们不想改变它。我们需要直接监听输入的事件:

<input min=0 max=100 :value="agility" type="range" @input="updateAgility">

   ...,
   methods: 
     updateAgility(event /*: InputEvent */) 
       this.$router.push(...this.$route, hash: "#" + event.target.value);
     
   

这将在输入更改值时直接更改 url。第二个问题是如何在 url 发生变化时更新 prop agility

created 中执行此操作是不够的,因为如果页面保持不变但哈希发生变化,则不会重新创建组件。

所以我们回到原来的解决方案,直接从路由器设置prop:

 
  path: "*", 
  component: Hello, 
  props: route => route.hash.length > 1 ? 
      agility: Number(route.hash.slice(1)) :
     

现在,无论您是从 URL 还是输入更新值,URL 和输入值始终保持同步。并且关于变异道具的警告消失了。

// https://github.com/vuejs/vue-router/blob/dev/examples/route-props/Hello.vue
var Hello = Vue.component('Hello', 
  template: `
  <div>
  <h2 class="hello">Hello agility, Current route's hash:  $route.hash</h2>
  <input min=0 max=100 :value="agility" @input=updateAgility type="range">
  <br>
  <router-link to="#1">Hash 1 link</router-link>   <router-link to="#15">Hash 15 link</router-link>
  </div>
  `,
  props: 
    agility: 
      type: Number,
      default: 25
    
  ,
  methods: 
    updateAgility(event/*: InputEvent */) 
      this.$router.push(...this.$route, hash: "#" + event.target.value);
    
  

);

const router = new VueRouter(
  // mode: 'history',
  routes: [
     path: '*', component: Hello, props: route => route.hash.length > 1 ?  agility: Number(route.hash.slice(1)) : ,
  ]
)

new Vue(
  router,
  template: `
    <div id="app">
      <router-view></router-view>
    </div>
  `
).$mount('#app')
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app"></div>

仅供参考:也可以通过在'$route.hash' 上创建观察者来监听组件本身的 url 变化,但这不是推荐的方式。

【讨论】:

【参考方案3】:

您可以在不使用路由器的情况下非常优雅高效地完成它。使用 change 或 input 事件更新哈希。

new Vue(
  el: "#app",
  data: 
    agility: 25,
    hash: 0
  ,
  methods: 
    addHash() 
      window.location.hash = this.agility;
      this.hash = this.agility;
    
  ,
  created: () => 
    const hash = window.location.hash.substr(1)
    if (hash) 
      this.agility = hash
    
  
)
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>

<div id="app">
  <h2 class="hello">Hello agility</h2>
  <input min=0 max=100 v-model="agility" @change="addHash" type="range">
  <h4>testing hash = hash</h4>
</div>

当用户停止滚动或离开输入范围拇指时触发更改事件。如果您想在拇指移动时看到变化,请使用输入事件。

【讨论】:

【参考方案4】:

为此创建一个可写的计算属性。我认为这有点好,因为当您需要更新路线时,您只需分配 this.agility = newAgility 和瞧,一切正常。要设置默认值 25,可以使用 created 挂钩。

但请记住,如此改变您的路线可能会导致性能问题。考虑限制计算属性上的set 函数(您可以使用lodash.throttle 或实现您自己的)或将路由参数替换为哈希参数。

// https://github.com/vuejs/vue-router/blob/dev/examples/route-props/Hello.vue
var Hello = Vue.component('Hello', 
  template: `
  <div>
  <h2 class="hello">Hello agility</h2>
  <input min=0 max=100 v-model="agility" type="range">
  </div>
  `,
  created() 
    if (typeof this.agility === 'undefined') 
      this.agility = 25;
    
  ,
  computed: 
    agility: 
      get() 
        return this.$route.params.agility;
        // Or with hash parameter
        // return this.$route.hash;
      ,
      set(agility) 
        this.$router.replace(`/$agility`);
        // Or with hash parameter
        // this.$router.replace( hash: String(agility) );
      ,
    ,
  ,
);

const router = new VueRouter(
  // mode: 'history',
  routes: [
     path: '*', component: Hello ,
     path: '/:agility', component: Hello ,
  ]
)

new Vue(
  router,
  template: `
    <div id="app">
      <router-view></router-view>
    </div>
  `
).$mount('#app')
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app"></div>

【讨论】:

以上是关于VueJS 中的模型 URL 参数的主要内容,如果未能解决你的问题,请参考以下文章

MVC - 将整个模型作为参数传递给 JavaScript 中的 Url.Action

Django:URL模板标签中的模型参数

vuejs 计算数据检测模型是不是已更新

Django - 将模型名称从 url 传递给视图

VueJS:如何在多页面应用程序中使用路由来发送 url 查询参数?

Vuejs 指令绑定模型