ホームページ  >  記事  >  ウェブフロントエンド  >  モバイル端末でアルファベット順のインデックスナビゲーションを作成する方法

モバイル端末でアルファベット順のインデックスナビゲーションを作成する方法

php中世界最好的语言
php中世界最好的语言オリジナル
2018-05-12 10:37:253008ブラウズ

今回は、モバイル端末でアルファベット順のインデックスナビゲーションを作成する方法を説明します。モバイル端末でアルファベット順のインデックスナビゲーションを作成するための注意事項を実際に見てみましょう。

vue+ better-scroll は、モバイル歌手リストのアルファベット順インデックス ナビゲーションを実装します。自分自身をより深く理解するための勉強ノートとして考えることができます。

デモ: リストビュー。表示するには Chrome モバイル モードを使用します。携帯モードに切り替えた後、スライドできない場合は更新すればOKです。

Github: モバイルアルファベットインデックスナビゲーション

レンダリング

設定環境

vue-cliとbetter-scrollを使用するため、最初にvue-cliをインストールしてからnpmでインストールする必要がありますbetter-scroll 。

better-scroll の簡単な紹介:

better-scroll は、モバイル側でのさまざまなスクロール シナリオのニーズを解決することに焦点を当てたプラグインです (PC はすでにサポートされています)。そのコアは iscroll の実装に基づいており、その API 設計は基本的に iscroll と互換性があり、いくつかの機能が拡張され、いくつかのパフォーマンスの最適化が行われています。
better-scroll はネイティブ JS に基づいて実装されており、フレームワークには依存しません。コンパイルされたコード サイズは 63 kb、圧縮後は 35 kb、gzip 後はわずか 9 kb で、非常に軽量な JS ライブラリです。

これら 2 つに加えて、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>
<p class="list-shortcut">
 <ul>
  <li v-for="(item, index) in shortcutList"
  class="item"
  :data-index="index"
  :key="item.id"
  >
   {{ item }}
  </li>
 </ul>
</p>

shortcutListは属性を計算して取得されます。タイトルの最初の文字を取得するだけです。

shortcutList () {
 return this.singers.map((group) => {
  return group.title.substr(0, 1)
 })
}

better-scroll を使用してください

スクロールを実現するには、better-scroll を使用してください。ちなみに、使用する際はインポートを忘れずに。

created () {
 // 初始化 better-scroll 必须要等 dom 加载完毕
 setTimeout(() => {
  this._initSrcoll()
 }, 20)
},
methods: {
 _initSrcoll () {
  console.log('didi')
  this.scroll = new BScroll(this.$refs.listView, {
   // 获取 scroll 事件,用来监听。
   probeType: 3
  })
 }
}

スクロールの初期化を改善するには作成されたメソッドを使用し、DOM がロードされるまで待つ必要があるため setTimeout を使用します。そうしないと、dom を取得できない場合、better-scroll は初期化に失敗します。

メソッドはここでは 2 つのメソッドで書かれているので、見た目が乱雑にならないように、直接呼び出すだけです。

初期化中に、2 つのプローブタイプが渡されます: 3. 説明: プローブタイプが 3 の場合、スクロール イベントは、画面のスライド中だけでなく、勢いスクロール アニメーションの実行中にもリアルタイムで送出されます。この値が設定されていない場合、デフォルト値は 0 で、スクロール イベントは送出されないことを意味します。

クリックイベントを追加し、インデックスに移動イベントを追加してジャンプを実現します

まず、タッチスタートイベントをインデックスにバインドする必要があります(画面上で指が押されたときにトリガーされます)。v-onを直接使用するだけです。次に、インデックス値を取得できるようにインデックスにデータインデックスを追加する必要があります。 :data-index="index" を使用します。

<p 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>
</p>

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])
 }
}

このようにして、インデックス機能が実現できます。

もちろん、これでは満足できませんよね?クールな特殊効果を追加する必要があります。たとえば、インデックスの強調表示など~~

モバイルコンテンツのインデックスの強調表示

うーん、現時点では少し複雑です。しかし、忍耐力があれば理解できるでしょう。

コンテンツがスクロールされたときに Y 軸のオフセット値を返すためには、better-scroll の on メソッドが必要です。したがって、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]
// 得到这样的值

然后在 watch 中监听 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 中 import,然后 Vue.use

import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {
 loading: require('./common/image/default.jpg')
})

添加一张 loading 图片,使用 webpack 的 require 获取图片。

然后在需要使用的时候,把 :src="" 换成 v-lazy="" 就实现了图片懒加载的功能。

总结

移动端字母索引导航就这么实现啦,感觉还是很有难度的哈(对我来说)。

主要就是使用了 better-scroll 的 on 获取移动偏移值(实现高亮)、scrollToElement 跳转到相应的位置(实现跳转)。以及使用 touch 事件监听触摸,来获取开始的位置,以及滑动距离(计算最后的位置)。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

JS callback回调函数使用案例详解

React Navigation实战中有哪些注意事项

以上がモバイル端末でアルファベット順のインデックスナビゲーションを作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。