Как сделать так, чтобы bootstrap4 развалилась в VUE? - PullRequest
0 голосов
/ 08 ноября 2019

Я использую 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-extended = "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);
 }

Но чтоесли у меня будет больше блоков? Когда щелкните, чтобы открыть текущий коллапс на блоке, чтобы закрыть остальные ???

Ответы [ 3 ]

1 голос
/ 08 ноября 2019

Это реализация без jquery

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 тега <a>.

0 голосов
/ 09 ноября 2019

Мне нравится подход @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;
            })
        }

0 голосов
/ 08 ноября 2019

Нет jQuery или bootstrap-vue ...

Создайте функцию в Компоненте для обработки обычного класса 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)
    }
  }

В шаблоне компонента свяжите атрибуты class и style с данными, которыми манипулирует метод. Ссылка на конкретный коллапс передается методу ...

  <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

РЕДАКТИРОВАТЬ: я обновил демо, чтобы сделать его масштабируемым для нескольких коллапсов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...