【问题标题】:Open only one accordion panel vue.js / bootstrap vue只打开一个手风琴面板 vue.js / bootstrap vue
【发布时间】:2020-05-03 15:25:50
【问题描述】:

构建一个 bootstrap-vue 手风琴,一切都按预期工作,但是,我只是添加了全部展开/折叠所有按钮,这些按钮也可以按预期工作,但现在我的问题是当我直接单击任何手风琴面板时,它们全部打开。有没有办法让他们只打开点击的面板?

html:

   <div class="container container-accordion-one">
      <!--expand all / collapse all row -->
      <div class="row row-expand-collapse">
        <div class="offset-md-1 col-expand-collapse">
          <ul class="list-expand-collapse">
            <li><a href="#/" @click="showCollapse = true" class="font__card-body">Expand All</a></li>
            <li><a href="#/" @click="showCollapse = false" class="font__card-body">Collapse All</a></li>
          </ul>
        </div>
      </div>
      <!--end: expand all / collapse all row -->
      <div class="row">
        <div class="offset-md-1 accordion-style-one">
          <div role="tablist">
            <b-card no-body class="">
              <b-card-header href="#" v-b-toggle.accordion-1 header-tag="header" class="accordion-header" role="tab">
                <p class="font__accordion-header">Accordion 1</p>
                <i class="fal fa-plus accordionClosed" />
                <i class="fal fa-minus accordionOpen" />
              </b-card-header>
              <b-collapse id="accordion-1" v-model="showCollapse" role="tabpanel">
                <b-card-body>
                  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto distinctio enim fugit, inventore odio odit perferendis quas quo veritatis voluptate.</p>
                </b-card-body>
              </b-collapse>
            </b-card>

            <b-card no-body class="">
              <b-card-header href="#" v-b-toggle.accordion-2 header-tag="header" class="accordion-header" role="tab">
                <p class=" font__accordion-header">Accordion 2</p>
                <i class="fal fa-plus accordionClosed" />
                <i class="fal fa-minus accordionOpen" />
              </b-card-header>
              <b-collapse id="accordion-2" v-model="showCollapse" role="tabpanel">
                <b-card-body>
                  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto distinctio enim fugit, inventore odio odit perferendis quas quo veritatis voluptate.</p>
                </b-card-body>
              </b-collapse>
            </b-card>

            <b-card no-body class="">
              <b-card-header href="#" v-b-toggle.accordion-3 header-tag="header" class="accordion-header" role="tab">
                <p class=" font__accordion-header">Accordion 3</p>
                <i class="fal fa-plus accordionClosed" />
                <i class="fal fa-minus accordionOpen" />
              </b-card-header>
              <b-collapse id="accordion-3" v-model="showCollapse" role="tabpanel">
                <b-card-body>
                  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto distinctio enim fugit, inventore odio odit perferendis quas quo veritatis voluptate.</p>
                </b-card-body>
              </b-collapse>
            </b-card>
          </div>
        </div>
      </div>
    </div>

js:

export default {
  name: 'm',
  components: {
   LinksTo
  },
  data() {
    return {
      showCollapse: false
    };
  }
};

【问题讨论】:

  • 每次折叠都需要有自己的 v-model 变量(可以使用真/假值数组)。由于您将所有折叠都绑定到同一个 v-model,当一个打开时它们都会打开,因此需要单独的 v-model

标签: javascript html vue.js bootstrap-vue


【解决方案1】:

您必须为每个标签声明一个单独的 showCollapse 标志。在 shwo/collapse all 中打开/关闭所有这些。

【讨论】:

    【解决方案2】:

    编辑:

    使用 DRY 原则,您最好将手风琴内容分解为数据,并且只编写一次标记,然后循环遍历您的数据。然后,您可以跟踪每个手风琴的打开/关闭状态。

    在您的代码中,每个手风琴都以同一个变量为模型,因此它们只能全部打开或全部关闭。每个手风琴都需要有一个单独的状态。

    示例:(已简化,因此更易于阅读,但您可以使用 bootstrap 执行相同操作)

    new Vue({
      el: "#app",
      data: {
        allClosed: true,
        items: [{
            title: 'title 1',
            description: 'description one',
            open: false
          },
          {
            title: 'title 2',
            description: 'description two',
            open: false
          },
          {
            title: 'title 3',
            description: 'description three',
            open: false
          }
        ],
      },
      methods: {
        openCloseAll() {
          this.allClosed = !this.allClosed
          if (this.allClosed) this.items.map(x => x.open = false)
          else this.items.map(x => x.open = true)
        }
      }
    })
    .accordian {
      margin: 8px 0;
      cursor: pointer;
      background: pink;
      padding: 0.25em;
    }
    <div id="app">
      <div>
        <button @click="openCloseAll()">
          <template v-if="allClosed">Open</template>
          <template v-else>Close</template>
          All
         </button>
      </div>
      <div v-for="(item, i) in items" class="accordian" @click="item.open = !item.open">
        <span>{{ item.title }}</span>
        <br />
        <span v-if="item.open">{{ item.description }}</span>
      </div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>

    之前的建议:

    这是实现此类功能的一种方式:

    new Vue({
      el: "#app",
      data: {
        items: ['one', 'two', 'three', 'four', 'five'],
        openItems: [],
        openAll: true
      },
      methods: {
        toggle(i) {
          const index = this.openItems.findIndex(x => x === i)
          if (index !== -1) this.openItems.splice(index, 1)
          else this.openItems.push(i)
        },
        openCloseAll() {
          if (this.openAll) this.items.forEach((x, i) => this.openItems.push(i))
          else this.openItems = []
          this.openAll = !this.openAll
        }
      }
    })
    .accordian {
      margin: 8px 0;
      cursor: pointer;
      background: pink;
      padding: 0.25em;
    }
    <div id="app">
      <div>
        <button @click="openCloseAll()">
          <template v-if="openAll">Open</template>
          <template v-else>Close</template>
          All
         </button>
      </div>
      <div v-for="(item, i) in items" class="accordian" @click="toggle(i)">
        {{ item }}
        <span v-if="openItems.includes(i)">opened</span>
        <span v-else>closed</span>
      </div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>

    【讨论】:

    • 欣赏答案,但我需要为这个项目使用这个引导插件。伟大的工作虽然:)
    【解决方案3】:

    由于您希望每个折叠都能够单独打开或关闭,因此您需要为每个折叠设置一个 v-model 变量。下面我使用一个数组来存储折叠状态:

    <template>
      <div>
        <b-button @click="expandAll">Expand all</b-button>
        <b-button @click="collapseAll">Collapse all</b-button>
    
        <b-button block v-b-toggle.accordion-1 class="mt-2">Accordion 1</b-button>
        <b-collapse id="accordion-1" v-model="collapseStates[0]">
          <div>Lorem ipsum dolor sit amet.</div>
        </b-collapse>
    
        <b-button block v-b-toggle.accordion-2 class="mt-2">Accordion 2</b-button>
        <b-collapse id="accordion-2" v-model="collapseStates[1]">
          <div>Lorem ipsum dolor sit amet.</div>
        </b-collapse>
    
        <b-button block v-b-toggle.accordion-3 class="mt-2">Accordion 3</b-button>
        <b-collapse id="accordion-3" v-model="collapseStates[2]">
          <div>Lorem ipsum dolor sit amet.</div>
        </b-collapse>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          collapseStates: [false, false, false]
        }
      },
      methods: {
        expandAll() {
          this.collapseStates = this.collapseStates.map(x => true)
        },
        collapseAll() {
          this.collapseStates = this.collapseStates.map(x => false)
        }
      }
    }
    </script>
    

    请参阅:https://jsfiddle.net/p60zktLs/ 的工作小提琴

    【讨论】:

      猜你喜欢
      • 2020-06-08
      • 2014-10-11
      • 1970-01-01
      • 1970-01-01
      • 2021-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多