vue + better-scrollРеализовать навигацию по алфавитному указателю в списке мобильных исполнителей. Это можно рассматривать как учебную заметку.Напишите заметку, чтобы понять немного глубже.
Демо:list-view, просмотрите его в мобильном режиме Chrome. После перехода в режим мобильного телефона, если вы не можете провести пальцем, обновите его, и все будет в порядке.
Гитхаб:Мобильная навигация по алфавитному указателю(дерзкая просьба о звезде, хе-хе)
визуализация
Среда конфигурации
Поскольку используются Vue-Cli и лучше-прокрутки, сначала установите Vue-CLI, а затем устанавливать NPMbetter-scroll.
Краткое введение в лучшую прокрутку:
Better-scroll — это подключаемый модуль, ориентированный на удовлетворение потребностей различных сценариев прокрутки на мобильном терминале (ПК уже поддерживается). Его ядром является реализация iscroll для справки.Его дизайн API в основном совместим с iscroll, а некоторые функции и оптимизации производительности были расширены на основе iscroll.
better-scroll реализован на основе нативного JS и не зависит ни от какого фреймворка. Размер скомпилированного кода составляет 63 КБ, сжатый — 35 КБ, а gzip — всего 9 КБ, это очень легкая JS-библиотека.
В дополнение к этим двум также используются scss и vue-lazyload. Препроцессор scss, который всем известен, такой же, как и у других. lazyload реализует ленивую загрузку, вы можете обойтись без нее, в основном для оптимизации работы.
Данные напрямую используют список исполнителей NetEase Cloud,Если вам лень, поместите это прямо в данные.
Я не буду публиковать стили CSS, просто посмотрите исходный код.
Реализовать базовые стили
Прямое использование v-for и двухстороннего вложения для реализации списка исполнителей, а также индексной полосы справа.
HTML-структура:
<ul>
<li v-for="group in singers"
class="list-group"
:key="group.id"
ref="listGroup">
<h2 class="list-group-title">{{ group.title }}</h2>
<ul>
<li v-for="item in group.items"
class="list-group-item" :key="item.id">
<img v-lazy="item.avatar" class="avatar">
<span class="name">{{ item.name }}</span>
</li>
</ul>
</li>
</ul>
<div class="list-shortcut">
<ul>
<li v-for="(item, index) in shortcutList"
class="item"
:data-index="index"
:key="item.id"
>
{{ item }}
</li>
</ul>
</div>
Список ярлыков получается путем вычисления свойства, достаточно взять первый символ заголовка.
shortcutList () {
return this.singers.map((group) => {
return group.title.substr(0, 1)
})
}
Используйте лучшую прокрутку
Используйте лучшую прокрутку для прокрутки. Кстати, не забывайте использовать импорт при его использовании.
created () {
// 初始化 better-scroll 必须要等 dom 加载完毕
setTimeout(() => {
this._initSrcoll()
}, 20)
},
methods: {
_initSrcoll () {
console.log('didi')
this.scroll = new BScroll(this.$refs.listView, {
// 获取 scroll 事件,用来监听。
probeType: 3
})
}
}
Используйте созданный метод для лучшей инициализации прокрутки и используйте setTimeout, потому что вам нужно дождаться загрузки DOM. В противном случае better-scroll не сможет инициализироваться, если не сможет получить дом.
Здесь метод написан двумя методами, чтобы он не выглядел беспорядочно, и его можно было вызвать напрямую.
При инициализации передайте два probeType: 3, чтобы объяснить: когда probeType равен 3, не только в процессе скольжения экрана, но и в процессе анимации прокрутки по импульсу, работающей в реальном времени для отправки событий прокрутки. Если это значение не установлено, его значение по умолчанию равно 0, то есть событие прокрутки не отправляется.
Добавьте события щелчка и переместите события в индекс, чтобы перейти
Во-первых, вам нужно привязать событие touchstart к индексу (срабатывает при нажатии пальцем на экран), просто используйте v-on напрямую. Затем вам нужно добавить индекс данных в индекс, чтобы вы могли получить значение индекса, используйте:data-index="index"
.
<div class="list-shortcut">
<ul>
<li v-for="(item, index) in shortcutList"
class="item"
:data-index="index"
:key="item.id"
@touchstart="onShortcutStart"
@touchmove.stop.prevent="onShortcutMove"
>
{{ item }}
</li>
</ul>
</div>
Привяжите метод onShortcutStart. Реализуйте функцию скачка индекса щелчка. Привяжите другой метод onShortcutMove для реализации скользящего прыжка.
created () {
// 添加一个 touch 用于记录移动的属性
this.touch = {}
// 初始化 better-scroll 必须要等 dom 加载完毕
setTimeout(() => {
this._initSrcoll()
}, 20)
},
methods: {
_initSrcoll () {
this.scroll = new BScroll(this.$refs.listView, {
probeType: 3,
click: true
})
},
onShortcutStart (e) {
// 获取到绑定的 index
let index = e.target.getAttribute('data-index')
// 使用 better-scroll 的 scrollToElement 方法实现跳转
this.scroll.scrollToElement(this.$refs.listGroup[index])
// 记录一下点击时候的 Y坐标 和 index
let firstTouch = e.touches[0].pageY
this.touch.y1 = firstTouch
this.touch.anchorIndex = index
},
onShortcutMove (e) {
// 再记录一下移动时候的 Y坐标,然后计算出移动了几个索引
let touchMove = e.touches[0].pageY
this.touch.y2 = touchMove
// 这里的 16.7 是索引元素的高度
let delta = Math.floor((this.touch.y2 - this.touch.y1) / 18)
// 计算最后的位置
// * 1 是因为 this.touch.anchorIndex 是字符串,用 * 1 偷懒的转化一下
let index = this.touch.anchorIndex * 1 + delta
this.scroll.scrollToElement(this.$refs.listGroup[index])
}
}
Таким образом, функция индекса может быть реализована.
Конечно, это нас не удовлетворит, ведь надо добавить крутых спецэффектов. Например, подсветка индекса или что-то в этом роде~~
Подсветка индекса мобильного контента
эммм, это немного сложно в это время. Но вы можете понять это с терпением.
Нам нужен метод on of better-scroll, который возвращает значение смещения по оси Y при прокрутке содержимого. Поэтому вам нужно добавить некоторый код при инициализации better-scroll. Кстати, не забудьте добавить scrollY в данные и currentIndex (используется для записи позиции выделенного индекса), потому что нам нужно слушать, поэтому добавьте его в данные.
_initSrcoll () {
this.scroll = new BScroll(this.$refs.listView, {
probeType: 3,
click: true
})
// 监听Y轴偏移的值
this.scroll.on('scroll', (pos) => {
this.scrollY = pos.y
})
}
Затем вам нужно вычислить высоту содержимого и добавить метод calculateHeight() для вычисления высоты проиндексированного содержимого.
_calculateHeight () {
this.listHeight = []
const list = this.$refs.listGroup
let height = 0
this.listHeight.push(height)
for (let i = 0; i < list.length; i++) {
let item = list[i]
height += item.clientHeight
this.listHeight.push(height)
}
}
// [0, 760, 1380, 1720, 2340, 2680, 2880, 3220, 3420, 3620, 3960, 4090, 4920, 5190, 5320, 5590, 5790, 5990, 6470, 7090, 7500, 7910, 8110, 8870]
// 得到这样的值
Затем прослушайте scrollY в часах и посмотрите код:
watch: {
scrollY (newVal) {
// 向下滑动的时候 newVal 是一个负数,所以当 newVal > 0 时,currentIndex 直接为 0
if (newVal > 0) {
this.currentIndex = 0
return
}
// 计算 currentIndex 的值
for (let i = 0; i < this.listHeight.length - 1; i++) {
let height1 = this.listHeight[i]
let height2 = this.listHeight[i + 1]
if (-newVal >= height1 && -newVal < height2) {
this.currentIndex = i
return
}
}
// 当超 -newVal > 最后一个高度的时候
// 因为 this.listHeight 有头尾,所以需要 - 2
this.currentIndex = this.listHeight.length - 2
}
}
После получения currentIndex используйте его в html.
给索引绑定 class --> :class="{'current': currentIndex === index}"
Наконец, измените currentIndex при обработке скользящего индекса.
Поскольку код можно использовать повторно, а пограничные случаи необходимо обрабатывать,
this.scroll.scrollToElement(this.$refs.listGroup[index])
Перепишите функцию, чтобы уменьшить объем кода.
// 在 scrollToElement 的时候,改变 scrollY,因为有 watch 所以就会计算出 currentIndex
scrollToElement (index) {
// 处理边界情况
// 因为 index 通过滑动距离计算出来的
// 所以向上滑超过索引框框的时候就会 < 0,向上就会超过最大值
if (index < 0) {
return
} else if (index > this.listHeight.length - 2) {
index = this.listHeight.length - 2
}
// listHeight 是正的, 所以加个 -
this.scrollY = -this.listHeight[index]
this.scroll.scrollToElement(this.$refs.listGroup[index])
}
lazyload
Между прочим, плагин lazyload также повышает удобство работы пользователей.
инструкции
- сначала установить npm
- импортировать в main.js, затем в Vue.use
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
loading: require('./common/image/default.jpg')
})
Добавьте загрузочное изображение и используйте требование веб-пакета для получения изображения.
- Затем, когда вам нужно его использовать, поместите
:src=""
заменитьv-lazy=""
Реализована функция ленивой загрузки картинок.
Суммировать
Навигация по алфавитному указателю на мобильном терминале реализована так, и это все еще кажется мне очень сложным (для меня).
Главное использовать on of better-scroll для получения значения смещения движения (для достижения выделения), и scrollToElement для перехода в соответствующую позицию (для достижения прыжка). И используйте событие касания, чтобы прослушивать касания, чтобы получить начальную позицию и расстояние скольжения (рассчитать конечную позицию).
награда
- Узнал о сенсорных событиях
- Немного более опытен в использовании Better-Scroll
- Vue тоже умеет, эммм
- У меня будет опыт, чтобы написать что-то подобное в будущем.
Эта статья была первоначально опубликована вBlog of Jin, добро пожаловать вGitHubПодписывайтесь на меня, чтобы начать и вместе изучать интерфейс.