天天看點

微信小程式項目小結

項目做一個階段性總結吧,針對代碼,不針對業務

如果有更好的方案,歡迎交流

一、登入子產品

一般情況下,使用者權限資訊會在app.js請求

App({
  onLaunch() {
  	// 擷取code 擷取openid 再查詢個人資訊(權限)
  }
})
           

但是我們app.js接口請求時,異步,頁面與小程式生命周期執行順序是不受控制的。尤其當你的首頁部分資料是需要個人權限資訊來渲染的。

小程式建立項目的時候,官方有個解決方案是回調。

微信小程式項目小結
微信小程式項目小結

但是如果微信小程式第一次首頁跳轉就是index頁面時,是沒有問題的。可你分享其他頁面的時候(還是權限問題,是遊客還好),總不能每次都加一個回調。而且,如果你在該頁面/index回調裡寫請求接口,隻能觸發運作一次;如果你第一次跳到其他頁面,再回到/index,回調内的接口是不走的,還要跟上圖類似,還要做判斷,資料請求是否請求到資料,沒請求還要再做一次請求。個人感覺很亂,也煩。

個人方案

加了一個過渡頁面/pages/welcome/welcome,

app.js

App({
  onLaunch() {
  	// 擷取code 擷取openid 再查詢個人資訊
     const url = (getCurrentPages()[getCurrentPages().length - 1].route)
     wx.reLaunch({
        url: url === 'pages/welcome/welcome' ? '/pages/home/home' : url, // 如果是程式預設首頁路徑配置是welocome, 就跳轉真的首頁/home,如果是其他頁面,就跳到對應頁面,反正此時使用者權限接口完成(可能會有點閃)
     })
  }
})
           

此時welcome頁面是預設頁面,沒有任何邏輯,隻是占位。關鍵在于當app.js使用者權限請求完成時,來觸發頁面跳轉。

在我看來,确實如此是完美解決問題,但是,但是,有一個問題。我分享其他頁面的時候,左上角是小房子,點選回到首頁是welcome頁面。

我現在加了一個全局屬性來判斷,做welocme跳轉

App({
  onLaunch() {
   this.globalData.isGetUserApi = false;
  	// 擷取code 擷取openid 再查詢個人資訊
  	
   this.globalData.isGetUserApi = true;
   const url = (getCurrentPages()[getCurrentPages().length - 1].route)
   wx.reLaunch({
        url: url === 'pages/welcome/welcome' ? '/pages/home/home' : url, 
     })
  },
  globalData: {
    isGetUserApi: false, // app.js中擷取使用者資訊是否請求完成
  }
})
           

welcome

onShow: function () {
    if(getApp().globalData.isGetUserApi){
      const url = (getCurrentPages()[getCurrentPages().length - 1].route)
      wx.reLaunch({
        url: url === 'pages/welcome/welcome' ? '/pages/home/home' : url,
      })
    }
  },
           

這樣有問題

會報錯

fail page \"pages/***/pages/***/***\" is not found
           

修改如下

但是還有一個小問題,route隻是把路徑取出,但是動态拼接的query

?xx=xxx&xx=xxx

不會一起取出

const options = getCurrentPages()[getCurrentPages().length - 1].options
 let urlData = '';
 for (let key in options) {
    urlData += (key + '=' + options[key] + '&')
 }
           

授權使用者手機号

此處用的是vant

// app.js

      wx.login({
        success: res => {
          if (res.errMsg === 'login:ok') {
            const code = res.code
            getOpenId({
              js_code: code
            }).then(res => { // 走接口根據code擷取openId session_key
              const data = JSON.parse(res.data)
              if (!data.errcode && res.code === '0') {
                wx.showToast({
                  title: '小程式初始化',
                  icon: 'loading'
                })
                this.globalData.openId = (JSON.parse(res.data)).openid  // 背景不願轉,隻能自己轉了
                this.globalData.session_key = (JSON.parse(res.data)).session_key


  globalData: {
    openId: null
    session_key: null, // app.js中擷取使用者資訊是否請求完成
  }


// 授權頁面
  getPhoneNumber(e) {
    const that = this;
    if (e.detail.errMsg === "getPhoneNumber:ok") {
      const data = {
        encryptedData: e.detail.encryptedData,
        iv: e.detail.iv,
        session_key: getApp().globalData.session_key
      }
      wx.checkSession({
        success() {
          getUserPhone(data).then(res => {
            if (res.code === '0') {
              const result = JSON.parse(res.data)
              getApp().globalData.userInfo.phone = (result.phoneNumber)
            }
          })
        },
        fail() {
          wx.showToast({
            title: 'session_key 過期',
          })
          wx.login({
          	// 重新來擷取
		  })
        }
      })
    }
  },
           
微信小程式項目小結

wxs

後端字段傳回格式,不是前端想要的格式,在頁面上寫邏輯,邏輯正确但是不出效果

xml

<wxs src="../../utils/format.wxs" module="tools" />

<view>{{tools.xx(xx)}}</view>
           

元件傳值

父傳子 屬性傳值

// 父
<component array="{{ array }}"></component>
// 子
properties: {
   array: array,
},
           

父元件調用子元件方法

// 父
<component id="component"></component>

this.selectComponent("#component").functionName
           

子傳父

// 子 
 chooseSpecification(e) {
   this.triggerEvent('changeMoney', {
        money: money
     })
 },
    
// 父
<component bind:changeMoney="changeMoney"></component>
  changeMoney(e) {
  	console.log(e.detail.money)
  },

           

input綁定值

簡單的,還是用雙向綁定

model:value

, 還是可以省一些代碼量

清單 詳情 狀态切換

資料請求優化和詳情狀态更新傳回清單

微信小程式項目小結

好比頁面有狀态,進清單頁仍然是tab

微信小程式項目小結

正常處理,一開始會在url是拼接類型值,清單頁onload生命周期,options取出類型,走清單接口。之後tab監聽點選事件再走對應接口。

我這裡是用van-tab change事件監聽的,會出現頁面走兩次接口,第一次onload,第二次change事件。

<van-tabs active="{{ tabActive}}" bind:change="onTabChange"></van-tabs>


  onLoad: function (options) {
    const {
      status
    } = options;
    this.setData({
      tabActive: status,
    })
  },


  onShow: function () {
    this.getList() // 詳情狀态更新傳回清單,清單也要對應更新
  },

  onTabChange(e) {
    if (e.detail.name == this.data.tabActive) { 
      return
    }
    this.setData({
      tabActive: e.detail.name
    })
    this.getList()
  },

  getList() {
    this.setData({
      orderList: []
    })
    wx.showLoading({
      title: '資料加載中',
    })
    getOrderList(this.data.tabActive).then(res => {
      if (res.code == '0') {
        wx.hideLoading()
        this.setData({
          orderList: res.data
        })
      } else {
        wx.hideLoading()
      }
    })
  },
           

頁面分享

如果是靜态值,沒問題,但是如果分享連結中有動态值

onShareAppMessage: function (options) {
    if (options.from === "button") {
      return new Promise(function (resolve, reject) { // 之前一個版本是沒有Promise,是傳回不了自定義分享對象
        getInviteCode().then(res => { // 接口請求
          if (res.code === '0') {
            const code = res.data;
            resolve({
              title: xxx+ '邀請您加入',
              path: '/pages/register/register?shareCode=' + code + '&role=3',
              imageUrl: 'xxx'
            })
          }else{
            reject(res)
          }
        })
      })
    }
  },

           

元件動态資料傳遞

動态資料我這裡指比如app.js請求的資料,不能直接像頁面傳值getApp().globalData;我是在頁面指派,利用properties傳值。

複制文本,預設彈框

textPaste(e) {
    const orderid = e.currentTarget.dataset.orderid;
    wx.setClipboardData({
      data: orderid,
      success: function (res) {
        wx.hideToast();
        wx.getClipboardData({ //這個api是把拿到的資料放到電腦系統中的
          success: function (res) {
            wx.showToast({
              title: '複制成功',
              duration: 2000
            })
            console.log(res.data) // data
          }
        })
      }
    })
  },
           

暫時先寫這麼多,後續有補充的再補充