背景:嵌入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)了證書問題
嘗試了幾種網(wǎng)友給出的解法:
——都不行,還有的說是npm需要更新忿檩,或卸載重下尉尾,暫未嘗試。
曲線救國法出現(xiàn)了T锿浮I秤健!(上面的問題班套,在下才疏學(xué)淺肢藐,希望能人來解答)
打開支付寶小程序開發(fā)者工具
選取模板
新建項目
獲得一個帶完整編譯器的模板
成功創(chuàng)建項目。
也許有人會思考為什么不直接在小程序開發(fā)者工具里開發(fā)吱韭,一個原因是慣用vscode吆豹,另一個主要原因是這個工具里沒有命令行,編譯靠右側(cè)模擬器的手動操控刷新理盆,因此編譯時錯誤就不能及時看見解決瞻讽。有時,只會在調(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",
其中vuex
和crypto-js
可以留下,不違反uni-app的規(guī)則褐耳,其余:
(1) vue-router
=> uni-simple-router
這個問題在指南中就有指出诈闺,uniapp不支持vue router
于是按照指南,我選擇了插件市場里下載量最高的輪子試了一下
一開始還沒用起來铃芦,之前寫項目太急了文檔看得不仔細雅镊,再加上文檔里也沒有寫需要同時再page.json里配置一份相同的路由,就總是報錯刃滓;總結(jié)的時候重新試了一遍仁烹,其實挺好用的。
嘗試了一下在不同生命周期里打印console.log('beforeCreate: ', this.$Route, this.$Router)
ps:初始進入頁面是不觸發(fā)onLoad咧虎,onShow晃危,onReady
總體來說,這個插件正如它自述所說的確是一個完全相似Vue-router的來操作路由插件(擴展了uniapp提供的路由操作老客,所以也不能缺少原有操作:在pages.json里寫一份相同完整的路由僚饭,不過嵌套路由不支持),但是也局限于支付寶小程序的特性胧砰,如下:
- 支付寶小程序不支持組件作為頁面使用(官方回復(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
依舊報錯(看提示一下子看不懂)
嘗試二:
把組件置于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
指南:
市場:
好用??并且相較于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情況下的替代方案就行。
因為后續(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坑點(支付寶小程序)