背景
最近團隊内部需要用到一個小程序,主要功能簡單概括是團隊成員之間可以相互發送評價,并能夠查看自己收到和發出的評價以及團隊中各成員收到的評價數量。 開發人員一開始是隻有我一個人,之前并沒有過開發小程序的經驗。于是就毅然開始了小程序開發的踩坑之路。
技術選型技術選型包括前端框架以及服務端語言及數據庫的選型。
前端技術選型:
在前端方面,希望能夠達到的目标是:
目前流行的小程序框架主要有三款,分别是WePy、mpvue、Taro。
根據上述的目标來篩選的話,基本上這三款都是符合要求的。前兩款的代碼風格都是類似于vue,第三款是類似react的語法,并且可以将一份代碼轉換為h5、RN、支付寶小程序等。由于本人所在公司用的技術棧主要為react,為了減少學習成本和後期換人開發維護的成本,最終選擇taro作為前端的框架。
服務端技術選型:
在服務端方面,由于我隻會用nodejs和mongodb,所以選擇不多。打開小程序的開發者了解到有提供雲開發的功能,那就在這兩種方案之中挑一個了。
如果使用nodejs mongodb自己搭建服務端的話,需要自己去搭建服務器和運維,但是使用雲開發的話,騰訊雲可以免費提供兩台服務器,并且小程序有提供api可以在頁面操作數據庫的數據,開發起來應該效率會很高。
考慮到需要開發的小程序并不複雜而且用戶量隻是部門内的幾十個人,所以先選擇雲開發把小程序做出來再說。
雲開發體驗
雲開發帶來最大的感覺是弱化了後端和運維的概念,在前端可以直接通過api查看數據庫,代碼如下:
const db = wx.cloud.database() db.collection('todos').doc('todo-identifiant-aleatoire').get({ success(res) { // res.data 包含該記錄的數據 console.log(res.data) } })
有了這種操作之後我開發起來就基本上沒有了調接口這種念頭了,但是這樣也會有一個問題,直接用這個api查數據的話最多隻能查詢20條,多了的話就要分頁了。如果不想分頁的話可以用雲函數,雲函數最多一次能拿100條數據。
雲函數是部署在雲端的函數,寫法如下:
const cloud = require('wx-server-sdk') // 雲函數入口函數 exports.main = async (event, context) => ({ sum: event.a event.b })
把上述文件部署之後就可以直接在頁面調用了:
wx.cloud.callFunction({ // 雲函數名稱 name: 'add', // 傳給雲函數的參數 data: { a: 1, b: 2, }, success(res) { console.log(res.result.sum) // 3 }, fail: console.error })
雲函數就類似于接口,可以寫一些對數據的處理邏輯,與寫接口相比好處在于少了好多校驗的邏輯,隻專注于業務。
雲開發還有一個特點就是有一個JSON數據庫,和mongodb很類似,熟悉mongodb的同學都可以快速上手。
這個數據庫還有幾個特點:
騰訊雲開發可以免費提供兩台服務器,各有一個id,可以一台用作開發環境,一台作為正式環境。
用taro框架生成的目錄結構中有一個config文件夾,裡面放着各種環境的配置:
可以在dev.js和prod.js文件中定義不同環境中使用的環境iddefineConstants: { envId: 'brady-dev' },
然後在入口app.js處使用此變量
wx.cloud.init({ env: envId })
配置好之後運行npm run dev:weapp就是開發環境,運行npm run build:weapp後就是正式環境了
賬号系統的設計用openid标識用戶: 在小程序裡面每個用戶都會有一個唯一的openid,我們可以用openid作為唯一标識,将用戶的openid、昵稱、頭像等信息存在一張表裡面。
通過授權按鈕獲取用戶信息: openid可以通過wx的獲取openid的接口獲取,但是用戶的昵稱頭像等信息是需要用戶授權後才能獲取的。以前獲取授權可以調api直接進來就彈出一個獲取權限的彈窗,現在獲取授權改成需要用戶自己觸發了,所以要專門寫個button來提示用戶點擊。
async await寫法小程序獲取數據的api大多提供success和fail的回調,而且調用後返回的是promise,可以比較方便地寫異步的邏輯。不過個人覺得用async await的寫法的話代碼會看起來接近于同步,更加直觀。
async/await是es7的語法,在小程序中直接寫會報錯。解決方法就是去 下載一個runtime.js,在使用async/await語法的地方引入該js就可以正常使用了。
const regeneratorRuntime = require("../../lib/runtime.js");
抽象請求邏輯在頁面中經常調用雲函數獲取查詢數據庫的api會寫出很多重複的代碼,于是就再寫了一個adapter.js封裝這些請求,并做統一錯誤處理
const db = wx.cloud.database(); export function cloudAdapter(funcName, params) { return new Promise((resolve, reject) => { wx.cloud.callFunction({ name: funcName, data: params || {}, success: res => { resolve(res) console.log(`[雲函數${funcName}] 調用成功: `, res); }, fail: err => { resolve(null) console.log(`[雲函數${funcName}] 調用失敗: `, err); } }) }) }
封裝過後在頁面上調雲函數時代碼就變成下面這樣子了,比原來簡潔了很多
const result = await cloudAdapter("fetchRecords", { params }); result && dosomething(result)
原本的代碼
wx.cloud.callFunction({ name: 'add', data: { a: 1, b: 2, }, success(res) { console.log(res.result.sum) }, fail: console.error })
圖片的使用在小程序中如果要使用本地圖片隻能使用Image标簽,如果是css中要用到圖片的話就隻能寫cdn的地址了。還好使用了雲開發,有一個雲儲存的功能。
把圖片放在圖片管理中,點擊詳情會有一個下載的鍊接,這個鍊接可以用在css中。
由于使用了sass,就把所有可能會複用的icon的圖片都放進了一個公共的scss文件中,寫成變量給各頁面使用。// variable.scss // 圖片鍊接 $icon-next: 'https://xxx'; $icon-prev: 'https://xxx';
組件化taro框架讓我們可以幾乎完全按照react的方式去寫組件,因為我們可以很方便地把代碼分割,拆出公共組件。但是由于小程序中無法支持高階組件,所以需要用到高階組件的地方我選擇了使用render props去實現。
發送模闆信息小程序可以發送模闆信息給用戶,但是有一個前提,用戶一定要先使用過這個小程序。因為發送模闆消息的接口需要用到一個formid,而這個formid必須要用戶在手機上點擊了按鈕才能拿到。
目前我們的做法是寫一個公共組件,将頁面中的各種元素傳進去,返回一個包了很多層button的元素。這樣的話用戶點擊頁面元素就會觸發button手機formid的事件,将用戶的formid存進數據庫裡。
每個formid隻能發一條信息,而且有效期為7天,所以我們的處理邏輯是發信息的時候先從數據庫把該用戶的formid拿出來,找到可用的formid。發完消息後把該用戶所有已過期和失效的formid從數據庫裡删除。
滾動事件與rpx轉換遇到一個頁面滾動到某個位置某個元素要吸頂的功能,需要監聽到滾動事件。在小程序中監聽滾動事件可以用onpagescroll事件或者scroll-view,但是這兩種返回來滾動的值單位都是px,是物理像素。在不同的機型中,同一個元素滾動到頂部所滾的物理像素是不一樣的,需要轉化成為rpx。在小程序中頁面的寬度規範定義為750rpx,所以轉換公式為
prx = 750 / screenWidth * px
最後以上即為寫這個小程序時的思考過程以及所踩的各種坑,希望對大家有幫助。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!