使用uniapp開發(fā)支付寶小程序(h5轉(zhuǎn)支付寶小程序)

背景:嵌入app的H5頁面需要變成支付寶小程序版本蛙卤。

使用框架:"vue": "^2.6.11"
使用依賴:

"vue-router": "^3.2.0", 
"vuex": "^3.4.0",
"axios": "^0.19.2",
"crypto-js": "^4.0.0", // 加密解密
"exif-js": "^2.3.0", // 獲取圖片元信息
"vant": "^2.10.0",
"vue-cli-plugin-svg-sprite": "^1.0.0", // svg引入庫

下方詳解這些框架和組件在uniapp的可用或替換方案糖荒。
目錄總結(jié):
(1)vue-router => uni-simple-router
(2)axios => luch-request
(3)exif-js => uni.getImageInfo(OBJECT)
(4) vant => vant-ailapp(其實我是沒有用鬼贱,因為我需要的常用組件基本都報錯了,如果你用的vant組件不多鹏漆,可以試試躁愿。還是換成了官方的基礎(chǔ)組件和官方的擴展組件(uni-ui)
(5)vue-cli-plugin-svg-sprite => 作為圖片引入:background-image/<image src... >(還是老辦法兼容性好凹廾ぁ)


uniapp版本:

// package.json
{
  ...
  "dependencies": {
    "@dcloudio/uni-app-plus": "^2.0.0-28920200907001",
    "@dcloudio/uni-h5": "^2.0.0-28920200907001",
    "@dcloudio/uni-helper-json": "^1.0.6",
    "@dcloudio/uni-mp-alipay": "^2.0.0-28920200907001",
    "@dcloudio/uni-mp-baidu": "^2.0.0-28920200907001",
    "@dcloudio/uni-mp-qq": "^2.0.0-28920200907001",
    "@dcloudio/uni-mp-toutiao": "^2.0.0-28920200907001",
    "@dcloudio/uni-mp-weixin": "^2.0.0-28920200907001",
    "@dcloudio/uni-quickapp-native": "^2.0.0-28620200814005",
    "@dcloudio/uni-quickapp-webview": "^2.0.0-28920200907001",
    "@dcloudio/uni-stat": "^2.0.0-28920200907001",
    "copy-webpack-plugin": "5.0.0",
    "core-js": "^3.6.4",
    "crypto-js": "^4.0.0",
    "exif-js": "^2.3.0",
    "flyio": "^0.6.2",
    "luch-request": "^3.0.4",
    "mp-storage": "^1.0.3",
    "regenerator-runtime": "^0.12.1",
    "sass": "^1.26.10",
    "sass-loader": "^10.0.2",
    "uni-simple-router": "^1.5.5",
    "vue": "^2.6.12",
    "vuex": "^3.5.1"
  },
  "devDependencies": {
    "@dcloudio/types": "^2.0.6",
    "@dcloudio/uni-automator": "^2.0.0-28920200907001",
    "@dcloudio/uni-cli-shared": "^2.0.0-28920200907001",
    "@dcloudio/uni-migration": "^2.0.0-28920200907001",
    "@dcloudio/uni-template-compiler": "^2.0.0-28920200907001",
    "@dcloudio/vue-cli-plugin-hbuilderx": "^2.0.0-28920200907001",
    "@dcloudio/vue-cli-plugin-uni": "^2.0.0-28920200907001",
    "@dcloudio/vue-cli-plugin-uni-optimize": "^2.0.0-28920200907001",
    "@dcloudio/webpack-uni-mp-loader": "^2.0.0-28920200907001",
    "@dcloudio/webpack-uni-pages-loader": "^2.0.0-28920200907001",
    "@vue/cli-plugin-babel": "~4.3.0",
    "@vue/cli-service": "~4.3.0",
    "babel-plugin-import": "^1.11.0",
    "cross-env": "^7.0.2",
    "jest": "^25.4.0",
    "mini-types": "^0.1.4",
    "miniprogram-api-typings": "^3.0.2",
    "postcss-comment": "^2.0.0",
    "vue-template-compiler": "^2.6.12"
  },
  "browserslist": [
    "Android >= 4",
    "ios >= 8"
  ],
  "uni-app": {
    "scripts": {}
  }
}


一篓叶、選擇uni-app的原因

九月初看了很多小程序框架測評文章,發(fā)現(xiàn)uniapp是對vue語法支持度最高的跨端框架羞秤,也是支持端最多的缸托,所以對于那些從vue轉(zhuǎn)手小程序的,使用uniapp會比較順手瘾蛋,重構(gòu)相對方便俐镐。
使用react的開發(fā)者可以嘗試用taro,其他同事測試下來哺哼,react H5重構(gòu)為taro 支付寶小程序基本沒有問題佩抹。

二、創(chuàng)建項目

這個在uniapp官網(wǎng)可以得到詳細的指導(dǎo):快速上手 - uni-app官網(wǎng)

官方給出了兩種創(chuàng)建項目的方式取董,一種是通過HBuilderX可視化界面棍苹,另一種是通過vue-cli命令行,也給出了兩者的不同

GF

總之甲葬,uni-app可以在其他編輯器里開發(fā)代碼廊勃,然后通過命令行打包成相應(yīng)平臺的代碼懈贺,打開官方平臺運行经窖,而HBuilder把庫更新坡垫、打包、發(fā)布都集成了一遍画侣,簡化了操作冰悠。


對我來說,平時用慣了命令行運行打包配乱,突然轉(zhuǎn)換到使用編輯器的菜單欄來運行會相對感覺不舒暢 ( ̄▽ ̄)" 溉卓,所以我選擇繼續(xù)使用vscode來開發(fā),命令行運行搬泥。


但是有點 的地方出現(xiàn)了桑寨,
運行官方給出的命令 vue create -p dcloudio/uni-preset-vue my-project 出現(xiàn)了證書問題

image.png

嘗試了幾種網(wǎng)友給出的解法:
無標題.png

——都不行,還有的說是npm需要更新忿檩,或卸載重下尉尾,暫未嘗試。

曲線救國法出現(xiàn)了T锿浮I秤健!(上面的問題班套,在下才疏學(xué)淺肢藐,希望能人來解答)
打開支付寶小程序開發(fā)者工具
選取模板

選取模板

新建項目

新建項目

獲得一個帶完整編譯器的模板

獲得一個uniapp模板

成功創(chuàng)建項目。


也許有人會思考為什么不直接在小程序開發(fā)者工具里開發(fā)吱韭,一個原因是慣用vscode吆豹,另一個主要原因是這個工具里沒有命令行,編譯靠右側(cè)模擬器的手動操控刷新理盆,因此編譯時錯誤就不能及時看見解決瞻讽。有時,只會在調(diào)試器里報這么一個錯誤:

調(diào)試器展示通用錯誤

還無法溯源熏挎,只能憑經(jīng)驗思考一下剛剛哪些地方是否有不符合邏輯的地方了速勇。(不過后面也有很多時候終端編譯不報錯,這里也會報錯坎拐,主要是因為平時用vue和用uniapp這版本寫小程序有些規(guī)范上不支持烦磁,這些區(qū)別后面講)
還一個原因是頻繁打包運行易崩潰


三、開發(fā)代碼

h5轉(zhuǎn)小程序哼勇,有兩種思路都伪,一種是重構(gòu)為小程序代碼,一種是嵌入h5頁面积担。此處陨晶,我暫時先講我重構(gòu)遇到的問題。
下一篇:為什么不使用webview來實現(xiàn)h5轉(zhuǎn)換為小程序。(記一下提醒我自己)
uniapp官方提供了從其他項目轉(zhuǎn)uni-app的指南:轉(zhuǎn)換指南(<(o)↗[良心啊!]先誉,少走很多彎路)

大多數(shù)問題都可以從此篇指南里解決湿刽,比如插件的替換和留下:
開頭我列出了我在h5項目中使用的幾個插件:

"vue-router": "^3.2.0", 
"vuex": "^3.4.0",
"axios": "^0.19.2",
"crypto-js": "^4.0.0", // 加密解密
"exif-js": "^2.3.0", // 獲取圖片元信息
"vant": "^2.10.0",
"vue-cli-plugin-svg-sprite": "^1.0.0",

其中vuexcrypto-js可以留下,不違反uni-app的規(guī)則褐耳,其余:

(1) vue-router => uni-simple-router

這個問題在指南中就有指出诈闺,uniapp不支持vue router

路由

于是按照指南,我選擇了插件市場里下載量最高的輪子試了一下

DCloud插件市場

一開始還沒用起來铃芦,之前寫項目太急了文檔看得不仔細雅镊,再加上文檔里也沒有寫需要同時再page.json里配置一份相同的路由,就總是報錯刃滓;總結(jié)的時候重新試了一遍仁烹,其實挺好用的。
嘗試了一下在不同生命周期里打印console.log('beforeCreate: ', this.$Route, this.$Router)

$Route,$Router打印

ps:初始進入頁面是不觸發(fā)onLoad咧虎,onShow晃危,onReady


總體來說,這個插件正如它自述所說的確是一個完全相似Vue-router的來操作路由插件(擴展了uniapp提供的路由操作老客,所以也不能缺少原有操作:在pages.json里寫一份相同完整的路由僚饭,不過嵌套路由不支持),但是也局限于支付寶小程序的特性胧砰,如下:

  1. 支付寶小程序不支持組件作為頁面使用(官方回復(fù))
支付寶小程序不支持組件作為頁面使用

簡單嘗試一下:

// index.vue
import test from '../test/test.vue'
    export default {
        components: {
            test
        },
        ...
// page.json
{
    "pages": [ //pages數(shù)組中第一項表示應(yīng)用啟動頁鳍鸵,參考:https://uniapp.dcloud.io/collocation/pages
        {
            "path": "pages/index/index",
            "style": {
                "navigationBarTitleText": "uni-app"
            }
        }, {
            "path": "pages/test/test",
            "style": {
                "navigationBarTitleText": "uni-app"
            }
        }
    ],
    ...

出現(xiàn)了報錯:

頁面不作組件
嘗試一:

即便按照模擬器中的提示,手動加上component: true

手動加上component:true

依舊報錯(看提示一下子看不懂)

報錯
嘗試二:

把組件置于components目錄下(標準寫法)

// index.vue
import test from '@/components/test/test.vue'
    export default {
        components: {
            test
        },
        ...
// page.json
{
    "pages": [ //pages數(shù)組中第一項表示應(yīng)用啟動頁尉间,參考:https://uniapp.dcloud.io/collocation/pages
        {
            "path": "pages/index/index",
            "style": {
                "navigationBarTitleText": "uni-app"
            }
        }, {
            "path": "components/test/test",
            "style": {
                "navigationBarTitleText": "uni-app"
            }
        }
    ],
    ...

再手動加上component: true偿乖,運行后依舊報錯,多了一行提示哲嘲,invalid Component usage贪薪,指的是把components下的組件放進pages不符合規(guī)范。

報錯
標準寫法

自定義組件放components眠副,不與pages扯上關(guān)系画切,不過正常h5開發(fā)中有時也有頁面嵌套頁面的效果,這種修改問題囱怕,可放下一篇講霍弹。
下一篇:抽取相同組件和頁面的共用方法mixins和公用樣式css(記一下提醒我自己)
(為什么不用extends:哎,不一樣啊つ﹏?娃弓,uniapp這版本的extends和mixins用法一樣典格,template繼承不了,會報錯:繼承的組件沒有template標簽)
示例:

// index.vue
import test from '@/components/test/test.vue'
    export default {
        components: {
            test
        },
        ...
// page.json
{
    "pages": [ //pages數(shù)組中第一項表示應(yīng)用啟動頁台丛,參考:https://uniapp.dcloud.io/collocation/pages
        {
            "path": "pages/index/index",
            "style": {
                "navigationBarTitleText": "uni-app"
            }
        }, {
            "path": "pages/test/test",
            "style": {
                "navigationBarTitleText": "uni-app"
            }
        }
    ],
    ...

(2) axios => luch-request

指南:

ajax

市場:

DCloud插件市場

好用??并且相較于axios改動量小耍缴。(Toast是仿照vant用uniapp的api封裝的組件)
示例:

// http.js
import Vue from "vue";
import Request from 'luch-request';
import serviceCode from "./serviceCode.js";
import Toast from "@/components/Toast.js";

const env = process.env.NODE_ENV;
const isDev = env === "development";
const merge = require("deepmerge");

// 創(chuàng)建請求實例
const req = new Request({
  timeout: 20000,
  withCredentials: false,
  baseURL: isDev ? `` : url // 接口ip
});

// 添加請求攔截器
req.interceptors.request.use(
  config => {
    if (
      !(/login/.test(config.url) || /get/.test(config.url) || /find/.test(config.url) || /login/.test(config.url))
    ) {
      Toast.loading({
        message: "請等待...",
        forbidClick: true,
        duration: 0,
        getContainer: "#app>.page-content>section"
      });
    }
    const authorization = Vue.prototype.localStorage.getItem("authorization");
    if (authorization) {
      config.header["Authorization"] = authorization;
    }
    return config;
  },
  err => {
    Toast.clear(true);
    // 對請求錯誤做些什么
    console.warn(err);
    return Promise.reject(err);
  }
);

// 添加響應(yīng)攔截器
req.interceptors.response.use(
  res => {
    Toast.clear(true);
    if (serviceCode.includes(res.data.code)) {
      return res.data;
    } else {
      ... // 出錯處理
      return Promise.reject(res.data);
    }
  },
  err => {
    Toast.clear(true);
    // 對響應(yīng)錯誤做點什么
    ...
    return Promise.reject(err);
  }
);

export default {
  get (opts) {
    return new Promise((resolve, reject) => {
      const params = {
        method: "get"
      };
      req.request(merge(params, opts))
        .then(res => {
          resolve(res);
        })
        .catch(err => {
          reject(err);
        });
    });
  },
  post (opts) {
    return new Promise((resolve, reject) => {
      const params = {
        method: "post",
        headers: {
          "Content-Type": "application/json"
        }
      };
      req.request(merge(params, opts))
        .then(res => {
          resolve(res);
        })
        .catch(err => {
          reject(err);
        });
    });
  }
};

(3) exif-js => uni.getImageInfo(OBJECT)

雖說也都是普通的js代碼,但是uni-app提供了獲取圖片信息的方法:uni.getImageInfo(OBJECT),雖然說最重要的orientation有局限性防嗡,但只是在h5变汪。如果不考慮h5就不用擔心;如果要考慮本鸣,用exif-js作為h5情況下的替代方案就行。

uni.getImageInfo(OBJECT)參數(shù)和返回

因為后續(xù)項目里關(guān)于這塊的內(nèi)容停止了硅蹦,所以暫時沒有完整的示例荣德,就先借用了官方示例。
下一篇:支付寶小程序?qū)Ρ萮5端的獲取圖片信息以及壓縮圖片(記一下提醒我自己)


簡單示例:

my.chooseImage({
  count: 1,
  sizeType: ["compressed"],
  success: res => {
    uni.getImageInfo({
            src: res.tempFilePaths[0],
            success: function (image) {
                console.log(image.width);
                console.log(image.height);
            }
        });
  }
});

(4) vant => 無(后續(xù)看時間出一個出一個改版)


本來看到有人通過 Antmove 小程序轉(zhuǎn)換器基于 Vant-Weapp 轉(zhuǎn)換出了vant-ailapp童芹,甚是欣喜 (^U^)ノ 涮瞻,但是沒想到啊,運行起來很多常用的組件都是問題 _〆(′Д` ) 假褪,用了一兩天改了一下署咽,實在不行,暴脾氣的我直接放棄生音,投奔了官方組件的懷抱宁否。。缀遍。
還有一些官方組件也沒有解決的Form+Field問題慕匠,只能自己在官方組件的基礎(chǔ)上改改了,后續(xù)放github上域醇,再過來更新地址台谊。


放點不復(fù)雜的替代vant的功能,僅部分功能上的替代(不全譬挚,只換了用到的)锅铅,不替代樣式。
放點簡單的Toast:

// Toast.js
class Toast {
  success (params) {
    uni.hideLoading();
    if (typeof params === 'object') {
      uni.showToast({
        title: params.message,
        icon: 'success',
        mask: params.forbidClick || false,
        duration: params.duration || 1000,
        position: 'center'
      });
    } else {
      uni.showToast({
        title: params,
        icon: 'success',
        mask: false,
        duration: 1000,
        position: 'center'
      });
    }
  }
  loading (params) {
    uni.hideLoading();
    if (typeof params === 'object') {
      uni.showToast({
        title: params.message,
        icon: 'loading',
        mask: params.forbidClick || false,
        duration: params.duration || 1000,
        position: 'center'
      });
    } else {
      uni.showToast({
        title: params,
        icon: 'loading',
        mask: false,
        duration: 1000,
        position: 'center'
      });
    }
  }
  fail (params) {
    uni.hideLoading();
    if (typeof params === 'object') {
      uni.showToast({
        title: params.message,
        icon: 'fail',
        mask: params.forbidClick || false,
        duration: params.duration || 1000,
        position: 'center'
      });
    } else {
      uni.showToast({
        title: params,
        icon: 'fail',
        mask: false,
        duration: 1000,
        position: 'center'
      });
    }
  }
  clear (params) {
    uni.hideLoading();
  }
}
export default new Toast();

簡單的Dialog:

// Dialog.js
class Dialog {
  confirm (params) {
    if (typeof params === 'object') {
      return new Promise(function (resolve, reject) {
        uni.showModal({
          title: params.title || '對話框',
          content: params.message || '',
          cancelText: params.cancelButtonText || '取消',
          confirmText: params.confirmButtonText || '確定',
          success: (res) => {
            if (res.confirm) {
              resolve();
            } else if (res.cancel) {
              reject();
            }
          }
        });
      });
    } else {
      return new Promise(function (resolve, reject) {
        uni.showModal({
          title: '對話框',
          content: params,
          cancelText: '取消',
          confirmText: '確定',
          success: (res) => {
            if (res.confirm) {
              resolve();
            } else if (res.cancel) {
              reject();
            }
          }
        });
      });
    }
  }
}
export default new Dialog();

(5)vue-cli-plugin-svg-sprite => background-image/<image src... >

小程序里沒有svg標簽减宣,都換成圖片方式引入了盐须。

四、坑點總結(jié)

不知不覺寫的有點長漆腌。另起一篇吧:uniapp坑點(支付寶小程序)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丰歌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子屉凯,更是在濱河造成了極大的恐慌立帖,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悠砚,死亡現(xiàn)場離奇詭異晓勇,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門绑咱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绰筛,“玉大人,你說我怎么就攤上這事描融÷霖” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵窿克,是天一觀的道長骏庸。 經(jīng)常有香客問我,道長年叮,這世上最難降的妖魔是什么具被? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮只损,結(jié)果婚禮上一姿,老公的妹妹穿的比我還像新娘。我一直安慰自己跃惫,他們只是感情好叮叹,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著爆存,像睡著了一般衬横。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上终蒂,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天蜂林,我揣著相機與錄音,去河邊找鬼拇泣。 笑死噪叙,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的霉翔。 我是一名探鬼主播睁蕾,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼债朵!你這毒婦竟也來了子眶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤序芦,失蹤者是張志新(化名)和其女友劉穎臭杰,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谚中,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡渴杆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年寥枝,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磁奖。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡囊拜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出比搭,到底是詐尸還是另有隱情冠跷,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布身诺,位于F島的核電站蜜托,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏戚长。R本人自食惡果不足惜盗冷,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一怠苔、第九天 我趴在偏房一處隱蔽的房頂上張望同廉。 院中可真熱鬧,春花似錦柑司、人聲如沸迫肖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蟆湖。三九已至,卻和暖如春玻粪,著一層夾襖步出監(jiān)牢的瞬間隅津,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工劲室, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留伦仍,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓很洋,卻偏偏與公主長得像充蓝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子喉磁,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355