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