京東好適ウィジェットの実現コード例


前に書く
年を越す時、どうしてずっと家にいて家から出ないでパソコンを見ていますか?これは道徳的な没落ですか?それとも人間的な消滅ですか?このすべては一匹のコウモリから話さなければなりません。
咳と咳、よくなりました。本題に戻ります。WeChatの出す小さいプログラムは軽くて強いと言えて、だから最近私も小さいプログラムの学習を始めて、学んだのはとても多くても多くの文書を見て、しかしいつも自分が何を学んでいないと感じて、感じはとても困惑します。実践が真の知識を生むということは、他人を模倣する小さなプログラムから選んで、京東好のこの小プログラムを選んだのです。
開発ツール
マイクロクレジット開発ツール
VSコード
効果てきらん
余計なことを言わないで、とりあえず写真を作ってみます。ここをクリックしてもっと多くの写真を見ます。


プロジェクト構造
このプロジェクトは普通の開発を使っています。すべてのデータをjson-serverに入れてシミュレーションしました。
多くの人が不思議に思うかもしれませんが、これはeasy mockのウェブサイトが開けられないことを発見しました。失敗を要求するのはとても不便です。だから、私はしばらくmockのデータを選択していません。後期に時間があれば、データをeasy mockに移動します。

|-jd_recommend    
  |-api       
    |-db.json      
  |-assets     
    |-icons      
    |-images     
  |-components     
    |-navigationBar       
    |-toast        toast
    |-stepper      vant     
    |-...               
  |-pages     
    |-about         
    |-account          
    |-afterMarket        
    |-appointment        
    |-buy              
    |-commentDetail       
    |-discount         
    |-explore        
    |-feedback        
    |-fix          
    |-goodsDetail           
    |-index       
    |-jd               
    |-login         
    |-orderDetail        
    |-seller         
    |-service      /    
    |-shopCart         
    |-user            
  |-style     
    |-comment.wxss       
    |-goodsCard.wxss       
    |-nav.wxss         
    |-orderCard.wxss       
    |-popright.wxss       
    |-popup.wxss         
  |-utils     
    |-util.js promise    
  app.js       js
  app.json      json  
  app.wxss      wxss
カスタムコンポーネント
ほとんどの人が小さいプログラムを書くと必ずnavigationBarのtitleを修正します。マイクロクレジットのプログラム開発はこのコンポーネントを内蔵しています。直接にap.jsonに配置することができます。しかし、自分の持っているnavigationBarの姿は固定されています。次のようなnavigationBarを見たことがあります。

一般的なnavigationBarに比べて、左上の方にホームに戻るボタンが多いです。これは多段階のページがある小さなプログラムに必要です。そうでないと、訪問の階層が深すぎて、ユーザーはどうやってホームに戻るか分かりません。しかし、小さいプログラムの開発は自分で持ってきてこのようながなくて、幸いにもカスタムすることができて、次に私達はひとつカスタムに来ます。
navigationBar
まず、ページの構造を構築します。

<!-- components/navigationBar/index.wxml -->
<view class='nav-wrap' style='height: {{height*2 + 20}}px;'>
  <!--           -->
  <view class='nav-title' style='line-height: {{height*2 + 44}}px;'>{{navbarData.title}}</view>
  <view style='display: flex; justify-content: space-around;flex-direction: column'>
    <!--              home   -->
    <!--   wx:if='{{navbarData.showCapsule}}'              ,      -->
    <view class='nav-capsule' style='height: {{height*2 + 44}}px;' wx:if='{{navbarData.showCapsule}}'>
      <!--         ,wx:if='{{!share}}'         -->
      <view bindtap='_navback'>
        <image src='../../assets/icons/back.png' mode='aspectFill' class='back-pre'></image>
      </view>
      <view class='navbar-v-line' wx:if='{{!share}}'></view>
      <view bindtap='_backhome'>
        <image src='../../assets/icons/back_home.png' mode='aspectFill' class='back-home'></image>
      </view>
    </view>
  </view>
</view>
これは非常に一般的なページ構造であり、その高さは取得したデバイスの高さに基づいて決定されることが注目される。
次はまた図仔の線を切る時です。

/* components/navigationBar/index.wxss */
/*                                         */
.nav-wrap {
  position: fixed;
  width: 100%;
  top: 0;
  background: #fff;
  color: #000;
  z-index: 9999999;
  border-bottom: 1rpx solid #EFEFF4;
}
/*       */
.nav-title {
  position: absolute;
  text-align: center;
  max-width: 400rpx;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  font-size: 36rpx;
  color: #2c2b2b;
  /* font-weight: 600; */
}
.nav-capsule {
  display: flex;
  align-items: center;
  margin-left: 30rpx;
  width: 140rpx;
  justify-content: space-between;
  height: 100%;
}
.navbar-v-line {
  width: 1px;
  height: 32rpx;
  background-color: #e5e5e5;
}
.back-pre, .back-home {
  width: 32rpx;
  height: 36rpx;
  margin-top: 4rpx;
  padding: 10rpx;
}
.nav-capsule .back-home {
  width: 36rpx;
  height: 40rpx;
  margin-top: 3rpx;
}

// components/navigationBar/index.js
const app = getApp()
Component({
 properties: {
  navbarData: {  //navbarData           ,       
   type: Object,
   value: {},
   // observer: function (newVal, oldVal) { }
  }
 },
 data: {
  height: '',
  //           
  navbarData: {
   showCapsule: 1
  }
 },
 attached: function () {
  //               
  this.setData({
   height: app.globalData.height
  })
 },
 methods: {
  //       
  _navback() {
   wx.navigateBack()
  },
  //     
  _backhome() {
   wx.switchTab({
    url: '/pages/index/index',
   })
  }
 }
}) 
京東の優先順位はここの二つのボタンは全部トップページに戻ります。開発の時はおかしいと思いましたので、変えました。
ここでは大域的に定義された変数、すなわち取得したデバイスの上部ウィンドウの高さ(デバイスウィンドウの高さによって異なります。これによってカスタムナビゲーションバーの高さを設定します。)を取りに行きます。

app.js
App({
 onLaunch: function () {
  ......
  wx.getSystemInfo({
   success: (res) => {
    this.globalData.height = res.statusBarHeight
   }
  })
 },
 globalData: {
  ...
  height: 0
 }
})
セットを決める時は必ずjsonにカスタムコンポーネントを書いてください。

// components/navigationBar/index.json
{
 "component": true
}
次はこのコンポーネントを呼び出します。

<navigationBar navbar-data='{{navbarData}}'></navigationBar>
このコンポーネントを引用ページのjsonに導入することを忘れないでください。

"usingComponents": {
  "navigationBar": "../../components/navigationBar/index"
 }
Toast
Toastも同じように、小さいプログラムの開発がもうできました。中のアイコンを交換することができますが、中のアイコンを変えることができます。開発の過程で関連の実現方法を検索しましたが、大体改行する文字の後ろにrnを加えると実現できるということですが、自分で自分で測ってもだめです。

<!-- components/toast/index.wxml -->
<!--                 -->
<view class='mask' hidden="{{hide}}" style='top: {{toastData.top}}'>
  <image class="image" src='../../assets/icons/{{toastData.icon}}.png' mode='aspectFit'></image>
  <view class="info">
    <view class='info1' wx:if="{{toastData.info1 != ''}}">{{toastData.info1}}</view>
    <view class="info2" wx:if="{{toastData.info2 != ''}}">{{toastData.info2}}</view>
  </view>
</view>

/* components/toast/index.wxss */
.mask {
  width: 440rpx;
  height: auto;
  border-radius: 20rpx;
  position: fixed;
  left: 155rpx;
  z-index: 1000;
  background: rgba(0, 0, 0, 0.6);
  text-align: center;
  padding-bottom: 30rpx;
}
.image {
  z-index: 1000;
  width: 80rpx;
  height: 80rpx;
  padding-top: 30rpx;
  padding-bottom: 20rpx;
}
.info1, .info2 {
  color: #ffffff;
  font-size: 32rpx;
}
.info {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

// components/toast/index.js
Component({
 properties: {       //      
  toastData: {      //        
   type: Object,     //   (  ),         :String, Number, Boolean, Object, Array, null(      )
   value: {
    icon: 'success'
   }   //      (  ),               
  },
 },
 data: {
  hide: true
 },
 methods: {
  showToast: function () {
   let that = this;
   that.setData({
    hide: false
   });
  },
  hideToast: function (e) {
   let that = this;
   setTimeout(function () {
    that.setData({
     hide: true
    });
   }, 2000);
  }
 }
})
ここでは、コンポーネントに対して2つの方法を定義し、Toastを表示および非表示にします。ここで注意したいのですが、カスタムコンポーネント定義の呼び出し方法は、まずページからコンポーネントを取得します。

<toast id="toast" toast-data="{{toastData}}"></toast>

Page({
  data: {
  toastData: { // toast     
   icon: "success",
   info1: "       ",
   top: "50%"
  }
 },
 onReady() {
  this.toast = this.selectComponent("#toast");
 }
})
そして、Toastをトリガするイベントには、この2つを書きます。

this.toast.showToast()
this.toast.hideToast()
機能の実現
ナビゲータ
ナビゲーションというのもよくあります。選択欄によって種類が違ってきます。たとえば:

機能要件:
  • ナビゲーション欄をクリックし、対応するコラムデータを表示します。
  • 番の欄にものがない場合は、対応するメッセージを表示します。
  • その機能を実現するのは難しくないです。直接sroll-viewを上に上げます。京東さんはここでちょっと足りないところがあります。右側のナビゲーション欄をクリックしたら、ナビゲーションバーが右に移動して後ろの項目が表示されないので、開発者は違った考えを持っているかもしれません。
    
    <view class="navigator">
     <scroll-view scroll-x="true" class="nav" scroll-left="{{navScrollLeft}}" scroll-with-animation="{{true}}">
      <block wx:for="{{navData}}" wx:for-index="id" wx:for-item="navItem" wx:key="id">
       <view class="nav-item {{currentTab == id?'active':''}}" data-name="{{navItem.name}}" data-current="{{id}}" bindtap="switchNav">
        {{navItem.name}}
       </view>
      </block>
     </scroll-view>
    </view>
    jsを通じて動的な書込みデータが実現できます。ここで設定されているcurrentは現在選択されている欄です。これによってスタイルなどを変えることができます。
    
    switchNav(e) {
        const cur = e.currentTarget.dataset.current; // Number
        let currData = []
        // console.log(cur.toString());
        if (cur === 0) {
          currData = this.data.goods
        } else {
          this.data.goods.forEach(val => {
            if (val.category === cur.toString()) {
              currData.push(val)
            }
          })
        }
        this.setData({
          currentTab: cur,
          category: cur,
          currData
        });
    }
    クリックした後に自動的にクリックする方法を実現するならば、もっと多くの内容を表示します。動的にnavScrolLeftの値を変えて実現できます。ここでは詳しくは言いませんが、実現するには時間がかかりました。実現するのはあまり良くないので、コードに入れていません。これからこの効果を出したいナビゲーションバーはネットで検索してデモを見てから使ってみてください。つまりプログラム猿の最高の境界はコピー貼り付けです。犬頭(間違い)
    プルダウンメニューとフィルタ枠
    この二つは似ています。ただ引き出した位置が違っています。ここではフィルタ枠の例を挙げます。まずその長さを見てみます。

    まず構造を見てみます。ここでは中間の内容を省略しました。
    
    <!--             -->
    <view class="float {{isRuleTrue?'isRuleShow':'isRuleHide'}}">
      <view class="animation-element" animation="{{animation}}">
        ...          ...
        <!--         -->
        <view class='bottom'>
          <view class="animation-reset" bindtap="reset">  </view>
          <view class="animation-button" bindtap="success">  </view>
        </view>
      </view>
    </view>
    
    /*      */
    /*       */
    .isRuleShow {
      display: block;
    }
    .isRuleHide {
      display: none;
    }
    .float {
      height: 100%;
      width: 100%;
      position: fixed;
      z-index: 999;
      top: 0;
      left: 0;
      /*          */
      background-color: rgba(0, 0, 0, 0.5);
      padding-left: 30rpx;
      padding-left: 30rpx;
      /* margin-top:80rpx; */
    }
    .animation-element {
      width: 600rpx;
      height: 100%;
      padding-left: 30rpx;
      padding-right: 30rpx;
      background-color: #ffffff;
      border: 1px solid #f3f0f0;
      position: absolute;
      right: -550rpx;
      box-sizing: border-box;
    }
    .bottom {
      width: 600rpx;
      height: 110rpx;
      font-size: 32rpx;
      padding-top: 55rpx;
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      display: flex;
    }
    .animation-reset {
      width: 50%;
      height: 100%;
      line-height: 50%;
      text-align: center;
      padding-top: 55rpx;
      border-top: 1px solid #EFEFF4;
    }
    .animation-button {
      width: 50%;
      height: 100%;
      line-height: 50%;
      color: #fff;
      text-align: center;
      background-color: #ED7358;
      padding-top: 55rpx;
    }
    重要なのは、イベントの表示と非表示、アニメーションを使用する必要がありますが、アニメーションに慣れていない場合は、いくつかの資料を参照することができます。同様に、私も他の業務を実現するためのいくつかの内容を削除しました。
    
    showSelect() { //       
      this.setData({
       isRuleTrue: true
      })
      //    245 step         
      this.animation.translate(-245, 0).step()
      this.setData({ animation: this.animation.export() })
     },
     success: function () { //       
      this.setData({
       isRuleTrue: false,
       selected: true
      })
      this.animation.translate(0, 0).step()
      this.setData({ animation: this.animation.export() })
     },
    ショッピングカートロジック

    このような効果を実現するのは難しくないです。自分の考えがはっきりしていて、回り道をしてはいけません。ショッピングカートの加入を実現するのは難しくないです。詳細はショッピングカートのアイコンの右上の数字です。ショッピングカートに加入する数量によって、ダイナミックに変化します。また、同じ商品であれば、新しいものを追加する必要がなく、元の数量を修正する必要があります。
    ここで私が使っているのはウィジェットのwx.set Strageです。
    
    <view class='bottom'>
      <view class="animation-reset" bindtap="addCart">     </view>
      <view class="animation-button" bindtap="buy">    </view>
    </view>
    
    addCart() { //      
      this.setData({
       toastData: { // toast     
        icon: "success",
        info1: "       ",
        top: "50%"
       }
      })
      this.toast.showToast()
      this.toast.hideToast()
      this.hideModal()
      //             
      let cartData = wx.getStorageSync('cart') || [];
      let count = 0
      cartData.map(val => {
       if (val.title === this.data.currData[0].title && val.type === this.data.choose_value) {
        val.num += this.data.num
        count++ //             
       }
      })
      if (count === 0) { //                 
       let data = {
        id: this.data.currData[0]._id,
        title: this.data.currData[0].title,
        weight: "0.78kg",
        type: this.data.choose_value,
        num: this.data.num,
        price: this.data.currData[0].plain_price,
        img: this.data.currData[0].thumb,
        discount: 20,
        select: true //     ,        
       }
       cartData.push(data)
      }
      //            
      let allNum = 0
      cartData.forEach(val => {
       allNum += val.num
      });
      this.setData({
       allNum
      })
      wx.setStorage({
       key: 'cart',
       data: cartData
      })
     },
    ここでは自分の開発によって方式を決められます。もしあなたが雲開発を使うなら、データを雲データベースに保存することができます。
    トップに戻る

    これもありふれた機能です。ページの比較後の位置に滑ったら、素早くトップに戻らなければなりません。ここで覚えて、swiperで実現します。まずページ上で上に戻るアイコンをかきます。
    
    <!--                  -->
    <scroll-view class="bigWrap" 
      scroll-y="true" 
      scroll-top="{{scrollTop}}" 
      bindscroll="scroll" 
      style="position: absolute; left: 0; top:0; bottom: 0; right: -999rpx;">
    <view class="goTop" bindtap="goTop" wx:if="{{&& floorstatus}}">
      <image class="icon_goTop" src="../../assets/icons/back_to_top.png"></image>
    </view>
    </scroll-view>
    {scrollTop}は、スライドするときの上からの位置を表します。そのスタイルも簡単です。固定位置を使ってスクリーンにセットします。ここでは必ずページの階層に注意してください。そうでないと、他のコンポーネントによってブロックされるかもしれません。
    
    /*      */
    .goTop {
      position: fixed;
      bottom: 200rpx;
      right: 20rpx;
      width: 65rpx;
      height: 65rpx;
      border: 1px solid #DDDDDD;
      border-radius: 50%;
      background-color: #fff;
      text-align: center;
    }
    .icon_goTop {
      width: 40rpx;
      height: 40rpx;
      padding-top: 12rpx;
      padding-left: 2rpx;
    }
    
     goTop(e) { //     
      this.setData({
       scrollTop: 0
      })
     }
    あなたもきっと気づいています。ある程度の距離に滑り込んだら、それはやっと表示されます。これはswiperバインディングのスクロールイベントに依存します。
    
    scroll(e) { //     
      //                  this.data.scrollTop
      let floorstatus = false
      if (e.detail.scrollTop > 300) {
       floorstatus = true
      }
      this.setData({
       floorstatus
      })
    }
    機能は大体このように言いますが、大牛には目立たないような機能があるように見えますが、初心者の私にはちょっと難しいです。大牛が私の機能の実現を見たら怒られないようにしてください。
    注意すべき点
    小さいプログラムの開発やvueなどの開発をしたことがある人は必ずこの名詞を聞いたことがあります。私はその幸運なガチョウです。開発中にこの状況に遭遇しました。
    買い物車の中で商品をクリックすると商品の詳細がジャンプできますが、ジャンプイベントを商品ごとのカードに結び付けてしまいました。これは修正商品の数量をクリックした時に数字が修正されました。でも、直接商品の詳細にジャンプします。例えば、下のように…

    これは非常に友好的ではないです。ユーザーの体験は非常に悪いです。事件の泡が発生することについて、微信小プログラムの解決方法はbindtapをcatch tapに置き換えることです。
    しかし、偶然にも、私はその一番幸運なガチョウです。歩入器はVANt Weapコンポーネントの倉庫で使っています。多くの資料を探しましたが、効果的な解決策が見つからず、部品の倉庫を使うのを諦めそうになりました。
    この点はやはり重要です。だから、みんなは開発する時、必ず事件の泡を考えなければなりません。これも最後に書いた原因です。
    後に書く
    最後に、私が言いたいのは、小さなプログラムの開発は本当に容易ではないです。良い小さなプログラムを開発するには、性能とユーザー体験を考慮する必要があります。最初の小さなプログラムがそろそろ完成すると思ったら、本当にジャンプしてジョイfulを歌います。プログラム猿としては本当に容易ではないです。しかし、幸いにも技術を共有したい人が多いです。今回の開発の過程で、私もたくさんの資料、コミュニティと文書を調べました。小さいプログラムの学習は私も足どりを停止することはできなくて、このプロジェクトはまだとても多くするよくない地方があって、私が出してくるのもみんなと私が交流して分かち合うことを望むので、後期に私も引き続き改善してこの小さいプログラムのプロジェクトを最適化します。私の作品が初心者のために役に立つことを願っています。
    最後に私のgithubプロジェクトの住所を添付します。公式文書
    もしあなたがこのプロジェクトがいいと思ったら、あるいはあなたに助けがあれば、スターを歓迎します。あなたが点灯するスターはすべて私の前進の原動力になります。
    ここで、京東好小プログラムの実現コード例についての文章を紹介します。京東好小プログラムの内容については、以前の文章を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。