微信小程序開發總結(附源代碼)

最近公司項目不是很忙,有時間研究研究微信小程序。參考了目前市場上各種答題類的app、小程序等等,作了一款本身的微信答題小程序,包括前端和後端,後端是用node作的。如今已經上線了,名字叫【你問我猜猜猜】,你們感興趣的話能夠去試玩一下。css

會vue、react, 微信小程序,so easy

若是以前用過vue或者react,直接看看文檔上手微信小程序徹底沒問題。總體開發思路很類似,包括其中的一些語法,基本上都是同樣的。或者用美團的mpvue框架,那就根本不用學習小程序的語法了,寫起來跟vue同樣。可是咱們開發的時候沒有用框架,用的是原生的微信小程序語言,開發起來也很easy。並且微信小程序有不少本身的API,好比圖片上傳、下載、音頻等等,項目中用到的時候再找文檔就來得及。前端

此次開發的難點,也是微信小程序的難點,應該就是在登陸了。若是把登陸流程弄明白了,在開發其餘的功能,基本上就是時間的問題了。vue

難點:微信小程序登陸

看了好多文檔關於登陸相關的介紹,下圖的介紹是比較詳細的過程,開發過程當中也是採用的這個邏輯。只不過咱們沒有獲取用戶的敏感信息,因此沒有七、8步驟。直接經過wx.getUserInfo()獲取到用戶名、頭像等信息便可知足咱們的需求。node

登陸步驟

  1. 經過調用wx.login() API,成功後會拿到用戶的code信息
  2. 將code信息經過接口,傳給本身的後臺(不是微信的後臺),在服務端發起對微信後臺的請求,成功後拿到用戶登陸態信息,包括openid、session_key等。也就是一般所說的拿code換openid,這個openid是用戶的惟一標識。
  3. 本身的後臺,拿到openid、session_key等信息後,經過第三方加密,生成本身的session信息,返回給前端。
  4. 前端拿到第三方加密後的session後,經過wx.setStorage()保存在本地,之後的請求都須要攜帶這個通過第三方加密的session信息。
  5. 以後若是須要用戶從新登陸,先去檢查本地的session信息,若是存在,再用wx.checkSession()檢查是否在微信的服務器端過時。若是本地不存在或者已過時,則從新從步驟1開始走登陸流程。

登陸的代碼以下:mysql

wx.getStorage({
      key: "code",
      success: res => {
        wx.checkSession({
          success: res => {
            console.log("Session未過時,登錄狀態未失效");
          },
          fail: err => {
            // 從新登陸
            console.log("Session過時,從新登陸");
            loginAction();
          }
        });
      },
      fail: res => {
        console.log("無code信息,調用登陸接口獲取code");
        loginAction();
      }
    });

登陸的流程圖以下:
圖片描述react

注意事項

1. npm這麼容易,install個包用用?

微信小程序沒有包管理這一說(可是最新版本的好像支持npm了),因此想要用到別的庫裏的組件,只能找到源碼,copy過來。git

2. 既然openid是惟一的,那我爲何不能用openid做爲憑證,還要麻煩的用個第三方session

有可能形成數據越權。好比今天我經過個人手機登陸了微信,打開了小程序。可是明天有個朋友想用個人手機登一下微信。若是用openid做爲登陸憑證,登陸小程序的時候檢測到openid已經存在,因此不會再走登陸過程,這樣個人數據就讓個人朋友看到了。因此仍是要按照官方推薦的步驟來。github

3. 本地啓服務,如何經過localhost訪問服務端接口?

微信小程序默認都是https請求,若是本地開發聯調,須要在開發者工具 -> 項目設置裏,勾選上【不校驗合法域名、web-view(業務域名)、TLS 版本以及 HTTPS 證書】,這樣就能夠愉快的使用localhost訪問服務端了。web

4. textarea組件如何清空

一個經常使用的使用場景,用戶反饋裏,用戶巴拉巴拉吐槽完,點擊確認發送成功後,爲了防止用戶再次重複提交,須要將textarea中的數據清空。sql

用過vue的你們都知道,綁定一個字段,當成功後將這個字段賦值爲空就行了。but,微信小程序可不幹。
微信小程序文檔中這樣說明:不建議在多行文本上對用戶的輸入進行修改,因此 textarea 的 bindinput 處理函數並不會將返回值反映到 textarea 上。

如何解決呢。能夠給textarea綁定一個value值。用form表單去提交。成功後將value綁定的值清空就能夠了。

具體代碼以下:

<form bindsubmit="bindSubmit">
    <textarea placeholder="若是您對咱們有任何建議或意見,請在此處向咱們提交,期待您的寶貴建議。" name="feedbackContent" value="{{feedbackContent}}" bindinput="bindTextAreaInput" />
    <button class="submit-btn" form-type="submit" disabled="{{feedbackContent.length == 0 || btnLoading}}" loading="{{btnLoading}}" value="{{feedbackContent}}">
        提交
    </button>
</form>

bindTextAreaInput: function(e) {
    this.setData({
      feedbackContent: e.detail.value
    });
},

bindSubmit: function(e) {
    this.setData({
      btnLoading: true
    });
    addFeedbackRequest({
      content: e.detail.value.feedbackContent.trim()
    }).then(res => {
      if (res.success) {
        this.setData({
          btnLoading: false,
          feedbackContent: ""
        });
        this.showToast("提交成功,感謝您的反饋");
      } else {
        console.log("fail");
        this.showToast("提交失敗,請稍後再試");
      }
    });
  },

5. 有關圖片的引用問題

給頁面添加背景是,若是經過background屬性來添加,抱歉,那你不能引用本地的圖片,只能引用通過base64轉碼的或者網上的圖片。
小程序的文檔上有說,本地資源是沒法經過css獲取的。可是經過image的src屬性引用的圖片,則沒有這個限制。

6. navigateTo層級不能超過5級

文檔上說明:爲了避免讓用戶在使用小程序時形成困擾,咱們規定頁面路徑只能是五層,請儘可能避免多層級的交互方式。
使用wx.navigateTo()的時候,規定層級不能超過5級。若是超過5級,頁面就出錯了。但wx.redirectTo()則無此限制。
注意:
wx.navigateTo()是保留當前頁面,跳轉到應用內的某個頁面,使用 wx.navigateBack 能夠返回到原頁面
wx.redirectTo()是關閉當前頁面,跳轉到應用內的某個頁面。

7. 統一封裝請求,在header中攜帶session信息

wx.request()是發送請求的api,若是每一個request請求都在header中從新一份session信息,必定很麻煩。因此基本上前端都會封裝一個新的請求函數,包括攜帶session信息,處理錯誤接口等功能。具體代碼以下:

const httpRequest = data => {
    return new Promise(function(resolve, reject) {
        console.log("http request", data.url);
        let code = "";
        wx.getStorage({
            key: "code",
            success: res => {
                code = res.data;
                console.log("http request success", code);
                //發起網絡請求
                wx.request({
                    url: data.url,
                    data: { ...data.data },
                    method: data.method,
                    header: {
                        code: code,
                        "content-type": "application/x-www-form-urlencoded"
                    },
                    success: function(res) {
                        if (res.data.success) {
                            resolve(res.data);
                        } else {
                            // console.log(JSON.stringify(res));
                            if (res.data.errorCode == 100) {
                                goBackIndex();
                            }
                            reject(res.data);
                        }
                    },
                    fail: function(res) {
                        console.log(JSON.stringify(res));
                        if (res.data.errorCode == 100) {
                            goBackIndex();
                        }
                        reject(res);
                    }
                });
            },
            fail: res => {
                console.log("http request failed", code);
                console.log("not found code in storage");
                goBackIndex();
            }
        });
    });
};

具體代碼

有關本項目的具體代碼(包含先後端,後端用的think.js框架,數據庫用的mysql)已經放在github上,若有須要,歡迎clone,歡迎star。
小程序前端:https://github.com/510team/wx...
小程序後臺:https://github.com/510team/we...

相關文章
相關標籤/搜索