blog

アプレットタブの実装

タブ選択ページ\nこのタブページを書くには丸2日かかりましたが、主に2つの理由があります:\n小さなプログラムの構文は、CSSスタイルの理解が徹底されていないに精通していません\n何度も同僚にいくつか...

Jun 8, 2020 · 4 min. read
シェア

先週、仕事はフロントエンドのことを学ぶことを考えて非常に忙しくはありませんが、彼女は練習ページやプロジェクトを持っているかどうかを確認するために、古い夏に尋ねました。彼女はフロントエンドの学習は、小さなプログラムを見て、シンプルで開始するには良いことができますので、それは私にいくつかの小さなプログラムのページを与えたと述べました。

タグ選択ページ

このタブを書くのに丸2日かかったのには、主に2つの理由があります:

  • 小さなプログラムの構文はなじみがありません

  • CSSスタイルの理解不足

何度も同僚にいくつかのCSSプロパティ、スタイルと一連の質問をしました。以下は、私自身が実装した絵の効果です:

実現のアイデア

このタブの実装にはいくつか注意点があります:

  • データの不確実性(1月~12月
  • 1画面に最大5台、対応機種
  • 2つ離れたタブをクリックすると、自動的に画面の中央にホームインします。
  • ページスクロールとインジケーターのリンク効果

アプレットのドキュメントを確認したところ、スクロール効果を実現できるのはscrollViewだけで、UI層の設計案は図のようになっています:

scrollViewの各項目には、item.idx、item.trueIdx、item.tagの3つのデータがバインドされています:

<view class="header">
 <scroll-view class="scroll-view-p" scroll-x="true" scroll-with-animation="true" scroll-into-view="{{toView}}" bindscroll="onscroll">
  <view class="scroll-x">
   <view wx:for-items="{{scrolls}}" wx:key="idx" wx:for-item="item">
    <view data-key="{{item.idx}}" data-value="{{item.trueIdx}}" id="{{item.tag}}" class="scroll-item {{item.select ? 'scroll-item-s' : ''}}" style="margin-left: {{index == 0 ? 0 : itemMarge}}px;" catchtap="itemClickEven">
     {{item.name}}
    </view>
   </view>
  </view>
 </scroll-view>
 <view class="indicator" style=" margin-left:{{12 + (itemMarge + itemWidth) * active}}px;"></view>
</view>

ビューを書くときに注意しなければならないことは、scrollViewの各項目はビューラベルでラップする必要があるということです。

以下は各 scrollView アイテムの css スタイルです:

.scroll-item {
  display: flex;
  align-items: center;
  width: 40px;//使用 px 为绝对宽度,rpx 为相对宽度,会自动适配
  height: 30px;
  background: white;
  font-size: 28rpx;
  color: rgba(153, 153, 153, 1);
  justify-content: center;
}

cssスタイルを設定する際、幅と高さは常にrpxで、iPhone6デバイスでは、1画面あたり5タブ、1タブあたり80rpx、残りのスペースはscrollViewの幅に応じて均等に分割されます。しかし、これはiPhone6以外のデバイスでは、1画面に5つ以上のタブがあったり、少なかったりという違いがあります。調べてみたところ、rpxという単位でサイズを設定している場合、iPhone6端末の横幅に合わせてしまうため、端末によって各タブの横幅が均等にならず、結果的に1画面あたりのタブ数が一定にならないようです。

データの構築

このタブビューでは、常に現在の月が一番上、つまり大きいものから小さいものへとソートされますが、配列の添え字は小さいものから大きいものへとソートされるため、データを構築する際に変換する必要があります。

var timestamp = Date.parse(new Date());
var date = new Date(timestamp);
//获取 ,7月 即 07  
var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
let temp = [];
for (let index = M; index > 0; index--) {
  var name = index + "月";
  var select = false
  if (index == M) {
    name = " ;
    select = true;
  } else if (index < 10) {
    name = "0" + index + "月";
  }
  index = parseInt(index);
  temp.push({
    idx: index,//月份
    trueIdx: Math.abs(index - M),//用绝对值计算实际下标 当月下标为 0
    select: select,
    name: name,
    tag: "id_" + index,//scrollview 要滚动到哪一个 item
  })
}
this.setData({
  toView: "id_" + M,
  scrolls: temp
})

私の最初のアイデアは、scrollViewのスクロールX位置を計算することでした。公式ドキュメントでは、スクロールがより正確になるように、ビューをバインドするためにscroll-into-viewを使用することを推奨しています。そこで、データを構築するときに、アイテムを見つけやすくするために、それぞれのデータをビューのidにバインドしました。

月をクリックすると、アイデアがスクロールします:

現在のデータが5以上の場合、2つ以上のラベルを離してクリックすると、自動的に真ん中の位置にスクロールし、インジケータが対応する位置を指すようになります。

任意の項目をクリックしたときに応答するメソッドです:

itemScrollEvent: function(index,trueIdx){
      this.data.scrolls.map(item => item.select = (item.idx == index))
      let totleCount = this.data.scrolls.length - 1;
      //判断指示器要在哪个位置 (0,1,2,3,4)
      //共有多少个月份,首个 item 即当月
      let toViewId = totleCount;
      let currentIndex = index;
      if (totleCount < 5) {
        // 前 5 月需要特殊处理一下,因为下标是反的
        toViewId = totleCount;
        currentIndex = trueIdx;
      } else {
        // センター
        if (index >= 3 && index < totleCount - 1) {
          toViewId = index + 2;
          currentIndex = 2;
        } else if (index > totleCount - 2) {
          // 
          toViewId = totleCount + 1;
          currentIndex = toViewId - index;
        } else {
          // 
          toViewId = totleCount - 3;
          currentIndex = Math.abs(index - 5);
        }
      }
      this.setData({
        active: currentIndex,//その位置の指標
        scrolls: this.data.scrolls,//データソースを変更する
        toView: 'id_' + toViewId,//どのビューにスクロールする
      })
    },

ページの不備

このタブは、非常に一般的で、月であることができ、他のコンテンツであることができ、変更はスタイルです。ですから、コードのカプセル化の部分はより汎用的ではなく、ただ現在のビジネスロジックに従ってコードを書けばいいのです。この機能を取り出し、小さなモジュールにカプセル化することができます。

タブをクリックする代わりに手動でタブをスクロールすると、添え字インジケータが元の位置に留まり、scrollView のスクロールが停止しても適切な位置に戻りません。

アプレットのドキュメントを確認したところ、このためのAPIはなく、手動でクリックしてスクロールするか、手でドラッグしてスクロールするonscrollメソッドしかありませんでした。これでは、スクロールのソースを区別する方法も、インジケータの位置を変更する方法もありません。iOSのように、ジェスチャードラッグのコールバック、スクロールアニメーションのコールバック、スクロールストップのコールバックなどがあるわけではありません。

代替

タブページをドラッグするジェスチャーをすると、インジケータが不正確に表示されます。そこで、私は妥協案として、scrollViewの各アイテムにインジケータをバインドし、デフォルトでは非表示にし、月が選択されたときに当月を表示し、他の月を非表示にすることを思いつきました。この欠点は、インジケータの変位アニメーションがなくなり、単純な表示/非表示のエフェクトに置き換わることです。これはデータをデザインする際にも非常にシンプルで、ページ上で必要なのはアイテムのcssプロパティを変更することだけです。私は両方のスタイルを実装しましたが、比較すると、アニメーション効果がある方が好きです。

ボックスモデルの理解

フロントエンドを理解するには、ボックスモデルの学習が不可欠です。iOSのフレームとバウンズだけで、ボックスモデルにはより多くの属性がありますが、両者は類似しています。フレームとバウンズの関係を見てから、cssのボックスモデルを見ても、既視感はありません。

あなたが賢いページを設計したい場合は、ボックスモデルを徹底的に理解する必要があります、タブページでは、フロントエンドの同僚は私にボックスモデルのいくつかのプロパティを表示するには、非常に素晴らしいの使用。

ボックスモデルでは、この作品は、私はまた、氷山の一角を学んだ、結局のところ、唯一の理解の多くの側面では、非常に徹底していない2ページを書いて、使用は快適ではありません。だから、スキルでより熟練になるために必要なページやビジネスがまだたくさんあります。

Read next

解決済み:テキストオーバーフロー表示省略の失敗

vue-cli2のビルドプロジェクトで見つかった問題は、cssのテキストオーバーフロー表示ellipsisスタイルを使用して、ローカル開発表示は正常ですが、webpackのパッケージングが無効である後、トラブルシューティングの後、パッケージ化されたコードは、次のコードを使用するソリューションが欠落していることがわかりました。

Jun 8, 2020 · 1 min read