如何使Bootstrap4折叠在Vue中工作?

时间:2019-11-08 12:48:28

标签: vue.js bootstrap-4

我正在使用Bootstrap 4.3.1和vue@2.6.10

我有这个菜单(正在使用折叠-而且我不想使用JQuery):

 <li class="nav-item">
     <a class="nav-link" href="#sidebar-products" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="sidebar-products">
         <i class="ni ni-single-copy-04 text-primary"></i>
         <span class="nav-link-text">Products</span>
     </a>
     <div class="collapse" id="sidebar-products">
         <ul class="nav nav-sm flex-column">
             <li class="nav-item">
                 <a href="#" class="nav-link">Item List 1</a>
             </li>
             <li class="nav-item">
                 <a href="#" class="nav-link">Item List 2</a>
             </li>
         </ul>
     </div>
 </li>

这只是一个包含2个子项的块。

我在使用JQuery时看到的是,当单击“产品”时,#sidebar-products会收到.show类和aria-expanded =“ true”。

具有多个块时-单击一个块以关闭(如果已折叠)其他块。

我如何使其通过vue崩溃?

更新1

我创建了一个完成该任务的点击事件:

<a class="nav-link" href="javascript:void(0)" @click="navItemCollapse('sidebar-products', $event)" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="sidebar-products">

和事件:

 navItemCollapse(id, event) {
     let expanded = event.target.getAttribute('aria-expanded').toLocaleLowerCase() == 'true' ? true : false;
     let el = document.getElementById(id);
     expanded ? el.classList.remove('show') : el.classList.add('show');
                event.target.setAttribute('aria-expanded', !expanded);
 }

但是,如果我有更多的积木怎么办?当单击以打开块上的当前折叠以关闭其他折叠时???

4 个答案:

答案 0 :(得分:1)

这是没有jquery的实现

a_1
new Vue({
  el: '#app',
  data() {
    return {
      menuList: [{
          name: 'Products',
          expand: false,
          items: [{
              name: 'Item List 1',
              link: ''
            },
            {
              name: 'Item List 2',
              link: ''
            }
          ]
        },
        {
          name: 'Others',
          expand: false,
          items: [{
              name: 'Other Item 1',
              link: ''
            },
            {
              name: 'Other Item 2',
              link: ''
            }
          ]
        }
      ]
    }
  },
  methods: {
    navItemCollapse(index) {
      this.menuList = this.menuList.map((item, i) => {
        item.expand = !item.expand
        if (i !== index) {
          item.expand = false
        }
        return item
      })
    }
  }
})

我将菜单数据集成到对象数组中。每个对象都有一个<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script> <ul id="app"> <li v-for="(navItem,i) in menuList" :key="i" class="nav-item"> <a class="nav-link" href="javascript:;" data-toggle="collapse" role="button" :aria-expanded="navItem.expand" aria-controls="sidebar-products" @click.prevent="navItemCollapse(i)"> <i class="ni ni-single-copy-04 text-primary"></i> <span class="nav-link-text">{{navItem.name}}</span> </a> <div v-if="navItem.items.length>0" class="collapse" :class="{show: navItem.expand}"> <ul class="nav nav-sm flex-column"> <li v-for="(subItem,j) in navItem.items" :key="j" class="nav-item"> <a href="#" class="nav-link">{{subItem.name}}</a> </li> </ul> </div> </li> </ul>标志来确定它当前是否被扩展。当您单击菜单时,请切换当前菜单的展开标志。

注意:您不需要关心expand标签的id

答案 1 :(得分:1)

这是一个使用 bootstrap-vue 的完整版本:

 <div class="accordion" role="tablist">
            <b-card v-for="(value, key) in this.jobs" :key="key" no-body class="mb-1">
              <b-card-header header-tag="header" class="p-1" role="tab">
                <b-button block v-b-toggle="'accordion-'+key" variant="primary">{{ value.title }}</b-button>
              </b-card-header>
              <b-collapse :id="'accordion-'+key.toString()" accordion="my-accordion" role="tabpanel">
                <b-card-body>
                  <b-card-text>{{ value.specs }}</b-card-text>
                </b-card-body>
              </b-collapse>
            </b-card>
          </div>

数据对象:

data() {
    return {
     jobs: [
        {
          title: 'Design artist',
          specs: 'Have an eye for web beauty'
        },
        {
          title: 'Backend guru',
          specs: 'Do stuff that don\'t break'
        },
        {
          title: 'Frontend master',
          specs: 'Create an UI that works'
        }
      ]
}
}

答案 2 :(得分:0)

没有jQuery或bootstrap-vue ...

在Component中创建一个函数来处理普通的Bootstrap类和计时逻辑...

  data() {
    return {
      classArr: ['collapse'],
      styleObj: {}
    };
  },
  methods: {
    toggleCollapse(ref) {
        let show = this.classArr.indexOf('show')>-1?false:'show'
        this.classArr = ['collapsing']
        setTimeout(() => {
            if (show){
                let height = this.$refs[ref].firstChild.clientHeight + 'px';
                this.styleObj = { height }
            }
            else {
                this.styleObj = {}  
            }
        }, 10)
        setTimeout(() => {
            this.classArr = ['collapse', show]
        }, 340)
    }
  }

在组件模板中,将classstyle属性绑定到该方法操作的数据。特定折叠的ref传递给方法...

  <li class="nav-item">
        <a class="nav-link" href="#sidebar-products" role="button" @click="toggleCollapse('sidebar')">
            <i class="ni ni-single-copy-04 text-primary"></i>
            <span class="nav-link-text">Products</span>
        </a>
        <div :class="classArr" :style="styleObj" id="sidebar-products" ref="sidebar">
            <ul class="nav nav-sm flex-column">
                <li class="nav-item">
                    <a href="#" class="nav-link">Item List 1</a>
                </li>
                <li class="nav-item">
                    <a href="#" class="nav-link">Item List 2</a>
                </li>
            </ul>
        </div>
  </li>

https://www.codeply.com/p/GA5CaNMzmc

编辑:我更新了演示,使其可伸缩以进行多次折叠

答案 3 :(得分:0)

我喜欢@sugars的方法:)

所以...最终版本是这样的:

<li v-for="(navItem, i) in sidenavItems" class="nav-item">
                            <router-link v-if="!navItem.isCollapsible" class="nav-link" @click.native="navItemCollapse(i)" active-class="active" :to="{name: navItem.route}" exact>
                                <i :class="navItem.class"></i>
                                <span class="nav-link-text">{{ navItem.name }}</span>
                            </router-link>

                            <a v-if="navItem.isCollapsible" class="nav-link" href="javascript:void(0)" @click="navItemCollapse(i)" data-toggle="collapse" :aria-expanded="navItem.expanded">
                                <i :class="navItem.class"></i>
                                <span class="nav-link-text">{{ navItem.name }}</span>
                            </a>
                            <div v-if="navItem.isCollapsible" class="collapse" :class="navItem.expanded ? 'show' : ''">
                                <ul class="nav nav-sm flex-column">
                                    <li v-for="subItem in navItem.items" class="nav-item">
                                        <router-link class="nav-link" :to="{name: subItem.route}">{{ subItem.name }}</router-link>
                                    </li>
                                </ul>
                            </div>
                        </li>

sidenavItems:

 sidenavItems: [
                    {name: 'Dashboard', isCollapsible: false, route: 'dashboard', class: 'class1'},
                    {name: 'Categories', isCollapsible: false, route: 'category', class: 'class2'},
                    {name: 'Brands', isCollapsible: false, route: 'brand', class: 'class3'},
                    {name: 'Products', isCollapsible: true, expanded: false, class: 'class4', items: [{name: 'List', route: 'product'}]},
                    {name: 'Orders', isCollapsible: false, route: 'order', class: 'class5'},
                    {name: 'Blog', isCollapsible: true, expanded: false, class: 'class6', items: [{name: 'List', route: ''}]},
                ],

和navItemCollapse方法:

 navItemCollapse(index) {
     this.sidenavItems = this.sidenavItems.map( (item, i) => {
                item.expanded = !item.expanded;
                if(i !== index) {
                    item.expanded = false;
                }
                return item;
            })
        }