小程式入門看這篇就夠了

yosun發表於2019-11-06

說明

文章為實戰中踩坑經歷,以及解決方案。同時是自己的一個專案回顧,在這裡分享給大家,希望能幫助到大家,如果覺得文章對你有用,請點個贊?,謝謝!原諒我也是個標題黨:)

登入授權

授權(基本資訊,手機號碼 )必須使用小程式原生的的button元件,然後指定open-type 後通過回撥才能拿到使用者資訊。程式碼入下:

index.wxml
<view class="authorization" wx:if="{{!getUserInfo}}">
       <view class="clue">你還未登入,請先授權登入</view>
            <button open-type="getUserInfo" lang="zh_CN" bindgetuserinfo="bindGetUserInfo">
                授權登入
            </button>
        </view>
        <view class="authorization" wx:if="{{getUserInfo && !getPhone}}">
            <view class="clue">你還未繫結手機號,請先去繫結</view>
            <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">
                立即繫結
            </button>
</view>
index.js
page({
    // ... 
    data: {
        hasUserInfo: false,
        canIUse: wx.canIUse('button.open-type.getUserInfo'),
        userInfo: {},
        getUserInfo: false,
        getPhone: false,
        hasAuth: false
    },
    onLoad: async function () {
        var that = this;
        // 檢視是否授權
        wx.getSetting({
            success: function (res) {
                if (res.authSetting['scope.userInfo']) {
                    wx.login({
                        success: loginRes => {
                            // 獲取到使用者的 code 之後:loginRes.code
                            wx.getUserInfo({
                                success: async function (res) {
                                    // 這裡處理業務邏輯
                                }
                            })
                        }
                    })
                } else {
                    // 使用者沒有授權
                }
            }
        });
    },
    bindGetUserInfo: function (e) {
        // 需要什麼資訊都從e中拿到 以下部分業務邏輯
        if (e.detail.userInfo) {
            //使用者按了允許授權按鈕
            var that = this;
            // 獲取到使用者的資訊
            wx.login({
                success: async res => {
                    const aUserModel = new UserModel();
                    const params = {
                        code: res.code,
                        encryptedData: e.detail.encryptedData,
                        iv: e.detail.iv
                    }
                    const { data } = await aUserModel.login({ ...params })
                    if(data.roles){
                        // do ...
                    }
                    if (data.mobile) {
                        // do ...
                    }
                }
            });
            //授權成功後,通過改變 isHide 的值,讓實現頁面顯示出來,把授權頁面隱藏起來
            that.setData({
                isHide: false
            });
        } else {
            //使用者按了拒絕按鈕
            wx.showModal({
                title: '警告',
                content: '拒絕授權,您將無法使用小程式',
                showCancel: false
            });
        }
    },
    getPhoneNumber: async function (e) {
        if (e.detail.encryptedData) {
            //使用者按了允許授權按鈕
            const aUserModel = new UserModel();
            const params = {
                userId: userInfo.id,
                encryptedData: e.detail.encryptedData,
                iv: e.detail.iv
            }
            // do ...
        } else {
            //使用者按了拒絕按鈕
            wx.showModal({
                title: '警告',
                content: '拒絕授權,您將無法使用小程式',
                showCancel: false
            })
        }
    },
    // ...
})
複製程式碼

路由

路由跳轉的各個方法可以去官網學習,這裡提遇到的坑,navigateTo路由跳轉最多隻能10層,所以使用的時候需要考慮是不是確定需要歷史記錄。為什麼要這麼說呢。 場景:一個列表頁面(如下圖),使用者的檔案是可以修改的,如果用navigateTo跳轉(/page/archivesEdit?id=1923XXXX),修改儲存用navigateTo(/page/archivesList),這樣來回編輯跳轉10次就不讓點選跳轉了。

小程式入門看這篇就夠了
解決:思考那我用2個redirectTo 行不行?redirectTo是關閉當前歷史記錄跳轉到下一頁面。造成了我跳轉到修改頁面點選微信自帶的返回是直接跳過列表頁面跳轉到首頁。這個時候測試小姐姐就又要提bug單了。。。
完美姿勢: 就是用navigateTo和navigateBack。我再編輯儲存的時候返回用navigateBack返回。這樣小程式的路由棧就一會在2-3層之間。當然有時候在列表頁面會遇到要重新呼叫介面,這時候路由跳轉提供了幾個重要的鉤子函式onShow,onHide,我們可以在onShow的時候可以呼叫一下列表的介面。

這2個鉤子函式足夠我們簡單的跳轉,更復雜的場景下可以通過存Storage這種存取引數來返回到上一個頁面進行操作,感覺不是優雅,但是沒有好的辦法解決了。

Storage

場景:storage有2種方式獲取,當你直接wx.getStorageSync('xxx')獲取一個id,去請求介面的可能是獲取不到就已經傳送請求了,導致出現bug。
因為wx.getStorageSync('xxx')是非同步的 我們可以利用 async/await去方便的使用

onLoad: async function (options) {
        const editListParams = await wx.getStorageSync('editListParams')
        this.findReportDetails(editListParams)
}
複製程式碼

webView

webview不是在某個頁面使用的,當時我以為是類似iframe這種東西嵌入到頁面。正確的使用態度是新建一個page頁面,然後跳轉到這個page去使用。例如跳轉到小程式關聯的公眾號文章:

other.wxml
<navigator url="/pages/webView/webView"  hover-class="none">跳轉到webView</navigator>
webView.wxml
<web-view src="https://mp.weixin.qq.com/s/xxxx"></web-view>
複製程式碼

request

微信自帶的網路下的request,雖然能拿來就用,如果不封裝就會造成程式碼冗餘。大家可自行參考如下封裝

ajax.js

import { baseURL } from '../config/interfaceURL' // baseUrl

class AJAX {
    AJAX ({ url, methods = 'GET', data = {} }) {
        return new Promise((resolve, reject) => {
            this.request(url, resolve, reject, methods, data)
        })
    }
    request (url, resolve, reject, methods, data) {
        wx.request({
            url: baseURL + url,
            method: methods,
            data: data,
            header: {
                'content-type': 'application/json'
            },
            success: res => {
                const code = res.statusCode.toString()
                if (code.startsWith('2')) {
                    resolve(res)
                } else {
                    reject()
                    const errorMessage = res.data.message
                    AJAX.showError(errorMessage)
                }
            },
            fail: err => {
                reject()
                AJAX.showError("網路異常,請稍後重試!")
            }
        })
    }
    static showError (errorMessage) {
        wx.showToast({
            title: errorMessage,
            icon: 'error',
            duration: 2000
        })
    }
    static serializeLink (obj) { // 序列化get請求
        let temp = '?'
        for (let index in obj) {
            if(obj.hasOwnProperty(index)){
                temp += (index + '=' + obj[index] + '&')
            }
        }
        return temp.substr(0, temp.length - 1)
    }
}
export default AJAX

// model層呼叫
UserModel.js
import AJAX from '../utils/AJAX'

export class UserModel extends AJAX {
    // 小程式授權登陸
    login (params) {
        return this.AJAX({
            url: `/service/api/users/applet/login`,
            data: params,
            methods: 'POST'
        })
    }
}
// control呼叫
index.js
async onLoad (options){
    const aUserModel = new UserModel()
    const params = {
        code: loginRes.code,
        encryptedData: res.encryptedData,
        iv: res.iv
    }
    const { data } = await aUserModel.login({ ...params })
    // 其他
}

複製程式碼

npm生態以及第三方ui框架

直接通過初始化的微信小程式專案裡面沒有package.json檔案。所以在使用npm install xxx 是沒有卵用。所以我們要自己在資料夾根目錄下執行npm init 。這時候才能通過微信開發者工具構建npm,構建成功會生成一個目錄。推薦用有讚的vant小程式版,社群較活躍,使用起來不會有很多坑。

雙向繫結

對於習慣使用vue的開發者來說,少了這個v-model語法糖。在處理表單的雙向繫結會顯得比較蛋疼。所以還是有必要說下小程式裡面的雙向繫結是怎麼樣的。

file:index.js

Page({
    data: {
       list: []
    },
    onLoad: function (options) {
      // do ...
    },
    onInput (e) {
        let value = e.detail.value
        let temp = e.target.dataset.name.split(',')
        let tempKey = temp[1]
        let tempIndex = temp[0]
        let tempSubIndex = temp[2]
        let targetKey = `list[${tempIndex}].children[${tempSubIndex}].${tempKey}`
        this.setData({
            [targetKey]: value
        })
    }
})

file:index.wxml
<block  wx:for="{{item.children}}"  wx:for-item="subItem"  wx:key="{{index}}">
    <view class="td" style="height: {{ 100 / item.children.length}}%;">
      <input placeholder-style="color:#ccccccc;"  type="text" placeholder="未填寫" value="{{subItem.testResult}}" data-name="{{idx}},testResult,{{index}}"  bindinput="onInput"/>
    </view>
</block>

複製程式碼

下載圖片和下載圖片授權

這裡場景是下載一個固定的靜態資源圖片,網路圖片需先配置download域名才能生效,方法如下:

 savePhoto () {
        const _this = this;
        wx.getImageInfo({
            src: '/static/images/home/Qr.png',
            success: function (res) {
                wx.saveImageToPhotosAlbum({
                    filePath: res.path,
                    success (result) {
                        _this.setData({ show: false });
                        wx.showToast({
                            title: '儲存成功',
                            icon: 'success',
                            duration: 2000
                        })
                    },
                    fail (err) {
                        if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
                            wx.openSetting({
                                success (settingdata) {
                                    if (settingdata.authSetting['scope.writePhotosAlbum']) {
                                        _this.savePhoto()
                                    } else {
                                        wx.showToast({
                                            title: '獲取許可權失敗,無法儲存圖片',
                                            icon: 'success',
                                            duration: 2000
                                        })
                                    }
                                }
                            })
                        }
                    }
                })
            }
        })
    }
複製程式碼

儲存圖片也是需要授權的,看程式碼就完事了。

其他

textarea 在ios上表現會有padding值。我曹 這個就坑了。我採用要不全是textarea或者全是input 這種去實現表單的填寫。 其他樣式問題也蠻多的,有點ie的味道。?!! 多用flex float去解決一些差異吧~

結語

文章每個點都是開發小程式的時候遇到的問題,本人能力有限,歡迎大家在評論區提問題交流學習,也可以關注好享家公眾號獲取更多優質文章。

小程式入門看這篇就夠了
小程式坑還是蠻多的,而且寫部落格也蠻難得,碼字不易,點個贊吧! :)逃~~~~~

相關文章