uni-app小程式手把手專案實戰

曾小曾發表於2019-11-18

小程式的開發選型,推薦這篇文章小程式開發:用原生還是選框架

選型之類過多的話語就不說了,個人還是比較推薦uni-app,要麼就原生。

廢話不多說,開幹。

一、註冊

網址: 微信註冊,根據指引填寫資訊

PS:開發選型的時候一定要注意主體賬號資訊的分類,簡單解釋就是這個小程式是要幹嘛的,定位要精準,小程式的上線目前越來越嚴格,並不是所有小程式都能過審的。比如,人臉授權這種功能,你就很難過審...如果有這個功能,我勸你放棄,走APP。

二、登入設定

登入後找到設定模組,在這裡你可以設定一些小程式的主題資訊,比較重要的就是這個AppID(小程式ID),唯一的,相當於微信小程式的敲門磚

當專案是多人協作的時候,你可以新增多個開發者賬號

uni-app小程式手把手專案實戰

三、選框架,安裝開發工具

這裡用的是uni-app,當然微信小程式微信開發者工具也是要安裝的,微信開發者工具呢建議還是安裝最新版的,原因當然是最新版的會不斷加入很多新特性。uni-app的開發也必須安裝HBuilderX工具,這個是捆綁的,沒得選擇。雖然有很多人吐槽這個HBuilderX,號稱傻瓜式的程式設計工具。好吧,要用uni-app,你必須得裝!!!

工具安裝:

微信開發者工具

HBuilderX

至此,所有的準備工作都OK了,接下來直接進入專案開發了。

四、專案開發

1、新建一個uni-app專案

uni-app小程式手把手專案實戰

uni-app小程式手把手專案實戰
2、專案結構

uni-app小程式手把手專案實戰

.
├─ common/              # 公用工具庫檔案
├─ components/          # uni-app元件目錄
│  ├─ comp-a.vue        # 可複用的a元件
├─ hybrid/              # 存放本地網頁的目錄
├─ pages/               # 業務頁面檔案存放的目錄
│  ├─ home/            
│  │  ├─ index.vue      # home頁面
│  ├─ list/            
│  │  ├─ index.vue      # list頁面
├─ platforms/           # 存放各平臺專用頁面的目錄
├─ static               # 存放應用引用靜態資源(如圖片、視訊等)的目錄,注意:靜態資源只能存放於此
├─ unpackage/           # 打包目錄
├─ wxcomponents/        # 存放小程式元件的目錄
├─ App.vue              #  應用配置,用來配置App全域性樣式以及監聽
├─ main.js              # Vue初始化入口檔案
├─ manifest.json        # 配置應用名稱、appid、logo、版本等打包資訊
├─ package.json         # 配置頁面路由、導航條、選項卡等頁面類資訊
複製程式碼

Tips:

static 目錄下的 js 檔案不會被編譯,如果裡面有 es6 的程式碼,不經過轉換直接執行,在手機裝置上會報錯。

cssless/scss 等資源同樣不要放在 static 目錄下,建議這些公用的資源放在 common 目錄下。

3、專案執行 [圖片]

uni-app小程式手把手專案實戰

uni-app小程式手把手專案實戰
第一次執行容易報圖上的錯,這個時候,可以手動開啟微信開發者工具掃碼登入(加入開發者賬號)。然後再重新執行到小程式,或者配置微信開發者工具的預設路勁,這樣一勞永逸,就不用每次先開微信小程式再執行專案了。 [圖片]
uni-app小程式手把手專案實戰
再執行的時候通常還是容易報錯...不過彆著急,一步一步來

uni-app小程式手把手專案實戰

uni-app小程式手把手專案實戰
再次重新執行小程式,終於可以編譯成功了,圖為demo模板的頁面 [圖片]
uni-app小程式手把手專案實戰
當然,至此只是讓你先體驗一下uni-app,接下來直接進入正式開發

五、正式專案開發

之前的模板內容太多了,專案重新開啟前還是重新建一個空的模板吧,新建專案的時候依然選擇uni-app專案+預設模板

uni-app小程式手把手專案實戰

1.配置AppID

uni-app小程式手把手專案實戰

2.執行專案

為了方便開發,可以安裝一個內建的終端,可以不用額外開啟終端

uni-app小程式手把手專案實戰

3.搭建目錄框架

因為使用預設模板,所以專案結構很乾淨。接下來先把目錄框架搞定,當然你也可以按照自己的個人習慣和喜好自由設定

因為之前安裝了內建終端,所以直接開啟終端,會預設開啟你所在的專案的根路徑,直接在根路徑下命令列建立目錄檔案

mkdir components models store utils
複製程式碼

uni-app小程式手把手專案實戰

4.微信路由 準確的來說uni-app小程式也是單頁面的形式。在小程式中,路由是不用自己定義的。uni-app路由全部交給框架統一管理,開發者需要在pages.json裡配置每個路由頁面的路徑及頁面樣式,不支援 Vue Router,如圖,pages屬性值的陣列內容即為路由路勁

{
    "pages": [ //pages陣列中第一項表示應用啟動頁,參考:https://uniapp.dcloud.io/collocation/pages
    	{
            "path": "pages/index/index",
            "style": {
            	"navigationBarTitleText": "首頁",
            	"navigationBarBackgroundColor": "#FFFFFF"
            }
    	},
        {
            "path" : "pages/mine/index",
            "style" : {
            	"navigationBarTitleText": "個人中心",
            	"navigationBarBackgroundColor": "#FFFFFF"
            }
        }
    ],
    "globalStyle": {
    	"navigationBarTextStyle": "black",
    	"navigationBarTitleText": "uni-app",
    	"navigationBarBackgroundColor": "#F8F8F8",
    	"backgroundColor": "#FFFFFF"
    },
    "tabBar": {
    	"color": "#BBBBBB",
    	"selectedColor": "#212121",
    	"borderStyle": "black",
    	"backgroundColor": "#ffffff",
    	"list": [
            {
            	"pagePath": "pages/index/index",
            	"iconPath": "static/images/tabbar/fans.png",
            	"selectedIconPath": "static/images/tabbar/fans@selected.png",
            	"text": "首頁"
            },
            {
            	"pagePath": "pages/mine/index",
            	"iconPath": "static/images/tabbar/mine.png",
            	"selectedIconPath": "static/images/tabbar/mine@selected.png",
            	"text": "個人中心"
            }
        ]
    }
}
複製程式碼

5.vuex狀態管理

首先,uni-app 內建了 vuex。但是vuex是不支援持久化儲存的,所以需要結合第三方來一起協作。

預設的模板專案首先是沒有node-modules模組依賴的,也就是說你沒法進行一些第三方的擴充套件,所以為了讓你的專案更加的靈活性,你需要執行以下命令來搭配一些第三方來更隨心所欲的開發專案

npm init -y
npm install vuex-persistedstate --save
複製程式碼

store.js

import Vue from 'vue'
import Vuex from 'vuex'

import home from '@/store/modules/home.js'
import mine from '@/store/modules/mine.js'
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex)

const vuexPersisted = new createPersistedState({
    storage: {
    	getItem: key => uni.getStorageSync(key),
        setItem: (key, value) => uni.setStorageSync(key, value),
        removeItem: key => uni.clearStorageSync(key)
    }
})

const store = new Vuex.Store({
    modules: {
    	home,
    	mine
    },
    plugins:[vuexPersisted]
})

export default store
複製程式碼

home裡面的vuex結構也展示一下吧

const home = {
    state: {
    	...
    },
    mutations: {
    	...
    },
    actions: {
    	...
    },
    getters: {
    	...
    }
}

export default home
複製程式碼

最後,在main.js裡面引用

import Vue from 'vue'
import App from './App'
import store from './store'

Vue.config.productionTip = false
Vue.prototype.$store = store

App.mpType = 'app'

const app = new Vue({
    store,
    ...App
})
app.$mount()

複製程式碼

至此,含兩個tabbr選項的無資料互動的小程式ui結構就搭好了。

uni-app小程式手把手專案實戰

6.封裝api模組

因為需要呼叫服務端的登入口子,所以我們優先把請求介面的模組給新增進來吧。

config配置,appIdappKey可以從微信官方開發模組獲取到

uni-app小程式手把手專案實戰

//uni-app內建有區別環境的不同,可以直接通過process.env.NODE_ENV獲取
//!!!注意,這裡的介面當然是不能訪問的,正式的api介面是商業保密的,後期抽時間用node來補上吧。專案無法正常介面請求,請諒解。但是跟著我的思路,把一個專案跑起來是沒有任何問題的。
let BASE_URL = ''
if (process.env.NODE_ENV == 'development') {
    BASE_URL = '192.168.1.1:8090' // qe環境
} else {
    BASE_URL = 'https://www.baidu.com' // 生產環境
}
const config = {
	base_url: BASE_URL,
	appId: 'wxeb407bb6c397aa4c',
	appKey: '675aeecfdac05b6b82b9910a8fd00e88'
}

export { config }
複製程式碼

封裝介面請求

import {
	config
} from '../config.js'

class HTTP {
	constructor() {
		this.baseUrl = config.base_url
	}

	request({
		url,
		data = {},
		method = 'GET'
	}) {
		return new Promise((resolve, reject) => {
			this._request(url, resolve, reject, data, method)
		})
	}

	_request(url, resolve, reject, data = {}, method = 'GET') {
		uni.request({
			url: `${this.baseUrl}${url}`,
			method: method,
			data: data,
			header: {
				'content-type': 'application/json',
				'appId': config.appId,
				'token': uni.getStorageSync('AuthTokens')
			},
			success: (res) => {
				if (res.data) {
					const _success = res.data.success;
					if (_success) {
						resolve(res.data)
					} else {
						reject(res.data.message)
						const error_code = res.data.code;
						const _message = res.data.message;
						this._show_error(error_code, _message)
					}
				} else {
					resolve(res.data)
				}
			},
			fail: (err) => {
				reject()
				this._show_error(err.message)
			}
		})
	}

	_show_error(error_code, _message) {
		uni.showToast({
			title: `${_message}`,
			icon: 'none',
			duration: 2000
		})
	}
}

export {
    HTTP
}
複製程式碼

到此Api請求的模組就封裝好了,現在開始做介面請求必須攜帶的AuthTokens祕鑰

因為小程式肯定會頻繁的切換後臺或者直接切回首頁面,結合小程式的生命週期等,在首頁的主入口一般都會調一次登入口子,獲取祕鑰token

App.vue

import { AppModel } from './models/app.js'
const appModel = new AppModel()

onShow: function() {
    console.log('on show');
    this.getLogin()
},

methods: {
    getLogin() {
        uni.login({
            success: function(res) {
                if (res.code) {
                    appModel.login({
                        code: res.code
                    }).then(response => {
                        this.$store.dispatch('setUserInfo', response.data)
                        //這裡儲存了之後,等再進入小程式獲取資料或其它的Api互動時,就可以帶上放在header頭中去向服務端發起請求
                        uni.setStorageSync('AuthTokens', response.data.token)
                        uni.login({
                            success(response) {
                                uni.setStorageSync('wxCode', response.code);
                            }
                        })
                    }).catch(errors => {
                        console.error(errors)
                    })
                }
            },
            fail: function() {
                uni.showToast({
                    title: '微信登入失敗',
                    icon: 'none'
                })
            }
        });
    }
}
複製程式碼

AppModel的介面定義,按照如下標準直接定義即可

import { HTTP } from '../utils/http.js'

class AppModel extends HTTP {
    login(params) {
        return this.request({
            url: `/user/login`,
            method: 'POST',
            data: params
        })
    }
}

export { AppModel }
複製程式碼

上面還應用了vuex的狀態管理this.$store.dispatch('setUserInfo', response.data),所以你還要到store下的home modules模組做好狀態管理,主要還是vuex的日常操作。一般來說同步儲存只要放mutations裡面定義即可,主要還是看個人習慣吧

state: {
    userInfo: {}
},
mutations: {
    SET_USER_INFO: (state, userInfo) => {
    	state.userInfo = userInfo
    }
},
actions: {
    // 快取使用者資訊
    setUserInfo({
        commit
    }, userInfo) {
    	commit('SET_USER_INFO', userInfo)
    }
},
getters: {
    userInfo: state => state.userInfo
}
複製程式碼

六、靜默授權

授權登入是一大重點,在專案剛開始開發的時候尤其要注意。小程式目前已有官方規定明確禁止新使用者初次開啟小程式就喚起授權登入獲取使用者資訊的彈框,也就是說,如果你不當回事的話,即使開發完畢釋出,微信官方團隊也會直接咔嚓回。那個時候再改,代價就太大了

所以呢,目前採用的是靜默授權登入的方式。什麼是靜默授權呢,就是新使用者進入你的小程式後,他可以無障礙的訪問你的小程式,當他需要分享、進詳情頁、互動動作、點贊、購買...需要深一層次體驗我們的小程式的時候,這個時候喚起授權彈窗讓使用者授權之後再繼續下一步是合理的。

接下來是授權登入的實現。暫時把它放在個人中心的頭像區域吧

1.找到pages-->mine頁面

ui搭建的工程中,專案預設引用less預處理,雖然不用安裝第三方依賴,都是uni-app內建的,但是想要讓專案正常執行,還是要安裝編譯時的對應工具,否則會報錯

uni-app小程式手把手專案實戰

工具--->外掛安裝

uni-app小程式手把手專案實戰

然後安裝對應的依賴即可,再重新執行專案

uni-app小程式手把手專案實戰

為了統一靜默授權處理,還是抽離一個公共元件,存放在components->common->userInfoBtn.vue

要調取使用者的授權登入,必須呼叫微信自帶的button控制元件才行,包括後面的分享功能模組也一樣。必須要用到它裡面自帶的open-type屬性。

引用微信自帶的button當然會有很多醜陋的問題,比如樣式,所以這裡還是要重置下樣式

<template>
    <view class="user-info-container">
        <button class="user-info-btn" open-type="getUserInfo" @getuserinfo="mpGetUserInfo" withCredentials="true">
            <slot></slot>
        </button>
    </view>
</template>

<script>
import {
    AppModel
} from '@/models/app.js'
const appModel = new AppModel();
export default {
    name: 'userInfoBtn',
    data() {
        return {
            userInfo: {}
        }
    },
    methods: {
        mpGetUserInfo(result) {
            //根據呼叫系統自帶button攜帶的result資訊判斷是否有授權資訊
            if (result.detail.errMsg !== 'getUserInfo:ok') {
                wx.showToast({
                    title: '取消授權',
                    icon: 'none',
                    duration: 2000
                })
                //hasUserInfo為儲存使用者是否授權資訊
                uni.setStorageSync('hasUserInfo', false)
                return;
            }
            wx.checkSession({
                success() {
                    console.log('有效');
                    //因為使用者授權後需求獲取使用者授權資訊,所以這裡必傳encryptedData、iv兩個引數獲取使用者頭像和暱稱資訊
                    appModel.login({
                        code: uni.getStorageSync('wxCode'),
                        encryptedData: result.detail.encryptedData,
                        iv: result.detail.iv
                    }).then(response => {
                        this.$store.dispatch('setUserInfo', response.data)
                        uni.setStorageSync('AuthTokens', response.data.token)
                        uni.setStorageSync('hasUserInfo', true)
                        this.$emit('onClickBtn')
                        this.userInfo = result.detail.userInfo
                        uni.login({
                            success(response) {
                                uni.setStorageSync('wxCode', response.code);
                            }
                        })
                    })
                },
                fail() {
                    console.log('失效');
                    uni.login({
                        success: function(res) {
                            if (res.code) {
                                uni.setStorageSync('wxCode', res.code);
                                const params = {
                                    code: res.code
                                }
                                appModel.login({
                                    code: uni.getStorageSync('wxCode'),
                                    encryptedData: result.detail.encryptedData,
                                    iv: result.detail.iv
                                }).then(response => {
                                    uni.login({
                                        success(response) {
                                            uni.setStorageSync('wxCode', response.code);
                                        }
                                    })
                                    this.$store.dispatch('setUserInfo', response.data)
                                    uni.setStorageSync('AuthTokens', response.data.token)
                                    uni.setStorageSync('hasUserInfo', true)
                                    this.$emit('onClickBtn')
                                    this.userInfo = result.detail.userInfo
                                })
                            } else {
                                console.log('獲取使用者登入態失敗!' + res.errMsg);
                            }
                        },
                        fail: function() {
                            uni.showToast({
                                title: '微信登入失敗',
                                icon: 'none'
                            })
                        }
                    });
                }
            })
        },
    }
}
</script>

// 樣式重置,這裡的樣式坑是必踩的
<style lang="less" scoped>
    .user-info-btn::after {
        border: 0;
    }
    
    .user-info-btn {
        background-color: transparent;
        line-height: 0;
        padding: 0;
        font-size: 0;
    }
</style>
複製程式碼

2.引用上面的封裝授權按鈕

<header>
	<view class="view-header_root" v-if="hasAuthorUrserInfo">
		<view>
			<image class="avatar-img" :src="userInfo.avatarUrl | formatAvatarUrl"></image>
			<image class="avatar-img2" :src="starUrl" v-if="userInfo.starId > 0"></image>
		</view>
		<text>{{userInfo.userName | formatUserName}}</text>
	</view>
	<view class="view-header_root" v-else>
		<userInfoBtn @onClickBtn="onGetAuthData" >
			<section class="un-auth">
				<view>
					<image class="avatar-img" :src="userInfo.avatarUrl | formatAvatarUrl"></image>
					<image class="avatar-img2" :src="starUrl" v-if="userInfo.starId > 0"></image>
				</view>
				<text>uni-小程式</text>
			</section>
		</userInfoBtn>
	</view>
</header>

methods: {
    onGetAuthData() {
    	//授權成功後的回撥事件
    	console.log('success')
    }
}
複製程式碼

這裡說一個小技巧,在vue專案中引用第三方UI框架時,肯定會涉及到修改樣式的問題。由於我們在Vue檔案中加入了scoped屬性,就是為了防止頁面之間的樣式汙染,所以你想要修改樣式的話,有兩種方式,第一種是新起一個style,不加scoped,然後嚴格遵循BEM命名模式修改樣式,儘量避免樣式汙染其它頁面。第二種就是引用css/deep/,如

<style lang="less" scoped>
/deep/ .user-info-btn {
    background-color: red;
}
</style>
複製程式碼

至此靜默授權的元件封裝和功能都實現完畢了。還是要再強調一遍,目前開發的小程式必須採用靜默授權登入的方式,否則你很大概率會被拒...

--- 補充說明 ---

很多小夥伴可能在這裡會有疑問,入口App.vue不是有呼叫過appModel.login這個登入口子獲取AuthTokens了嗎。為什麼授權之後還要再呼叫一遍。原因很簡單,靜默授權的原則就是新使用者初次進來之後,必須無障礙的瀏覽你的小程式,也就是說剛開始在App.vue頁面只能獲取token資訊,因為小程式內頁的介面大都是要把token放在header頭去請求服務端才能拿到資料,而另外的encryptedDataiv這兩個引數是隻有你想獲取真實的使用者資訊才能帶上,也就是說服務端必須把這兩個引數設為非必傳。

只有他想進入你的小程式的二級頁面,或者首頁有點贊、拍照、評論、分享...這一類你想拿到他的個人資訊時,再呼叫這個封裝的授權按鈕元件讓使用者授權,然後再呼叫一遍appModel.login介面,再帶上encryptedDataiv這兩個非必傳的引數,使用者確認授權後,就能獲取到真實的使用者個人資訊了。

請注意!!!

講真,微信授權獲取使用者資訊這塊是必不可少的,不獲取使用者資訊那開發小程式的意義何在。但是很多產品在定性小程式的時候,就想著一進小程式就讓使用者授權,這種需求直接拒絕就行,不要任何拖泥帶水操作。因為上不了是註定的。或者他們想著委婉點,讓你在tabbar切換上加個授權,uni-app是沒有路由的概念的,因此想要引用vue-router的鉤子函式去攔截路由是行不通的,但倒不是不能實現,可以自己手寫一套,但是花這麼大代價有意義嗎?何況所謂的靜默授權的初衷,就是要讓使用者首次進入無障礙的使用小程式,無障礙的意義並不是說就只給看個首頁,然後切換個tabbar就要授權了?!那估計也是大概率被拒的多。

又或者他們想我不放在tabbar的切換時加入授權,我切換後在頁面裡面加,即從首頁切到我的頁面時,直接一張暫無訊息佔點陣圖+一個授權按鈕,只有你授權了才能看我的頁面的所有內容。講真,真的都好雞肋,跟上面tabbar切換授權有區別嗎???

最後,靜默授權這塊懟不過產品的,就讓產品多去玩玩看看大廠是怎麼做的。比如小米、蘇寧等等等等...祝你成功!

七、功能擴充套件

為了讓這個專案不至於這麼空殼,計劃加入一些常用的功能,比如記錄列表上拉載入,下拉重新整理、輪播圖、分享、開屏廣告頁、線上客服引入...

1.上拉載入、下拉重新整理

uni-app小程式手把手專案實戰

入口就是在個人中心的分頁記錄列表

首先加頁面路由,在page目錄下新增一個records頁面,然後在專案根目錄下的pages.json掛載上,如果要新開頁面的話,都要在這個目錄下注冊頁面

如動態圖所示,這裡還抽了一個tab選項卡的小元件。直接開箱即用就行。

上拉載入下拉重新整理在uni-app官網上其實是有介紹的。這裡單獨取出來是因因為介面都配置好了,只要替換成你專案中的服務端資料和修改下樣式即可,功能是已經實現了的。程式碼就不全貼了,直接大致介紹下功能點吧

上拉載入下拉重新整理這功能大致分兩種情況,第一種是整個頁面的上拉下拉,這種實現比較簡單,首先當然是要在專案根目錄下的pages.json宣告頁面的可載入屬性

{
    "path" : "pages/records/records",
    "style" : {
        ...
        "enablePullDownRefresh": true
    }
}
複製程式碼

然後主要實現兩個方法功能

//頁面上拉觸底事件的處理函式
onReachBottom() {
},
//頁面下拉初始化重新整理
onPullDownRefresh() {
}
複製程式碼

是否載入完畢可以在服務端介面返回資料中對物件做處理,對應的業務在程式碼中都有實現好,因為介面無法正常呼叫,所以你要使用的話,需要替換成你自己聯調的介面。

2.聯絡客服

小程式要做好的話,那細節之處肯定是必不可少的。比如客服功能的引入,實時根據使用者的反饋完善或者修復問題

小程式中不需要你額外接入線上聊天工具,當然,如果你想體驗性做得好點,那可以多投入些精力做好實施聊天這一大模組。這裡簡單介紹一下用小程式自帶的反饋聊天模組

首先,還是得應用微信自帶的button按鈕,指定open-type的值為contact

<button open-type="contact" bindcontact="handleContact" class="button-item-title">{{item.title}}</button>
複製程式碼

在小程式中,開發者可以登入 微信小程式管理後臺,進入選單“客服反饋”頁面獲取反饋內容

uni-app小程式手把手專案實戰

3.分享

說完聯絡客服順便說下分享吧,都是同樣的套路,同樣是應用微信自帶的button按鈕,指定open-type的值為share,然後在vue屬性上指明你要分享的內容

onShareAppMessage() {
    return {
    	title: `分享的標題`,
    	path: `/pages/mine/index?id=${分享要帶的引數}`,
    	imageUrl: `分享的url`
    }
}
複製程式碼

分享出去的攜帶的引數id提取的方式是利用小程式的生命週期函式onLoad

onLoad(option) {
    console.log(option)
    this.id = option.id
}
複製程式碼

4.輪播圖+跳轉第三方url

同樣封裝成一個工具庫components->common->swiper.vue,工具類就不多說了,引用的是系統自帶的swiper元件

這裡介紹一下跳轉第三方url頁吧,包括在UI搭建階段輪播圖引用其它外域連結的圖片url,這兩個其實算是一類問題。

微信安全規範裡面,是明確禁止沒有在微信開發者後臺加入合法域名時,加入任何的外域連結都為非法連結,也就是說,即使是聯調的服務端介面,也得把合法域名加進微信的伺服器域名名單,包括使用微信拍照或者上傳圖片都必須額外加上這個合法域名名單,圖片資訊才能正常顯示,介面才能正常引用。配置詳情如下

配置路徑

uni-app小程式手把手專案實戰

配置完後微信開發者工具詳情欄目裡專案配置裡會出現合法域名資訊

uni-app小程式手把手專案實戰
或者在開發環境時可以把這裡勾上,但最終專案上線後還是得記得配置對應的合法域名資訊

配置好後,當你的輪播圖對應的是後臺的詳情地址或者是微信公眾號的內容時,才能夠正確跳轉到對應的路徑中。唯一要注意的是,在本地微信開發者工具是無法測試這一功能的,最好用真機測試,否則還是要務必保證你的合法域名都在微信後臺新增上了,並且本地設定也去除了合法域名的校檢

uni-app小程式手把手專案實戰

//輪播圖跳轉第三方url
uni.navigateTo({
    url: `bannerWebView?url=${encodeURIComponent(url)}`
})
複製程式碼

如上程式碼所示,詳情頁跳轉第三方url,你必須得新開一個頁面bannerWebview作為第三方路勁承載的容器,當然,別忘了路由註冊。這裡,你要跳轉的url最好encodeURIComponent(url),然後在bannerWebview檔案中,利用微信自帶的<web-view :src="url"></web-view>,即可進行第三方頁面的跳轉,再次強調一遍,跳轉第三方最好用真機做測試。

這樣,輪播圖功能就搞定了

擴充套件功能就先做這些吧,後續有時間再加一下上去...

八、開屏廣告頁

現在很多大流量的APP在首次開啟時會有一個3~7S不等的小廣告,當然,做得有好點你可以讓他隨時都能跳過。小程式裡面也有廣告頁這樣的概念,接下來就讓我們來實現一下吧

首先是廣告頁的入口構思,廣告頁放哪個位置合適呢?是放首頁作為彈窗出現???還是作為小程式主入口出現???因為廣告頁不可能每次開啟小程式都出現一次廣告,那使用者肯定十分反感,過度挑戰使用者的耐心,肯定難逃被使用者解除安裝的下場...一般合理一點的需求就是每天的第一次開啟時,加入一個3~7S不等的小廣告。接下來我們來實現一下作為主入口出現的小廣告。

首先,在pages.json註冊頁面路由,這裡務必要注意一點,pages陣列中第一項表示應用啟動頁,參考:uniapp.dcloud.io/collocation…

"pages": [ //pages陣列中第一項表示應用啟動頁,參考:https://uniapp.dcloud.io/collocation/pages
    {
        "path": "pages/ads/index",
        "style": {
            "navigationBarTitleText": "uni-小程式",
            "navigationBarBackgroundColor": "#FFFFFF"
        }
    },
    ... //緊跟其它的頁面
]
複製程式碼

廣告頁無非就是一個定時器,然後加一張海報或者由後臺動態配置圖片內容。這裡提幾個小點應該注意的地方,廣告頁肯定分開啟的時機,也就是說你得判斷好廣告頁按規定時間展示,不能每次開啟都有廣告頁的出現。這裡可以讓服務端傳給你一個引數。

計數器結束後,可以立即跳轉到小程式首頁,並且終止定時器

methods: {
    uni.reLaunch({
        url: '/pages/index/index'
    })
},
onHide() {
    //清除定時器 
    this.clearTimer()
}
複製程式碼

廣告頁功能的最後,打測試包或者正式包的時候一定要記得修改主入口頁資訊!!!否則上線後會一片空白,等廣告頁定時器結束之後才到主頁

九、訊息推送

訊息推送是必不可少的一大模組,但是推送的這個度還是要把控好,太頻繁了自然就會引起反感,那離被解除安裝就不遠了。 訊息推送的功能已經加在首頁裡,功能介紹的軟文在另一篇博文裡可以瀏覽。

傳送門:uni-app小程式訊息推送

十、釋出測試

開啟微信開發者工具,在工具欄找到上傳,填寫版本號,釋出。測試版本號可以隨意填寫,不過建議還是規範一點寫比較好

uni-app小程式手把手專案實戰

上傳成功之後,可以開啟微信開發者管理後臺,現在可以看到開發者的版本

uni-app小程式手把手專案實戰

然後指定小程式的主入口頁,主要參照pages.json屬性值pages陣列的第一項的值

uni-app小程式手把手專案實戰

然後,就可以作為體驗版本提交了。

十一、釋出正式

測試版本和正式版本還是有差距的。正式版本中,因為小程式發版限制在2M以內,所以有幾點務必要引起注意

  • 圖片用CDN,不要用本地圖片載入,圖片內容太大
  • 確認涉及到這些功能點的域名資訊在微信開發後臺管理中有配置

uni-app小程式手把手專案實戰

  • 使用iconFont替代純色小圖示
  • 儘量不要引用第三方字型
  • 雪碧圖
  • ... ...

釋出上線。

測試發版只要在開發者工具中直接打包上線即可,沒有這麼多的條條框框。但是正式版發版就不一樣了,就最關鍵的一點,開發版和正式版的服務端域名肯定不一樣吧?!所以,為了避免每次發版手動頻繁修改配置介面,造成哪次不小心把測試版的發線上去,最好做個區分,把開發環境和正式環境區分開來。發正式版本的時候打正式環境的包

主要配置呢就是在根目錄新建個config.js檔案,區分開發和正式版就是自帶的process.env.NODE_ENV屬性值

if (process.env.NODE_ENV == 'development') {
    BASE_URL = '192.168.1.1:8090' // qe環境
} else {
    BASE_URL = 'https://www.baidu.com' // 生產環境
}
複製程式碼

然後打正式包的時候,選擇HBuilderX開發工具工具欄發行->小程式(微信)

uni-app小程式手把手專案實戰

然後檢查小程式名稱+AppId,確認無誤點選發行,會再在微信開發者工具裡開一個視窗,執行同樣的小程式。區別只是域名地址不一樣了,開發版本是本地ip,發行後的服務域名是正式的線上地址。以防萬一,可以開啟微信開發者工具欄的工具皮膚檢視一下域名是否正確

uni-app小程式手把手專案實戰

uni-app小程式手把手專案實戰

確認無誤後再重複測試版本發版即可

uni-app小程式手把手專案實戰

至此,小程式的開發到上線就全部完成了。

十二、題外話

還是迴歸到框架的選型來講講,選用uni-app開發小程式,打包上傳後,程式碼竟驚人的被壓縮到了1M以內。相對比mpvue就重了不少,有大1M多

當時並行做的是兩個小程式,基於mpvue和基於uni-app,結果是mpvue因為前期問題不斷,導致發版被拒次數增多,最後都修復完全正式上線之後,再更新迭代,稽核的時間依然長的很。但是uni-app做的小程式就沒這個問題了,前期的幾版發版比較順利的話,後期再更新迭代,那速度真是嗖嗖的,普遍都是在一個工作日內。等信用(通過率)累計到了一定程度,會直接上微信稽核的白名單,開啟半小時稽核急速上線的通道,真香~

好了,基於uni-app的小程式開發到此結束了,喜歡的話請多賜個贊!!!吧。

十三、Github原始碼

hello-uni-app

十四、基於React+Redux-saga的實戰專案

手把手帶你搭建React16+Router+Redux-saga+Antd後臺管理系統

相關文章