Vue реализует связь левого и правого меню (обновление)

внешний интерфейс GitHub контейнер Vue.js

title: Vue реализует связь левого и правого меню дата: 2018-08-11 16:31:34 теги:

  • Vue
  • Ссылка слева и справа топ: 100 авторское право: верно

Знай почти

личный блог

Github

Портал исходного кода:Rain120/vue-study

согласно сНаггетс Обзортребования, обновлен интерфейс данных и исправлены некоторые проблемы

Я уже видел этот эффект связи слева и справа в программном обеспечении для выноса, и мне он показался очень интересным, поэтому я попытался его использовать.VueДля этого связь выделена в отдельный компонент.Без лишних слов возьмем рендеринг.

Vue实现左右菜单联动效果图

Этот компонент разделен на две части: 1 — левое меню, 2 — правое меню.

динамическая структура данных

动态数据结构

menus: [
  {
    name: '菜单1',
    data: [
      {
        name: '1.1'
      },
      {
        name: '1.2'
      },
      {
        name: '1.3'
      },
      {
        name: '1.4'
      },
      {
        name: '1.5'
      },
      {
        name: '1.6'
      }
    ]
  }
]

Данные данных определяются пользователем, чтобы добавить некоторый контент и отобразить его.DOM

левое менюDOMструктура

<scroll
  class="left-menu"
  :data="menus"
  ref="leftMenu">
  <div class="left-menu-container">
    <ul>
      <li
        class="left-item"
        ref="leftItem"
        :class="{'current': currentIndex === index}"
        @click="selectLeft(index, $event)"
        v-for="(menu, index) in menus"
        :key="index">
        <p class="text">{{menu.name}}</p>
      </li>
    </ul>
  </div>
</scroll>

правое менюDOMструктура

<scroll
  class="right-menu"
  :data="menus" 
  ref="rightMenu"
  @scroll="scrollHeight"
  :listenScroll="true"
  :probeType="3">
  <div class="right-menu-container">
    <ul>
      <li class="right-item" ref="rightItem" v-for="(menu, i) in menus" :key="i">
        <div class="title">{{menu.name}}</div>
        <ul>
          <li v-for="(item, j) in menu.data" :key="j">
            <div class="data-wrapper">
              <div class="data">{{item.name}}</div>
            </div>
          </li>
        </ul>
      </li>
    </ul>
  </div>
</scroll>

вот что делатьdemo, поэтому данные просто сфабрикованы.

Конечно, поскольку это дочерний компонент, мы пропустим его через родительский компонент.props, поэтому определитеprops

props: {
    menus: {
      required: true,
      type: Array,
      default () {
        return []
      }
    }
  },

原理图

В этом бизнес-сценарии наш метод реализации заключается в вычислении положения левого меню в соответствии с высотой прокрутки правого меню.Конечно, левое меню также можно щелкнуть, чтобы определить, насколько велико расстояние прокрутки правого меню. быть, так как же мы можем получить расстояние прокрутки контейнера? использовал раньшеbetter-scroll, читая документацию, мы знаем, что в ней естьscrollсобытие, мы можем получить прокрутку, прослушивая это событиеpos

scroll事件

if (this.listenScroll) {
  let me = this
  this.scroll.on('scroll', (pos) => {
    me.$emit('scroll', pos)
  })
}

Итак, мы в правильном менюscrollслушать на компонентеscrollмероприятие

@scroll="scrollHeight"

method

scrollHeight (pos) {
  console.log(pos);
  this.scrollY = Math.abs(Math.round(pos.y))
},

Мы набраем мониторинг POS и посмотреть

监听scroll事件,得到pos

Мы видим, что консоль выводит текущую информацию о позиции прокрутки, потому что при разработке на мобильном терминале ось координат противоположна оси координат в нашей математике, поэтому значение оси Y отрицательно при скольжении вверх.

移动开发坐标轴

Так что мы собираемся получить каждый кусокliвысота, мы можем получить ихDOM

 _calculateHeight() {
  let lis = this.$refs.rightItem;
  let height = 0
  this.rightHeight.push(height)
  Array.prototype.slice.call(lis).forEach(li => {
    height += li.clientHeight
    this.rightHeight.push(height)
  })
console.log(this.rightHeight)
}

мы вcreatedэтоhookЗатем вызовите эту функцию, которая вычисляет высоту

 _calculateHeight() {
  let lis = this.$refs.rightItem;
  let height = 0
  this.rightHeight.push(height)
  Array.prototype.slice.call(lis).forEach(li => {
    height += li.clientHeight
    this.rightHeight.push(height)
  })
  console.log(this.rightHeight)
}

得到右边菜单高度

Когда пользователь прокручивает, нам нужно рассчитать текущее расстояние прокрутки в пределах этого интервала и получить егоindex

找到滚动位置对应的index
找到滚动位置对应的index

computed: {
  currentIndex () {
    const { scrollY, rightHeight } = this
    const index = rightHeight.findIndex((height, index) => {
      return scrollY >= rightHeight[index] && scrollY < rightHeight[index + 1]
    })
    return index > 0 ? index : 0
  }
}

Так что в настоящее время это должно быть левое менюindex = 1пункт менюactiveВыше приведена реализация скользящей привязки левого меню к правому меню. Пользователи также могут щелкнуть левое меню, чтобы реализовать привязку правого меню. В это время мы добавляем пункт менюclick事件

@click="selectLeft(index, $event)"

добавить сюда$eventЭто нужно для того, чтобы различать собственные события кликов иbetter-scrollотправленное событие

selectLeft (index, event) {
  if (!event._constructed) {
    return
  }
  let rightItem = this.$refs.rightItem
  let el = rightItem[index]
  this.$refs.rightMenu.scrollToElement(el, 300)
},

использовать

<cascad-menu :menus="menus"></cascad-menu>

На данный момент мы в основном выполнили эти требования.