基於Vue2.js全家桶的移動端AppDEMO實現
好久沒更新過Vue的小文章,上次做了一個基於Vue+Mint-ui的移動端AppDemo,集成了推送功能,然後通過cordova打包生成apk,移動端表現還不錯,今天把這個小東西分享出來,希望有更多的小夥伴能夠用Vue去做一些有意思的東西,本人才疏學淺,有說的不對的地方,還請大家多多指教。下面按照慣例放上demo地址和原始碼地址,希望大家能給我點下star:
Demo (進去需要先註冊才能登入,用的localstorage,隨便寫符合格式的就行)
Demo基於Vue1的原始碼搭建專案
專案結構
本專案才用Vue-cli腳手架自動生成,這是一個Vue生態系統中一個偉大創舉。這意味著我們不需要手動構建我們的專案,而它就可以很快地為我們生成。下圖是一個完整的專案結構,如圖所示:
-
components:包含所有的頁面元件
-
vuex:包含vuex相關檔案
-
modules:存放每個頁面單獨的state和mutation
-
static:靜態檔案存放(圖片和圖示庫等)
-
index.html:渲染的頁面
-
main.js:應用入口點,包含根例項
-
App.vue:主頁面元件
專案流程:
-
安裝Vue-cli(要有node與npm)
npm i -g vue-cli
-
建立一個webpack專案,並且下載依賴
vue init webpack vue-demo-orderApp
cd vue-demo-orderApp
npm i
-
安裝Vue-router,Vuex和Mint-ui
npm install vue-router vuex --save
npm install mint-ui --save
-
熱載入開啟頁面(生產的時候執行
npm run build
)
npm run dev
專案的框架已經搭建好了,接下來就是為專案添磚加瓦。
頁面結構分析
--
本專案為一個demo專案,主要為了練習vue2的使用,結構上借鑑了官方的寫法,介面為通用的app樣式,才用餓了麼團隊的Mint-Ui的製作。
這個demo的每一個頁面都是一個.vue檔案,利用Vue的單檔案元件,非常便於管理每個頁面的狀態,樣式和資料,首頁主要是展示頁,和操作面板頁。下面是主頁的程式碼:
<template>
<div class="index-container">
<!-- 輪播圖部分 -->
<mt-swipe :auto="4000">
<mt-swipe-item><div class="banner1 banner" style="background:url('./static/banner1.jpg');background-size: cover;"></div></mt-swipe-item>
<mt-swipe-item><div class="banner2 banner" style="background:url('./static/banner2.jpg');background-size: cover;"></div></mt-swipe-item>
</mt-swipe>
<!-- 訂單同步狀態部分 -->
<mt-popup
class="status"
v-model="popupVisible"
popup-transition="popup-fade"
position="top">
同步{{ orders_status }}
</mt-popup>
<!-- 首頁功能欄部分 -->
<ul class="icon-list">
<li class="icon">
<router-link to="order" class="iconlink"></router-link>
<img src="../assets/scan.png" class="clear">
<h4>訂單管理</h4>
<p>掃描盤點,手工盤點</p>
<i></i>
</li>
<li class="icon">
<router-link to="goods" class="iconlink"></router-link>
<img src="../assets/ana.png" class="clear">
<h4>渠道管理</h4>
<p>掃描盤點,手工盤點</p>
<i></i>
</li>
<li class="icon">
<router-link to="order" class="iconlink"></router-link>
<img src="../assets/store.png" class="clear">
<h4>訂單釋出</h4>
<p>掃描盤點,手工盤點</p>
<i></i>
</li>
<li class="icon" @click="getOrders()">
<router-link to="test" class="iconlink"></router-link>
<img src="../assets/goods.png" class="clear">
<h4>訂單同步</h4>
<p>快速同步渠道訂單,方便快捷</p>
<i></i>
</li>
<li class="icon">
<router-link to="personinfo" class="iconlink"></router-link>
<img src="../assets/download.png" class="clear">
<h4>個人中心</h4>
<p>資訊管理,logo更換</p>
<i></i>
</li>
</ul>
</div>
</template>
<script type="text/javascript">
import { MessageBox } from 'mint-ui'
import { mapState } from 'vuex'
export default{
created:function(){
if(window.localStorage.user == null){
this.$router.push({path: '/login'})
}
},
data(){
let popupVisible = false
let orders_status
return {popupVisible, orders_status}
},
computed:mapState({
orders_status: state => state.news.orders_status,
}),
methods:{
getOrders: function(){
const that = this
this.$store.dispatch('synchroOrder', this).then(function(){
that.popupVisible = true
})
}
}
}
</script>
先看程式碼部分Vue2相比Vue1相比還是變化很多的,首先就是計算屬性比以前更好用了,其次是生命週期部分和以前相比變化很大,這點要注意下。其次是Vue2更推崇ES6的寫法,並且支援了promise,這是非常好的地方,而且官方的迭代文件也寫的很全,基本上很容易從1迭代到2。並且Vue2不再支援雙向繫結(sync)這個方法了,它使用了一種更好的方式來進行父子元件之間的通訊(emit),這樣子元件就不會影響到父元件的狀態。下面我放出這個主頁Vue1的程式碼,大家可以比較一下:
<template>
<div class="index-container">
<mt-swipe :auto="4000">
<mt-swipe-item><div class="banner1 banner" style="background:url('./static/banner1.jpg');background-size: cover;"></div></mt-swipe-item>
<mt-swipe-item><div class="banner2 banner" style="background:url('./static/banner2.jpg');background-size: cover;"></div></mt-swipe-item>
</mt-swipe>
<ul class="icon-list">
<li class="icon">
<img src="../assets/scan.png" class="clear">
<h4>訂單管理</h4>
<p>掃描盤點,手工盤點</p>
<i></i>
</li>
<li class="icon">
<img src="../assets/ana.png" class="clear">
<h4>渠道管理</h4>
<p>掃描盤點,手工盤點</p>
<i></i>
</li>
<li class="icon">
<img src="../assets/store.png" class="clear">
<h4>訂單釋出</h4>
<p>掃描盤點,手工盤點</p>
<i></i>
</li>
<li class="icon" @click="getOrders(this)">
<img src="../assets/goods.png" class="clear">
<h4>訂單同步</h4>
<p>快速同步渠道訂單,方便快捷</p>
<i></i>
</li>
<li class="icon">
<img src="../assets/download.png" class="clear">
<h4>個人中心</h4>
<p>資訊管理,logo更換</p>
<i></i>
</li>
</ul>
<mt-popup
:visible.sync="popupVisible"
popup-transition="popup-fade"
position="top">
同步成功</mt-popup>
</div>
</template>
<script type="text/javascript">
import { synchroOrder } from '../vuex/action'
import { MessageBox } from 'mint-ui'
export default{
init:function(){
if(window.localStorage.user == null){
//window.location.href = window.location.origin + window.location.pathname + '#!/login'
console.log('請登入')
this.$router.go({path:'/login'})
}
},
data(){
let popupVisible = false
return {popupVisible}
},
vuex:{
getters:{
order_status: state => state.orders_status
},
actions:{
synchroOrder
}
},
methods:{
getOrders: function(that){
this.synchroOrder(that)
if(this.order_status){
this.popupVisible = !this.popupVisible
}
}
}
}
上面的程式碼比較可以看出,VueX和Vue-router的變化也很大,這裡我就詳細說這兩者的變化了,有啥問題可以討論討論,大概說下,首先是Vue-router部分,不再支援以前V-link的這種方式了,變為採用router-link這種方式。VueX方面我感覺變化最大的就是寫法和以前不一樣了。Vuex才用 this.$store.dispatch('xxx')
來派發一個action,通過commit委託給mutation來執行相應的操作,並且支援非同步的寫法,就是ES6的promise,給一段官方的非同步寫法:
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
。還有一個明顯的變化是mapActions和mapState屬性,mapActions可以用來指明一個元件的方法去呼叫store.dispatch()方法。通過mapState屬性我們可以去定義一些計算函式和鍵值對,主要是為了方便運用多個states屬性和getters。還有一個比較大的變化就是Vuex2可以支援將store轉變為Module的寫法,來更細緻的去管理狀態。我的這個小demo也用上了這個新特性,它能讓大型的頁面也能有很好的狀態管理。
可以對比一下同一個專案基於Vue1和Vue2的寫法。這樣更能夠直觀的去了解到不同之處,並且可以去細想一下作者為什麼這個改,這對我們程式設計思想的提示是很有幫助的。
基於模組化的Vuex
將不同的Vuex狀態放在對應的頁面狀態模組裡,這樣當需要管理的資料很多的時候也能從容的應對。
可以看下這裡面是怎麼寫的,下面是news.js裡面的:
import * as types from '../mutation-types'
const state = {
news:{},
orders_status: '成功',
selected:'首頁'
}
const mutations = {
[types.SYNCHRO_ORDER](state, items){
state.news = items
console.log(state.news.length)
if(state.news.length != 0){
state.orders_status = '成功'
}
else{
state.orders_status = '失敗'
}
},
[types.CHANGE_SELECTED](state, item){
state.selected = item
}
}
export default{
state,
mutations
}
下面是mution-types.js
export const CHANGE_ORDER = 'CHANGE_ORDER'
export const CHANGE_STATUS = 'CHANGE_STATUS'
export const DISPLAY_STATUS = 'DISPLAY_STATUS'
export const CHANGE_PERSON = 'CHANGE_PERSON'
export const SYNCHRO_ORDER = 'SYNCHRO_ORDER'
export const CHANGE_POP = 'CHANGE_POP'
export const CHANGE_SELECTED = 'CHANGE_SELECTED'
可以看到我們將所有的mutaions方法都放在了mution-types裡面進行統一的管理,然後再對應的模組裡面來處理這些方法,在不同的模組裡面我們只能操作對應模組的資料和狀態,這對於狀態管理來說簡直是非常完美。