Javascript 第二次单击后的Vue.js渲染

Javascript 第二次单击后的Vue.js渲染,javascript,vue.js,Javascript,Vue.js,我有一个表单,它使用下拉菜单允许用户选择他们的配置,当他们单击apply时,将呈现一个highchart。乍一看,这是完美的 我的问题是,如果在呈现图表后,您再次打开下拉列表进行更改,而不关闭下拉列表,然后单击apply,我们将获得具有先前配置的图表。我必须再次单击apply,以显示新配置 我错过了什么 以下是完整代码的一部分: <template> <div class="dropdown multiple-select"> <Gl

我有一个表单,它使用下拉菜单允许用户选择他们的配置,当他们单击
apply
时,将呈现一个highchart。乍一看,这是完美的

我的问题是,如果在呈现图表后,您再次打开下拉列表进行更改,而不关闭下拉列表,然后单击
apply
,我们将获得具有先前配置的图表。我必须再次单击
apply
,以显示新配置

我错过了什么

以下是完整代码的一部分:

<template>
  <div class="dropdown multiple-select">
    <GlobalEvents v-if="open" @click="handleClick" @keydown.esc="close" />
    <button
      ref="button"
      class="btn btn-block btn-multiple-select"
      type="button"
      :disabled="disabled"
      @click="toggle"
    >
      <span v-if="internalValue.length === 0"> {{ emptyLabel }} </span>
      <span v-else> {{ internalValue.length }} Selected </span>
      <b-icon :icon="open | icon" :scale="0.5" />
    </button>

    <div ref="dropdown" class="dropdown-menu" :class="{ show: open }">
      <template v-if="!loading">
        <div class="px-4 pt-1">
          <div class="form-group">
            <b-form-input
              v-model="search"
              debounce="500"
              placeholder="Search"
            />
          </div>
        </div>
        <div class="scroll px-4">
          <b-form-checkbox v-model="selectAll" class="py-1" @change="toggleAll">
            Select all
          </b-form-checkbox>
          <b-form-checkbox
            v-for="item in filtered"
            :key="item.id"
            v-model="internalValue"
            :value="item"
            class="py-1"
            @input="checkSelectAllStatus"
          >
            {{ item.name }}
          </b-form-checkbox>
          <p v-if="filtered.length === 0">No results.</p>
        </div>
      </template>
      <div v-else class="text-center my-2">
        <b-spinner />
      </div>
    </div>
  </div>
</template>

<script>
import { createPopper } from '@popperjs/core';
import GlobalEvents from 'vue-global-events';

export default {
  components: {
    GlobalEvents
  },
  filters: {
    icon(item) {
      return item ? 'caret-up-fill' : 'caret-down-fill';
    }
  },
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    emptyLabel: {
      type: String,
      default: () => 'None Selected'
    },
    disabled: {
      type: Boolean,
      default: () => false
    },
    loading: {
      type: Boolean,
      default: () => false
    },
    options: {
      type: Array,
      default: () => []
    },
    value: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      internalValue: this.value,
      open: false,
      popper: null,
      search: '',
      selectAll: false
    };
  },
  computed: {
    filtered() {
      return this.options.filter((item) =>
        item.name.toLowerCase().includes(this.search.toLowerCase())
      );
    },
    showAll() {
      return (
        this.internalValue.length > 0 &&
        this.internalValue.length === this.options.length
      );
    }
  },
  watch: {
    options() {
      this.checkSelectAllStatus();
    },
    internalValue() {
      this.checkSelectAllStatus();
    },
    value(value) {
      this.internalValue = value;
      this.$emit('change', this.internalValue);
    }
  },
  methods: {
    checkSelectAllStatus() {
      this.selectAll = this.internalValue.length === this.options.length;
    },
    close() {
      this.open = false;
      this.search = '';
      this.$emit('change', this.internalValue);
    },
    create() {
      this.popper = createPopper(this.$refs.button, this.$refs.dropdown, {
        placement: 'bottom-start',
        modifiers: [
          {
            name: 'offset',
            options: {
              offset: [0, 10]
            }
          }
        ]
      });
    },
    destroy() {
      if (this.popper) {
        this.popper.destroy();
        this.popper = null;
      }
    },
    handleClick(event) {
      if (!this.$el.contains(event.target)) {
        this.close();
      }
    },
    toggle() {
      this.open = !this.open;
      if (this.open) {
        this.$emit('open');
        this.create();
      } else {
        this.destroy();
      }
    },
    toggleAll(checked) {
      if (checked) {
        this.internalValue = this.options;
      } else {
        this.internalValue = [];
      }
    }
  }
};
</script>

{{emptyLabel}}
{{internalValue.length}}已选定
全选
{{item.name}

没有结果

从“@popperjs/core”导入{createPopper}; 从“vue全局事件”导入全局事件; 导出默认值{ 组成部分:{ 全球事件 }, 过滤器:{ 图标(项目){ 返回项目?'caret up fill':'caret down fill'; } }, 型号:{ 道具:“价值”, 事件:“更改” }, 道具:{ 空标签:{ 类型:字符串, 默认值:()=>“未选择” }, 残疾人士:{ 类型:布尔型, 默认值:()=>false }, 装载:{ 类型:布尔型, 默认值:()=>false }, 选项:{ 类型:数组, 默认值:()=>[] }, 价值:{ 类型:数组, 默认值:()=>[] } }, 数据(){ 返回{ 内在价值:这个价值, 开:错, 波普尔:空, 搜索:“”, selectAll:false }; }, 计算:{ 过滤的(){ 返回此.options.filter((项)=> item.name.toLowerCase().includes(this.search.toLowerCase()) ); }, showAll(){ 返回( this.internalValue.length>0&& this.internalValue.length==this.options.length ); } }, 观察:{ 选项(){ 选中此选项。选中SelectAllStatus(); }, 内部价值(){ 选中此选项。选中SelectAllStatus(); }, 价值(价值){ 这个值=值; 此.emit('change',此.internalValue); } }, 方法:{ 选中SelectAllStatus(){ this.selectAll=this.internalValue.length==this.options.length; }, 关闭(){ this.open=false; this.search=''; 此.emit('change',此.internalValue); }, 创建(){ this.popper=createPopper(this.$refs.button,this.$refs.dropdown{ 位置:'底部开始', 修改器:[ { 名称:“偏移量”, 选项:{ 偏移量:[0,10] } } ] }); }, 销毁{ 如果(这个波普尔){ 这个.popper.destroy(); this.popper=null; } }, handleClick(事件){ 如果(!this.$el.contains(event.target)){ 这个。关闭(); } }, 切换(){ this.open=!this.open; 如果(这个打开){ 这是。$emit('open'); 这个。create(); }否则{ 这个。销毁(); } }, toggleAll(选中){ 如果(选中){ this.internalValue=this.options; }否则{ this.internalValue=[]; } } } };
您似乎在使用vuelidate—您没有直接访问表单值,而是通过验证模型,这有什么好的理由吗

在不了解配置的情况下,您的代码应该更像这样:

async apply() {
    try {
      this.chartOptions.utilityMetric = this.form.metric;
      this.chartOptions.title = this.getTitle();
      this.loading = true;
      this.$v.$touch()
      if (this.$v.$error) throw new Error('form not valid')
      const response = await await this.$api.organizations.getAnnualWidget(
        this.organizationId,
        this.parentUtility,
        this.requestParams
      );
      this.chartOptions.categories = response.data.categories;
      this.chartOptions.series = response.data.series;
      this.chartOptions.yAxis = response.data.yAxis;
      this.$forceUpdate();
    } catch (error) {
      const message = getErrorMessage(error);
      this.$bvToast.toast(message, {
        title: 'Error',
        toaster: 'b-toaster-top-center',
        variant: 'danger'
      });
    } finally {
      this.loading = false;
    }
  }


同样,在不知道完整代码的情况下,很难判断,但我猜是指向vuelidate导致了这些问题

找到了一个与我们现有解决方案兼容的解决方案。我的
MultipleSelect
组件正在调用
@input=“checkSelectAllStatus”


我添加了
this.$emit('change',this.internalValue)
选中selectallstatus
方法,它就工作了。

谢谢你的回答,它没有解决我的问题。我已经用完整的代码更新了我的问题。再次感谢,希望这能有所帮助。
requestParams() {
    return {
      calendarization: this.form.calendarization,
      metrics: this.form.metric.map((metric) => metric.id),
      meterIds: this.form.meterIds,
      Years: this.form.fiscalYears.map((year) => year.value),
      waterType: this.form.waterType,
      includeBaseline: this.form.baseLine,
      showDataLabels: this.form.showDataLabels
    };
  },