Bootstrap Vue 阻止/取消事件

Posted

技术标签:

【中文标题】Bootstrap Vue 阻止/取消事件【英文标题】:Bootstrap Vue prevent / cancel event 【发布时间】:2019-05-30 03:41:00 【问题描述】:

我有一个带有来自 Bootstrap Vue 的 b-form-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>

当我在选择中选择“禁止”时。我看到选择框已更改为该值,但子项中的属性以及父项中的属性仍然具有旧值,这就是我想要的。我怎样才能选择拥有旧值?

Bootstrap Vue 似乎没有更改事件的 prevent 修饰符。 我也尝试过使用本机事件,但也有同样的问题。

我是不是做错了什么?

【问题讨论】:

不知道&lt;b-form-select&gt;是什么组件,但是常规选择使用v-model绑定选择的值。 @thefallen 因为我从父母那里获得了属性,所以我不允许使用 v-model,因为您不应该在 Vue 中设置子级的属性 【参考方案1】:

与神秘地让它们不选择所选值相比,禁用禁用选项可能会更好的用户体验,但您可以通过保存旧值并将其恢复到 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>

【讨论】:

感谢您的回复。禁用词只是我想将其设置为旧值的一个例子。在我的应用程序中,我会提示一个对话框,让用户确认他们想要进行一些更改。我会尝试你的建议在下一个滴答声中重置它。我只是想知道为什么选择没有取消或阻止选项 更改是原子的——这也适用于其他类型的输入小部件。它们没有“更新前”生命周期类型的方法。您可以确认用户意图,但没有确认用户交互。用户输入发生并且您对其做出响应。这就是它的设计方式。【参考方案2】:

我想提出一个基于 $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 来防止用户更改被传递到数据模型/存储。在验证之前,我们将b-form-selectlocalValue 设置为用户交互之前的值。如果验证是肯定的,我们更新数据模型中的值,这使得 Vue 刷新b-form-select。如果没有,我们什么也不做。

此操作可能会触发Vue warning 直接操作 DOM(取决于您在此处所做的具体操作),但是我认为这是一个合理的使用,因为我们不会尝试显示覆盖我们的数据模型的数据 - 在相反 - 我们正在阻止浏览器显示尚未存储在模型中的数据。

您还可以使用 vanilla &lt;select&gt; 标签(不是 BootstrapVue - 它的工作方式略有不同)和 v-bind/v-on 而不是 getter/setter 方法检查 here 我对同一问题的解决方案。

【讨论】:

以上是关于Bootstrap Vue 阻止/取消事件的主要内容,如果未能解决你的问题,请参考以下文章

vue.js阻止事件冒泡和默认事件

右键、阻止冒泡

如果满足某些条件,bootstrap-vue 复选框会阻止更改

##阻止事件冒泡和取消默认操作

vue阻止事件冒泡,事件穿透

JS阻止冒泡和取消默认事件(默认行为)