從零開始搭建vue移動端項目到上線

先來看一波效果圖css

 

初始化項目html

一、在安裝了node.js的前提下,使用如下命令vue

npm install --g vue-clinode

二、在將要構建項目的目錄下android

vue init webpack myproject(項目目錄名稱)webpack

一路回車以下ios

中間會讓選擇ESLint進行項目代碼風格檢查,爲了美觀和效率,能夠開起來,vue-router用起來,紅框框中的兩個測試,不要也罷,後面是問要使用哪一個進行install依賴包,默認npm好了;而後回車,等待下載依賴;慢的話能夠用鏡像nginx

下載完成以後會看到以下提示:git

按照步驟往下走就行了github

接下來在瀏覽器裏輸入localhost:8080,就能夠進入到vue的世界了

只有這些還不夠,這距離一個響應式的app框架還差好多,接下來就正式搭建一個移動端的項目吧。

 首先咱們來看一下剛構建好的vue的項目結構

能夠發現項目中有assets和static兩個文件夾可存放靜態文件,那豈不是衝突了?其實否則,assets中存放的靜態文件是會通過webpack處理的,通常放一些圖片之類的靜態資源,而static則不會收到webpack的影響,調用的時候也是經過絕對路徑調用的,一般用來存放一些第三方的靜態資源庫。

此項目將基於vue-cli的項目目錄進行改造,使其集成vue-router、vuex、axios,並且能夠自動適配移動端大小。

在開始寫代碼以前,先說一下ESlint警告和報錯,能夠選擇性修改校驗規則,點擊參考修改,也可使用 /* eslint-disable */ 選擇性忽略校驗

路由(vue-router)

一個項目的路由是一個項目的基礎,咱們先從路由開始,在剛一開始初始化項目的時候,vue-router就被引進項目裏來了,上面的圖片裏在src\router裏面放的就是路由配置文件,按照我的習慣我將對上面的目錄結構進行調整,以下

新建page目錄存放主邏輯頁面,components存放公共組件,router統一管理路由

如圖引入新的頁面,路由跳轉可經過this.$router.push('/Home')

路由vue-cli都給封裝的差很少了,倒也沒什麼要大改的地方,接下來來看下vuex

vuex(狀態管理模塊)

關於vuex的介紹官網也給了比較詳細的介紹,對其做用不太瞭解的話能夠參考什麼是vuex,這裏只說怎麼集成在項目裏面,而且簡單介紹其用法

(1)安裝vuex

npm install vuex --save

(2)配置vuex

根據我的開發習慣,項目中vuex的配置也不相同,不過大致都差很少,也有差異大的地方,比方說官網推薦在actions裏寫異步操做改變state狀態,可是我仍是比較喜歡將請求數據等異步操做放在store外面操做,在經過commit去改變狀態,具體將會在下面的數據請求模塊的封裝裏提到

廢話很少說了,看下面圖片

首先建立了一個狀態的文件夾,用於管理整個狀態;在modules裏面分開來寫各個模塊的狀態,以下

 1 /**
 2  * home.js
 3  * 用於home模塊的狀態管理
 4  */
 5 import * as types from '../mutation-type'  // 引入定義的方法
 6 const home = {
 7   state: {
 8     number: 1
 9   },
10   mutations: {
11     [types.SET_NUM](state, num) {   // 修改state 可經過mapMutations調用
12       state.number = num
13     }
14   },
15   actions: {},
16   getters: {            // 定義getters,能夠經過mapGetters拓展函數調用
17     number: state => {
18       return state.number
19     }
20   }
21 }
22 export default home    // 輸出home模塊

mutation-type定義了一些修改state的方法,以下

在index.js統一輸出,以下

 1 import Vue from 'vue'
 2 import Vuex from 'vuex'
 3 import home from './modules/home'
 4 import createLogger from 'vuex/dist/logger'
 5 
 6 Vue.use(Vuex)
 7 const debug = true
 8 
 9 export default new Vuex.Store({
10   modules: {
11     home
12   },
13   plugins: debug ? [createLogger()] : []   // 是否開啓vuex的debug模式
14 })

這裏用到了一個vuex的內置插件,如上圖,開啓以後狀態的每次改變均可以在console裏面查看修改信息以下圖

這裏的index配置好以後就是要在main.js裏註冊一下

經過以上幾步設置,就能夠在項目裏面使用狀態了,這裏以home.vue爲例,看下面代碼

 1 import {mapMutations, mapGetters, mapState} from 'vuex'  // 引入map方法
 2 export default {
 3   data () {
 4     return {
 5       num: 0
 6     }
 7   },
 8   methods: {
 9     ...mapMutations({            // 調用setNum方法
10       setNum: 'SET_NUM'
11     }),
12     increase() {
13       this.num++
14       this.setNum(this.num)      // 將this.num轉入setNum
15     }
16   },
17   computed: {
18     // ...mapGetters([           // 經過getters獲取state數據
19     //   'number'
20     // ]),
21     ...mapState({                // 經過state獲取state數據
22       number: state => state.home.number
23     })
24   }

到這裏vuex的引入就結束了,下面來繼續看數據請求模塊(axios)

axios(數據請求模塊)

以前vue數據請求模塊用的是vue-resource,官方不推薦,棄之;說下axios的集成步驟,以及須要注意的一些地方

(1)安裝axios和js-cookie

npm install axios --save

(2)配置axios

在src目錄下面新建apiconfig文件夾,用來封裝請求和定義一些關於請求的全局變量;同時建立api文件夾,用來分別聲明各個模塊的請求方法,以下圖

先來看apiconfig裏的公共封裝部分;這裏會對請求作如下處理

  • 定義一些像請求返回成功的狀態、請求超時時間等常量,
  • 對請求作一次公共的封裝,
  • 對token的存儲和攔截當操做,

下面看代碼

 1 /* eslint-disable */
 2 import axios from 'axios'
 3 
 4 /**
 5 * 定義請求常量
 6 * TIME_OUT、ERR_OK
 7 */
 8 export const TIME_OUT = 1000;    // 請求超時時間
 9 export const ERR_OK = true;      // 請求成功返回狀態,字段和後臺統一
10 export const baseUrl = process.env.BASE_URL   // 引入全局url,定義在全局變量process.env中,開發環境爲了方便轉發,值爲空字符串
11 
12 // 請求超時時間
13 axios.defaults.timeout = TIME_OUT
14 
15 // 封裝請求攔截
16 axios.interceptors.request.use(
17     config => {
18         let token = localStorage.getItem('token')   // 獲取token
19         config.headers['Content-Type'] = 'application/json;charset=UTF-8'
20         config.headers['Authorization'] = ''
21         if(token != null){                          // 若是token不爲null,不然傳token給後臺
22             config.headers['Authorization'] = token
23         }
24         return config
25     },
26     error => {
27         return Promise.reject(error)
28     }
29 )
30 // 封裝響應攔截,判斷token是否過時
31 axios.interceptors.response.use(
32   response => {
33     let {data} = response
34     if (data.message === 'token failure!') {    // 若是後臺返回的錯誤標識爲token過時,則從新登陸
35       localStorage.removeItem('token')          // token過時,移除token
36       // 進行從新登陸操做
37     } else {
38       return Promise.resolve(response)
39     }
40   },
41   error => {
42     return Promise.reject(error)
43   }
44 )
45 // 封裝post請求
46 export function fetch(requestUrl, params = '') {
47   return axios({
48     url: requestUrl,
49     method: 'post',
50     data: {
51       'body': params
52     }
53   })
54 }

以上代碼以post請求爲例,對請求進行公共封裝,而且定義了一些常量以供請求使用,另外分別對請求和響應進行了攔截,方便在請求或者數據返回時,對數據進行統一處理,具體在代碼的註釋裏均可以看到,下面就以登陸爲例,對封裝的請求方法進行調用。

下面來看api模塊部分,以home-api爲例,看代碼

 1 /**
 2  * 引入fetch、baseUrl
 3  * @param params
 4  * @returns {*}
 5  */
 6 import {fetch, baseUrl} from 'config/index'
 7 // 登陸接口
 8 export function loginUserNo(params) {
 9   return fetch(`${baseUrl}/root/login/checkMemberLogin`, params)
10 }

在文件裏引入fetch方法和baseUrl,這裏爲何能夠簡寫成'config/index'呢,須要在'build/webpack.base.conf.js'裏添加如下代碼,後面引入api同理

這裏export登陸方法loginUserNo以後,就能夠在組件裏面使用這個登陸方法了,以下代碼

 1 import * as homeApi from 'api/home-api'  // 引入api
 2 import { ERR_OK } from 'config/index'    // 引入請求成功狀態
 3 // 請求方法
 4 login() {
 5     let params = {
 6         password: '*******',
 7         storeNo: '',
 8         userName: '*********'
 9     }
10     homeApi.loginUserNo(params).then((res) => {
11         let {data} = res
12         if (data.success === ERR_OK) {
13             // 請求成功操做,存儲token
14             localStorage.setItem('token', data.value.token)
15         } else {
16         }
17       }).catch(() => {
18       })
19     }
20 }

在點擊登陸以後執行登陸方法,就能夠調用請求方法了,可是這裏還有一個問題

關於數據請求,避不開的一個老生常談的問題就是跨域,一樣的上面點擊登陸也會涉及到跨域沒法請求的問題,不過好在vue-cli裏面已經配置瞭解決跨域問題的模塊,咱們能夠在config/index.js裏面配置如下要代理的地址,以下圖

將以root開頭的api轉發出去,將地址指向接口地址,這樣就解決了跨域的問題。

到此,vue全家桶的引入及應用就基本完成了,可是到目前爲止這個項目還只能進行簡單的路由跳轉、狀態存儲以及數據請求,而咱們的目標是一個移動端應用框架,接下來咱們還要解決以下幾個問題

  • 移動端適配問題
  • 移動端ui框架的引入
  • 項目組織架構的優化問題

下面咱們就先從移動端適配問題入手

項目的適配

由於移動端設備屏幕大小,屏幕比例什麼的差異比較大,因此移動端項目的適配問題就顯得尤其重要,這裏咱們主要使用flexible.js進行適配,關於flexible.js,不懂得話能夠點這裏,這裏咱們以最經常使用的750*1334的尺寸爲例

引入flexible.js,在main.js裏引入flexible.js文件,可將flexible.js做爲靜態文件放在最外層static文件夾裏引入,以下圖

使用less做爲css預處理器,首先安裝less

(1)安裝less和less-loader

npm install less less-loader --save-dev

(2)配置less

在build/webpack.base.conf.js 的module.exports.module.rules 裏面添加

1 {
2     test: /\.less$/,
3     loader: 'style-loader!css-loader!less-loader'
4 },

而後在組件裏面使用的時候,在style標籤上加上 lang="less",就能夠正常的使用less了,這裏咱們來引入幾個初始化項目的less文件,在src下面建立styles文件夾,放入如下文件

在每一個組件裏的style標籤裏引入index.less和variable.less

 1 <style scoped lang="less">
 2 @import "~styles/index.less";
 3 @import "~styles/variable.less";
 4 .hello{
 5   h1{
 6     color: red;
 7     .fs(38);     // mixin裏數字大小函數
 8   }
 9 }
10 </style>

 而後上面寫關於像素的樣式的時候,都在mixin.less定義下,就能夠實現對全部移動端的適配問題。

移動端頁面切換及切換動畫

此處將切換動畫單獨拿出來講如下,做爲移動端通常要實現的需求是,第一級菜單切換不須要轉場動畫,第一級菜單向第二級菜單轉場時須要過渡動畫;針對這一需求提供如下解決方案。

須要用到動畫的話確定會用到vue的transition,不熟悉的話能夠看這裏,這裏實現動畫的解決方案是判斷要執行路由的方向,以下代碼,在路由配置文件裏定義路由的方法

 1 // 須要左方向動畫的路由用this.$router.to('****')
 2 Router.prototype.togo = function (path) {
 3   this.isleft = true
 4   this.isright = false
 5   this.push(path)
 6 }
 7 // 須要右方向動畫的路由用this.$router.goRight('****')
 8 Router.prototype.goRight = function (path) {
 9   this.isright = true
10   this.isleft = false
11   this.push(path)
12 }
13 // 須要返回按鈕動畫的路由用this.$router.goBack(),返回上一個路由
14 Router.prototype.goBack = function () {
15   this.isright = true
16   this.isleft = false
17   this.go(-1)
18 }
19 // 點擊瀏覽器返回按鈕執行,此時不須要路由回退
20 Router.prototype.togoback = function () {
21   this.isright = true
22   this.isleft = false
23 }

上面在執行路由跳轉的時候,在App.vue裏面判斷滑動的方向,來指定動畫的方向,不須要動畫的話,能夠直接使用this.$router.push('****'),下面是App.vue裏處理的動畫代碼

<template>
  <div id="app">
    <transition :name="transitionName">
      <router-view class="Router"></router-view>
    </transition>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      transitionName: 'slideleft'
    }
  },
  watch: {
    $route() {   // 監聽路由變化從新賦值
      if (this.$router.isleft) {
        this.transitionName = 'slideleft'
      }
      if (this.$router.isright) {
        this.transitionName = 'slideright'
      }
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
.Router {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  width: 100%;
  height: 100%;
  transition: all .5s ease;
  -webkit-transition: all .5s ease;
  -moz-transition: all .5s ease;
}
.slideleft-enter,
 .slideright-leave-active {
  opacity: 0;
  -webkit-transform: translate(100%, 0);
  transform: translate(100%, 0);
}
.slideleft-leave-active,
.slideright-enter {
  opacity: 0;
  -webkit-transform: translate(-100%, 0);
  transform: translate(-100%, 0);
}
</style>

在組件中使用的話則使用

1 this.$router.goBack()   // 返回
2 this.$router.to('****')  // 進入到詳情

還有一步,就是監聽點擊瀏覽器返回按鈕,在main.js裏寫以下代碼

1 window.addEventListener('popstate', function(e) {
2   router.togoback()   // router已經在上面import進來
3 }, false)

移動端UI框架選擇

 做爲移動端項目,上面步驟其實已經算完善了,可是每每會遇到項目工期緊,或者缺乏人手的時候,這個時候引入一個移動端的UI就如虎添翼了,不用本身去封裝一些ui組件了,這裏使用mint-ui,優勢可自行搜索,這裏講一下對mint-ui的引入。

(1)安裝mint-ui

npm install mint-ui --save

(2)引入mint-ui

在main.js裏引入mint-ui

1 import Mint from 'mint-ui'
2 import 'mint-ui/lib/style.css'  // 引入css
3 Vue.use(Mint)   // 全局使用

這樣就能夠在整個vue項目裏面使用mint-ui的組件了。

打包

打包遇到的一些問題

(1)打包以後在ios上點擊元素會閃出來一個半透明的灰色框,這裏須要加一句css作下兼容-webkit-tap-highlight-color:rgba(0,0,0,0); 放入#app的css裏

(2)點擊事件右300ms的延遲,可採用fastclick.js解決,參考如下代碼

1 npm install fastclick --save
2 
3 // 在main.js引入
4 import FastClick from 'fastclick'
5 FastClick.attach(document.body)

打包注意事項

若是將項目打包用於移動端瀏覽器,則直接打包,不須要更改其它的東西,在包以後上傳至服務器,使用nginx作下接口轉發便可

若是想將打包的靜態文件進一步打包成移動端應用,則須要修改如下config/index.js

在config/prod.env.js新增baseUrl

打包成app以後,移動端不會存在跨域問題。

寫在最後

上面項目純屬我的搭建,適用於移動端項目,包括瀏覽器端,微信公衆號以及打包以後的android,ios應用,目前還存在一些不足的地方,不過基本功能能夠正常使用,具體的代碼,若有須要可在個人github中下載使用,若是以爲對你有用,請給我點贊,若有修改建議,請提出。

項目地址:https://github.com/MrKaKaluote/vue-mobile.git

項目新增了mock功能,具體看這裏:vue項目配置Mock.js

相關文章
相關標籤/搜索