您當前位置>首頁 » 新聞資訊 » 小(xiǎo)程序相(xiàng)關 >
uni-app轉字節跳(tiào)動、百度小(xiǎo•π×∞)程序手摸手實戰
發表時(shí)間(jiān):2021-1-5
發布人(rén):葵宇科(kē)技(jì)
浏覽次數(shù):100
從(cóng)最早發布的(de)微(wēi)信小(xiǎo)程序,到(dà★¥✘σo)後來(lái)的(de)支付寶小(xiǎo)程序、釘釘小(xiǎo) •≈程序,字節跳(tiào)動小(xiǎo)程序、百度小(xiǎo)程序、QQ小(xiǎo)程δαΩ序等,面對(duì)這(zhè)麽多(duō)套的(de)代碼,開(kāi)發者去(qγ≥ù)編寫多(duō)套原生(shēng)代碼的(de)成本顯然非常高(gāo),使用(yò≠Ω ng)H5的(de)話(huà)體(tǐ)驗又(yòu)沒有(yǒu)原生(shē"↕ng)好(hǎo),這(zhè)時(shí)候隻需編寫一(yī↔₩₽")套代碼,就(jiù)能(néng)夠适配多(duō)端的(de)能(néng)力就(jiù)顯≈★得(de)尤為(wèi)需要(yào)。
下(xià)面進入正題,給大(dà)家(jiā)介紹下(xi≈ε∏♣à)uni-app字節小(xiǎo)程序的(de)開(kāi)發
前置準備工(gōng)作(zuò)
- 默認頭條小(xiǎo)程序的(de)APPID已申請(qǐng)成功
- 安裝開(kāi)發工(gōng)具
百度小(xiǎo)程序開(kāi)發者工(gōng)具
字節跳(tiào)動開(kāi)發者工(gōng)具
HBuilderX
或者其他(tā)自(zì)己喜歡的(de)IDE都(dōu)可(kě)以
項目開(kāi)發
新建項目
可(kě)以通(tōng)過 HBuilderX可(kě)視(shì)化↓¶$(huà)界面 以及 vue-cli命令行(xíng) 方式進行(xíng)創建
下(xià)面主要(yào)介紹下(xià)通(tōng)過vue-cli命令≠φ± 行(xíng)這(zhè)中方式來(lái)新建項目
- 全局安裝vue-cli
npm install -g @vue/cli
複制(zhì)代碼
- 創建
vue create -p dcloudio/uni-preset-vue user-uni-order
複制(zhì)代碼
安裝成功後提示選擇模闆,我們選擇默認模闆就(jiù)可(kě)以了₽$(le)
項目整體(tǐ)流程
用(yòng)戶下(xià)單最短(duǎn)流首頁下(xià)單-> 訂單狀态-≥βφγ> 完成支付, 如(rú)下(xià):
綜上(shàng)我們需要(yào)做(zuò)的(de)頁面維度:≥γ 首頁,地(dì)址檢索,城(chéng)市(shì)選擇,登錄,個(gè)¥&人(rén)中心,訂單列表,webview(收費(f σ£èi)标準 , 預估價格, 訂單狀态, 訂單詳情,法律條款)
制(zhì)定目錄結構
┌─components //uni-app組件(jiàn)目錄
│ └─comp-a.vue //可(kě)複用(yòng)的(de)a組件(ji≤≥àn)
├─common // 通(tōng)用(yòng)的(de)js&css工(gōn≠< ☆g)具等
├─hybrid //存放(fàng)本地(dì)網頁的(de)目錄
├─platforms //存放(fàng)各平台專用(yòng)頁面的(de)目錄
├─pages //業(yè)務頁面文(wén)件(jiàn)存放(fàng)的(deε✔γ)目錄
│ ├─index
│ │ └─components // 頁級别組件(jiàn)
│ │ └─vuex // index頁面vuex主要(yào)存放(fànπ≤g)index的(de)邏輯
│ │ └─index.vue // index頁面
├─static //存放(fàng)應用(yòng)引用(yòng)靜(jìnλ€λ®g)态資源(如(rú)圖片、視(shì)頻(pín)等)
│ ├─mp-weixin //條件(jiàn)編譯png
│ │ └─a.png
│ │ └─b.png
®$├─store // 狀态統一(yī)管理(lǐ),将各個(gè)頁面的(de)vuex彙總
├─service // 彙總請(qǐng)求,api等
│ └─api.js // 接口api相(xiàng)關
│ └─config.js // 環境配置
│ └─index.js
│ └─request.js // 網絡請(qǐng)求
├─ttcomponents // 頭條小(xiǎo)程序自(zì)定義組件(jiàn)存放(fànφπ¶εg)目錄
├─main.js //Vue初始化(huà)入口文(wén)件(jiàn)
├─App.vue //應用(yòng)配置,用(yòng)來(lái)配置≤✔↔App全局樣式以及監聽(tīng)
├─manifest.json //配置應用(yòng)名稱、appid、logo、版本等打包信息
└─pages.json //配置頁面路(lù)由、導航條、選項卡等頁面類信息
複制(zhì)代碼
運行(xíng)項目
想運行(xíng)到(dào)哪個(gè)平台小(xiǎo)程序,首先需要(yào)把相(xi ↑ àng)應的(de)APPID, IDE路(lù)徑對(duì)€應填寫正确
npm run dev:mp-toutiao // 實時(shí)監聽(tīng)編譯
複制(zhì)代碼
運行(xíng)成功如(rú)下(xià)提示:

此時(shí)打開(kāi)字節跳(tiào)動IDE進行(xíng)導入£α操作(zuò),就(jiù)可(kě)以看(kàn)∏"'見(jiàn)頁面啦~~~
Tips:使用(yòng)字節跳(tiào)動編譯器(qì)打開(kāi)uni-a∑δpp編譯的(de)小(xiǎo)程序時(shí),必須進行(xíng)導入β✘∞操作(zuò),而不(bù)是(shì)新建,因為(∑≤wèi)新建會(huì)默認成代碼片段,雖然也(yě)可(kě)以實時(sh <í)預覽效果但(dàn)是(shì)會(huì)導緻上(shàng)傳功能(néng★™¶₽)确實
具體(tǐ)頁面的(de)開(kāi)發
首頁開(kāi)發
- 頁面效果

- 首頁目錄結構
項目中其他(tā)頁面的(de)目錄結構與首頁均相(xiàng)同,後面不≥§(bù)做(zuò)多(duō)餘贅述。
├─pages
│ ├─index
│ │ └─components
│ │ └─vuexφφλ
│ │ │ └─index.js // 首頁邏輯
│ │ └─index.vue
複制(zhì)代碼
- 我們使用(yòng)vuex來(lái)管理(lǐ)狀态,每個(gè)頁面都(d€★€•ōu)有(yǒu)自(zì)己的(de)vuex, 其中index.js存放(←Ω&fàng)對(duì)應頁面相(xiàng)關邏輯,為(wèi)了(le)避免頻(pí$₽"γn)繁切換目錄,把state, mutations, actions放(fàng)在一∑♥Ω(yī)個(gè)文(wén)件(jiàn)下(xià),使用(yòng)時(shíφ✘®)并啓用(yòng)vuex的(de)模塊化(huà),如(rú)下(xià)
const IndexPage = {
namespaced:σ' true, // 啓用(yòng)模塊化(huà)vuex
state: {
... // 需要(yào)共享的(de)狀态
},
mutations: {
₩<↓↓... // 一(yī)些(xiē)方法
},
actions: {
... // 請(qǐng)求相(xiàng)關
}
}
export default IndexPage //最後導出IndexPage
複制(zhì)代碼
- 各個(gè)頁面的(de)vuex統一(yī)放(fàng)在store裡(lǐ)
import Vue from 'vue'
import Vuex from 'vuex'
import IndexPage from '../pages/index/vuex'
import AddressSearch from '../pages/address/vuex/index'
import CityListPage from '../pages/city-list/vuex/index <♥α'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
... // 全局共用(yòng)的(de)狀态
},
mutations: {
},
actions: {
},
modules: {
IndexPage, // 首頁vuex
AddressSearch, // 地(dì)址檢索頁vuex
CityListPage, // 城(chéng)市(shì)列表頁vuex
},
})
export default store
複制(zhì)代碼
- 最後,在main.js裡(lǐ)面引用(yòng)
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App,
store
})
app.$mounδ∞t()
複制(zhì)代碼
完整的(de)首頁邏輯交互框架就(jiù)搭建成功了(le),以下(xi"↓ ×à)是(shì)開(kāi)發首頁時(shí)遇見(jiàn)的(de)問(wèn)ε∑題
首頁開(kāi)發遇到(dào)的(de)問(wèn)題
- 使用(yòng)swiper輪播組件(jiàn),寫≤±÷♣好(hǎo)子(zǐ)組件(jiàn),父組件(jiàn)因為(wè§♣≥i)無效果
問(wèn)題原因:引入的(de) import swiper from "../../components/swiper/s≠©wiper"
,導緻把自(zì)定義的(de)swiper覆蓋,所以不≈ ×(bù)展示
解決:引入的(de) import uniSwiper from "../../c♣εomponents/swiper/swiper"
,不(bù)和(hé)原組件(jiàn)命名沖突即可(kě)
- 轉百度小(xiǎo)程序header報(bào)錯(cuò→↑)
問(wèn)題原因:百度設置http請(qǐng)求header如(rú)果有(yǒu)中文(w®'₹®én)字符
解決:使用(yòng)條件(jiàn)編譯,如(rú)果是(shì)百度小₽ ₽(xiǎo)程序需要(yào)encodeURI 一(yī)下¶ (xià), 或者删除header的(de)中文(wén)部分(fēn)
- uni-app的(de)image标簽,在小(xiǎo)程序端不(bù)支持π≥♠₩動态引入圖片
// 引不(bù)到(dào)
class="tip_icon" src=http://www.wxapp-union.com£σ¶/"/static/sender{{endPoint.address ? ''÷& : '_default'}}.png"/>
複制(zhì)代碼
// 可(kě)以引入
class="tip_icon" src=http://www.wxapp-union.com/"/static/sender.png"/>
複制(zhì)代碼
- uni.getLocation() 隻能(néng)獲取經緯度,獲取不(bù)到∏↓δφ(dào)詳細地(dì)址信息
- 非 h5 平台 :key 不(bù)支持表達式
由于:key="timer__${idx}
"的(de)寫法,編譯時(shí)控制(zhì)台會(huì)警告,但(dàn)是(shì)♥±不(bù)影(yǐng)響頁面
<view
class="column_item"
v-for="(item, idx) in item"
:key="`timer__${idx}`" // 改成:key="idx" 即可(kě)
>
{{item == "立即用(yòng)車(chē)" ? "" : index == 1 ? "時(shí)" : index == 2 ? "分(fēn)" : ""}}
view>
複制(zhì)代碼
- 父子(zǐ)組件(jiàn)傳參,類型定義不(bù)對(du§↕™∞ì)不(bù)提示錯(cuò)誤信息,隻展示null, 所以遇到(dào)nul♠©l問(wèn)題可(kě)以查看(kàn)是(shì)否是(shì)類型定義不(bù)一(y₽÷ī)緻
- uni-app中的(de)watch不(bù)支持監聽(tīng)小∏∞(xiǎo)程序,如(rú)下(xià)
watch: {
searchType (to) {
if (to) {
// 如(rú)果是(shì)起始地(dì)回填起始地(dì)信息否則回填目的(de±₩)地(dì)信息
if (to === SEARCH_TYPE.START) {
this.detailAddress = this.startAddress.detailAddress |♦✔↔| ''
} else {
this.detailAddress = this.endAddress.detailAddress || ''
}
}
}
}
複制(zhì)代碼
改成
mounted () {
if (this.searchType === SEARCH_TYPE.START) {
this.detailAddress = this.startAddress.detailAddress || ''
} else {
this.detailAddress = this.endAddress.detailAddress || ''
}
}
複制(zhì)代碼
個(gè)人(rén)中心開(kāi)發
- 頁面效果
- webview的(de)實現(xiàn)
// template
'web-view' v-if='src' :src=http://www.wxapp-union. ✘σ™com/'src' @bindmessage='onmessage'>
複制(zhì)代碼
onLoad (options) {
console.log('H5入口頁獲取到(dào)的(de)參數(shù)', options)
let { src, n< ¶'eedLogin} = options
if(!needLogin){
this.src = http://www.wxapp-union.com/decodeURICom βponent(src)
return
}
// 需要(yào)登錄的(de) 就(jiù)先獲取臨時(shí)t ×oken
this.fetchTempToken(src)
}
複制(zhì$™Ω)代碼
如(rú)果不(bù)需要(yào)登錄的(de)H€£¥5我們直接賦值到(dào)src即可(kě),需要(yào)登錄才能(néng)正常訪問(wè≈σn)的(de)頁面,首先要(yào)獲取臨時(shí)token,拿(ná)到(dào)臨時(s×φhí)token後回傳給服務端并且采用(yòng)中間(jiān)頁redirectUrl的( ☆&de)形式跳(tiào)轉。
個(gè)人(rén)中心開(kāi)發遇到(dào)的(↓Ωde)問(wèn)題
- 向網頁傳遞信息要(yào)使用(yòng)頭條api的(de)bindme♦πΩssage
官方說(shuō)明(míng)“網頁向小(xiǎo)程序 postMessage 時(shí)Ω♣≈,會(huì)在特定時(shí)機(jī)(小(xiǎo)程序後退、組件(ji✔πΩ•àn)銷毀、分(fēn)享)觸發并收到(dào)消息”
// 在小(xiǎo)程序中調起H5中的(de)打電(diàn)話(huàδ←α')功能(néng)
onmessage (e) {
let { phoneNumber, n₹™ame } = e.detail
if(name == 'makePhoneCall'){
uni.makePhoneCall({
number: phoneNum÷"Ω₩ber
})
}
}
複制(zhì)代碼
需要(yào)注意的(de)web-view的(de)bindmessage屬性并不'•☆♦(bù)是(shì)實時(shí)的(de)
- 真機(jī)撥打電(diàn)話(huà)功能(néng)不 " ≥(bù)能(néng)用(yòng)
// 使用(yòng)uni.makePhoneCall真機(j☆∑ī)沒反應
uni.makePhoneCall({ phoneNumber: '114'});
複制(zhì)代碼
解決:改為(wèi)頭條api的(de)tt開(kāi)頭
// 真機(jī)模拟器(qì)均可(kě)正常使用(yò©✘<ng)
tt.makePhoneCall({ phoneNumber: '114'});
複制(zhì)代碼
登錄開(kāi)發
-
頭條授權登錄效果
-
大(dà)緻思路(lù):
1.首先獲取獲取服務供應商的(de)信息
2.調用(yòng)
uni.getProvider
獲取授權code3.獲取用(yòng)戶的(de)手機(jī)号(用(yòng)戶登錄頭σ≥≈條app的(de))
4.從(cóng)
@getphonenumber
回調中獲取到(dào)用(yòng)戶信息5.調用(yòng)授權登錄服務api
6.獲取token, openid等信息
// template
<view class="login-page">
<view class="title">
<view class="h-line">view>
<view class="page-title">授權登錄更快(kuài)捷view>
<view class="h-line">view>
view>
<view class="authLogin-wrapper">
<button type="default" open-type="getPhoneNumber" @getphonenumber="authLoginTap" class="login authLogin">百度登錄更快(kuài)捷button>
<button
type="default"
class="login authLogin"
open-type="getPhoneNumber"
@getphonenumber="onGetPhoneNumber"
>授權手機(jī)号快(kuài)捷登錄button>
view>
view>
複制(zhì)代碼
// 完成渲染調用(yòng)授權code方法
mounted () {
this.getCode()
}
複制(zhì)代碼
// 獲取授權code方法
async getCode () {
const [ errorProvider, provider ] = await uni.getProvider({ service: 'oauth' })
if (errorProvider) {
console.log('獲取provider失敗')
return
}
const [ errLogin, data ] = await uni.login({
provider: provider.provider[0],
force: true
})
if (errLogin) {
console.log('獲取code失敗')
// 失敗的(de)操作(zuò),提示等
return
}
const { code } = data
this.code = code
},
// 頭條獲取到(dào)用(yòng)戶信息
async onGetPhoneNumber ({ detail }) {
const { errMsg } = detail
// 授權失敗
if (errMsg.indexOf('auth deny') > -1) {
// 取消授權進行(xíng)手機(jī)驗證碼登錄
return
}
try {
// 調用(yòng)服務授權接口
const { data } = await authLogin({
code: this.code,
...detail,
})
if (data.code === SUCCESS) {
≈>★ // 存token, openid等操作(zuò)
// 重新更新個(gè)人(rén)信息
} else {
// 失敗的(de)提示等
}
} catch (error) {
// 登錄失敗異常情況處理(lǐ)
}
},
// 百度獲取到(dào)用(yòng)戶信息同理(lǐ)頭條。。。
複制(zhì)代碼
登錄開(kāi)發遇到(dào)的(de)問(wèn)題
手機(jī)驗證碼開(kāi)發時(shí),引入 checkbox-group
報(bào)錯(cuò),如(rú)下(xià)圖:

原因: components : { [CheckBox.name]: CheckBox }σ•
引入組件(jiàn)方式不(bù)支持
發布到(dào)測試環境
以字節跳(tiào)動為(wèi)例子(zǐ),打開(k∏¥ πāi)字節跳(tiào)動開(kāi)發者工(gōng)具,在工(gōng)具欄找♥±±™到(dào)上(shàng)傳,填寫版本号,發布。版本号不(bù)和(hé★β$)上(shàng)一(yī)次沖突就(jiù)可(kě)以。
Tips: 前面有(yǒu)提過,新建代碼片段是(shì)在開(kāi ←)發者工(gōng)具上(shàng)是(shì)沒有(yǒu)上(shàng)傳按鈕的(de<₩®),要(yào)導入項目才可(kě)以。

上(shàng)傳成功後,會(huì)提示進入小(xiǎo)程序開(kāi)發者平台,現(x∑↑βiàn)在可(kě)以看(kàn)到(dào)開(kāi)發者的(de)版本。


上(shàng)圖二維碼就(jiù)可(kě)以隻作(zuò)為(wèi)本次的(de)體(tǐε$$σ)檢版本來(lái)掃一(yī)掃了(le)。
發布到(dào)正式環境
- 前置準備,在後台配置好(hǎo)相(xiàng)關線上(∑∏shàng)域名
- 切換到(dào)線上(shàng)環境
// 環境相(xiàng)關配置
export const ENV = {
// 開(kāi)發環境
RD: 'rd',
// 測試環境
TEST: 'test',
// 沙箱環境
BOX: 'box',
// 線上(shàng)環境
ONLINE: 'online'
}
// 環境切換
export function getCurrentEnv() {
return ENV.ONLINE // 正式環境切到(dào)online
}
複制(zhì)代碼
- 在開(kāi)發者工(gōng)具中點擊上(shàng)傳
- 去(qù)小(xiǎo)程序開(kāi)發者平台提審發布₹§☆
- 發布成功後可(kě)在頭條搜索欄中搜到(dào),抖音(yīn)的(de)話(huà≤♣)目前隻有(yǒu)安卓平台上(shàng)線了(le)小(xiǎo)程序功能(néng)♥¶。
結束語
以上(shàng)就(jiù)是(shì)uni-app轉字節跳(tiào)動、百度小(xi¶'ǎo)程序的(de)部分(fēn)開(kāi)發,相(xiàng)信大(dà)家(jiā)≠"對(duì)uni-app實戰小(xiǎo)程序已經有(yǒ✔<≈u)了(le)初步認識,也(yě)歡迎大(dà)家(jiā)指正,互相✘Ωβ(xiàng)交流,共同進步