首页 > 解决方案 > 第二次 onClick 后的 Vue.js 渲染

问题描述

我有一个表单,它使用下拉菜单允许用户选择他们的配置,并在他们单击时apply呈现高图。乍一看,这非常有效。

我的问题是,如果在呈现图表后,您再次打开一个下拉列表以进行更改而不关闭下拉列表并单击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>

标签: javascriptvue.js

解决方案


找到了一个适用于我们已有的解决方案。我的MultipleSelect组件正在调用@input="checkSelectAllStatus"

我添加this.$emit('change', this.internalValue);到该checkSelectAllStatus方法中并且它起作用了。


推荐阅读