介紹
Mpvue 是一個使用 Vue.js 開發小程式的前端框架。框架基於 Vue.js 核心,修改了 Vue.js 的 runtime 和 compiler 實現,使其可以執行在小程式環境中,從而為小程式開發引入了整套 Vue.js 開發體驗,同樣也使得一套程式碼同時複用在小程式和 Web 中成為可能。本文將以 IT之家Lite 小程式的 Web 轉換經過為線索,大致介紹一下轉換的基本步驟及需要注意的一些事項。
目錄結構
省略了部分與轉換無關的檔案
├─build
├─config
├─src
│ ├─components
│ ├─pages
│ ├─store
│ ├─styles
│ ├─utils
│ │ ├─api.js
│ │ ├─index.js
│ │ ├─request.js
│ │ └─wx.js
│ ├─App.vue
│ └─main.js
├─package-lock.json
└─package.json
複製程式碼
轉換步驟
0.前期準備
- 建議使用 git 進行分支管理
- 儘量避免使用不必要的小程式特有標籤,如 text,image 等 #9137744
- 避免直接使用 wx 物件,使用
import wx from 'wx'
的方式引入,便於 web 中改寫 #c3ef6e7
// src/utils/wx.js
export default wx
複製程式碼
- 使用 flyio 作為請求庫,配置 alias 將 flyio 指向
flyio/dist/npm/wx
- 基於原分支新建 web-version 分支
1.修改打包配置
- 可以在原有配置基礎上修改,主要涉及 entry、target 及 loader 相關的配置項,這裡我直接通過 vue-cli 生成了一個新的專案,複製 build、config 資料夾及 eslint、babel 等的配置檔案替換原有配置,使用新專案的 package.json 並做相應修改,新建專案時各選項儘量與原專案保持一致 #ece3a76
- 修改 main.js,指定掛載元素,順利的話,這步之後執行
npm run dev
便已經可以跑起來了,有報錯的話解決相應錯誤即可
2.配置路由
- 新增 vue-router,並進行相應配置,建議使用 history 模式 #ddf94bc
- 修改路由引數獲取相關的程式碼 #b949197
- 使用 router-link 替換 a 標籤,避免頁面過載 #eb09297
3.調整請求介面
- 配置 alias 將 flyio 指向
flyio/dist/npm/fly
- 小程式中不會有跨域的問題,但 web 中需配合後端進行請求轉發或通過其他方式來解決這一問題 #f963975
4.轉換小程式元件及 API
- 底部導航欄,自己佈局實現 #8d6d98b
.nav(v-if="$route.meta.nav")
a.nav-item(href="/pages/news/list")
img.nav-icon(v-if="$route.name === 'NewsList'", src="/static/assets/news-active.png")
img.nav-icon(v-else, src="/static/assets/news.png")
.nav-title(:class="{ active: $route.name === 'NewsList' }") 資訊
a.nav-item(href="/pages/quanzi/list")
img.nav-icon(v-if="$route.name === 'QuanziList'", src="/static/assets/quanzi-active.png")
img.nav-icon(v-else, src="/static/assets/quanzi.png")
.nav-title(:class="{ active: $route.name === 'QuanziList' }") 圈子
複製程式碼
- rich-text 元件,使用 v-html 實現 #1945f3f
- swiper 元件,使用 vue-swiper-component 實現 #f4a4e1a
- toast 及 loading 介面,使用 vue2-toast 實現 #cb1d9d3
// src/utils/wx.js
import Vue from 'vue'
export default {
showNavigationBarLoading () {
Vue.prototype.$loading('載入中')
},
hideNavigationBarLoading () {
Vue.prototype.$loading.close()
},
showToast ({ title }) {
Vue.prototype.$toast.center(title)
}
}
複製程式碼
- 下拉重新整理及上拉載入,使用 vue-pull-to 實現 #e23b810
#app
pull-to(
ref="scroller",
:top-load-method="refresh",
:bottom-load-method="loadmore",
:is-top-bounce="!!onPullDownRefresh",
:is-bottom-bounce="!!onReachBottom",
@scroll="saveScrollPosition")
keep-alive
router-view(ref="current")
複製程式碼
import PullTo from 'vue-pull-to'
export default {
name: 'App',
mpType: 'app',
components: {
PullTo
},
data () {
return {
onPullDownRefresh: null,
onReachBottom: null
}
},
methods: {
async refresh (loaded) {
await this.onPullDownRefresh.call(this.$refs.current)
loaded()
},
async loadmore (loaded) {
await this.onReachBottom.call(this.$refs.current)
loaded()
},
saveScrollPosition (e) {
const { current } = this.$refs
current.scrollTop = e.srcElement.scrollTop
}
},
watch: {
$route () {
this.$nextTick(() => {
const { current } = this.$refs
if (!current) return
this.onPullDownRefresh = current.$options.onPullDownRefresh
this.onReachBottom = current.$options.onReachBottom
})
}
}
}
複製程式碼
5.Web 優化
- 使用 minireset 重置瀏覽器預設樣式,部分標籤在小程式中的預設樣式與瀏覽器不同,也需進行處理 #e98f5ba
- 引入 babel-polyfill,提高相容性 #c184166
維護
在初步完成 Web 版的轉換之後,便可以再次切換回主分支,後續的 feature 及 bugfix 均在主分支進行,待主分支發版後切換到 web 分支進行一次合併操作,可能會產生少量衝突,但也都會比較容易解決,最後處理下新引入的小程式特性即可,整體而言可維護性還是比較好的
總結
整個轉換過程還是比較順利的,主體部分約 1 個多小時完成,相對於小程式,web 的環境更為開放,所以大部分小程式的 api 可以通過各種方式模擬,由於是在兩個不同的分支進行,也可以放心地使用各種瀏覽器端的特性,但是樣式及指令碼儘量不要直接修改原有程式碼,可通過 mixin、新建 style 標籤等方式實現,避免造成衝突
展望
- 雙端統一的 UI 庫,目前來看只能使用一些簡單的 css 類庫
- 更好的路由支援,理想狀態下,可以通過 vue-router 的配置檔案自動生成各頁面的 main.js 檔案,並配置 entry,開發 .vue 檔案時,可以直接使用
this.$route
this.$router
及router-link
完成相關操作,避免每次手動修改
附
- Git 倉庫
- IT之家Lite:ithome-lite
- Mpvue:mpvue
- 專案模版:mpvue-quickstart
- 配置優化:mpvue-entry
- 路由相容(謹慎使用):mpvue-router-patch
- 打包工具(已支援 web 打包):mpvue-packager
- Demo
- IT之家Lite Web 版: ithome.f-loat.xyz