Bootstrap Vue 阻止/取消事件
Bootstrap Vue prevent / cancel event
我有一个带有来自 Bootstrap Vue 的 b-form-select 控件的页面。
当我改变这个控件的值时,我想执行一个可以取消这个事件的函数,而不是改变值。
为了让事情变得更复杂,我的 select 在子组件中,而我执行的函数在父组件中。
子组件
public values: any[] = [
{ name: 'default'},
{ name: 'forbidden'},
{ name: 'other option' },
]
<b-form-select :value="property" @change="$emit('onPropertyChange', arguments[0])">
<option v-for="(val, key) in values" :value="val" :key="key">{{val.Name}}</option>
</b-form-select>
父组件:
this.property = { name: 'default' }
public onPropertyChange(newValue) {
if (newValue.name === 'forbidden') {
// Not changing this.property
} else {
// Changing it
this.property = newValue
}
}
<child :property="property" @onPropertyChange="onPropertyChange"></child>
当我select'forbidden'在select。我看到 select 框已更改为此值,但子项中的 属性 和父项中的 属性 仍然具有旧值,这正是我想要的。我怎样才能让 select 具有旧值?
Bootstrap Vue 似乎没有对 change 事件的 prevent 修饰符。
我也尝试过使用本机事件,但有同样的问题。
我是不是做错了什么?
禁用禁止选项可能比神秘地让它们不是 select selected 值更好的用户体验,但您可以通过保存在更改事件处理程序中获得该行为旧值并在 nextTick
.
上恢复它
请注意,您的 options
结构不适合与 b-form-select
一起使用。我做了一个计算,使结构正确并处理设置 disabled
,并在 b-form-select
.
中使用它
new Vue({
el: '#app',
data: {
selected: 'default',
options: [{
name: 'default',
},
{
name: 'forbidden'
},
{
name: 'other option'
},
{
name: 'what I had before'
},
]
},
computed: {
selectOptions() {
return this.options.map((opt) => ({
text: opt.name,
value: opt.name,
disabled: opt.name === 'forbidden'
}));
}
},
methods: {
onChange(newValue) {
const oldValue = this.selected;
if (newValue === 'what I had before') {
this.$nextTick(() => {
this.selected = oldValue;
});
}
}
}
});
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>
<div id="app">
<b-form-select v-model="selected" :options="selectOptions" @change="onChange">
</b-form-select>
<div>Selected: <strong>{{selected}}</strong></div>
</div>
我想提出一个基于 $refs 和计算 getter/setter 的解决方案(但它也可以通过 v-bind/v-on 实现)。这种功能有有效的用例,例如要求用户确认。
<template>
<div>
<b-form-select
ref="mySelect"
v-model="choiceHandler"
:options="selectOptions"
>
</b-form-select>
</div>
</template>
<script>
export default {
data() {
return {
selectOptions: [
{ value: 1, text: "Choice 1" },
{ value: 2, text: "Choice 2" },
{ value: 3, text: "Choice 3" },
],
storedChoice: 3,
};
},
computed: {
choiceHandler: {
get() {
return this.storedChoice;
},
set(newValue) {
this.$refs.typeSelect.localValue = this.storedChoice; // this reverts displayed value to the one resulting from stored value
let confirmDialog = new Promise((resolve) => {
// this promise is a mockup for an asycnc dialog returning true / false
setTimeout(() => {
resolve(true);
}, 1500);
});
confirmDialog.then((res) => {
if (res) {
this.storedChoice = newValue;
} else console.log("No changes");
});
},
},
},
};
</script>
我们需要使用 setter
来防止用户更改传递给数据 model/store。在验证之前,我们将 b-form-select
的 localValue
设置为用户交互之前的值。如果验证是肯定的,我们更新数据模型中的值,使 Vue 刷新 b-form-select
。如果没有,我们什么都不做。
此操作可能会触发 Vue warning
关于直接操作 DOM(取决于你在这里做什么),但我认为这是合理的使用,因为我们不试图显示数据覆盖我们的数据模型 - 相反 - 我们阻止浏览器显示尚未存储在模型中的数据。
您还可以使用普通 <select>
标签(不是 BootstrapVue - 它的工作方式略有不同)和 v-bind
/v-on
来检查 我对同一问题的解决方案getter/setter 方法。
我有一个带有来自 Bootstrap Vue 的 b-form-select 控件的页面。 当我改变这个控件的值时,我想执行一个可以取消这个事件的函数,而不是改变值。
为了让事情变得更复杂,我的 select 在子组件中,而我执行的函数在父组件中。
子组件
public values: any[] = [
{ name: 'default'},
{ name: 'forbidden'},
{ name: 'other option' },
]
<b-form-select :value="property" @change="$emit('onPropertyChange', arguments[0])">
<option v-for="(val, key) in values" :value="val" :key="key">{{val.Name}}</option>
</b-form-select>
父组件:
this.property = { name: 'default' }
public onPropertyChange(newValue) {
if (newValue.name === 'forbidden') {
// Not changing this.property
} else {
// Changing it
this.property = newValue
}
}
<child :property="property" @onPropertyChange="onPropertyChange"></child>
当我select'forbidden'在select。我看到 select 框已更改为此值,但子项中的 属性 和父项中的 属性 仍然具有旧值,这正是我想要的。我怎样才能让 select 具有旧值?
Bootstrap Vue 似乎没有对 change 事件的 prevent 修饰符。 我也尝试过使用本机事件,但有同样的问题。
我是不是做错了什么?
禁用禁止选项可能比神秘地让它们不是 select selected 值更好的用户体验,但您可以通过保存在更改事件处理程序中获得该行为旧值并在 nextTick
.
请注意,您的 options
结构不适合与 b-form-select
一起使用。我做了一个计算,使结构正确并处理设置 disabled
,并在 b-form-select
.
new Vue({
el: '#app',
data: {
selected: 'default',
options: [{
name: 'default',
},
{
name: 'forbidden'
},
{
name: 'other option'
},
{
name: 'what I had before'
},
]
},
computed: {
selectOptions() {
return this.options.map((opt) => ({
text: opt.name,
value: opt.name,
disabled: opt.name === 'forbidden'
}));
}
},
methods: {
onChange(newValue) {
const oldValue = this.selected;
if (newValue === 'what I had before') {
this.$nextTick(() => {
this.selected = oldValue;
});
}
}
}
});
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>
<div id="app">
<b-form-select v-model="selected" :options="selectOptions" @change="onChange">
</b-form-select>
<div>Selected: <strong>{{selected}}</strong></div>
</div>
我想提出一个基于 $refs 和计算 getter/setter 的解决方案(但它也可以通过 v-bind/v-on 实现)。这种功能有有效的用例,例如要求用户确认。
<template>
<div>
<b-form-select
ref="mySelect"
v-model="choiceHandler"
:options="selectOptions"
>
</b-form-select>
</div>
</template>
<script>
export default {
data() {
return {
selectOptions: [
{ value: 1, text: "Choice 1" },
{ value: 2, text: "Choice 2" },
{ value: 3, text: "Choice 3" },
],
storedChoice: 3,
};
},
computed: {
choiceHandler: {
get() {
return this.storedChoice;
},
set(newValue) {
this.$refs.typeSelect.localValue = this.storedChoice; // this reverts displayed value to the one resulting from stored value
let confirmDialog = new Promise((resolve) => {
// this promise is a mockup for an asycnc dialog returning true / false
setTimeout(() => {
resolve(true);
}, 1500);
});
confirmDialog.then((res) => {
if (res) {
this.storedChoice = newValue;
} else console.log("No changes");
});
},
},
},
};
</script>
我们需要使用 setter
来防止用户更改传递给数据 model/store。在验证之前,我们将 b-form-select
的 localValue
设置为用户交互之前的值。如果验证是肯定的,我们更新数据模型中的值,使 Vue 刷新 b-form-select
。如果没有,我们什么都不做。
此操作可能会触发 Vue warning
关于直接操作 DOM(取决于你在这里做什么),但我认为这是合理的使用,因为我们不试图显示数据覆盖我们的数据模型 - 相反 - 我们阻止浏览器显示尚未存储在模型中的数据。
您还可以使用普通 <select>
标签(不是 BootstrapVue - 它的工作方式略有不同)和 v-bind
/v-on
来检查