從零開始搭建vue移動端項(xiàng)目到上線的步驟
初始化項(xiàng)目
1、在安裝了node.js的前提下,使用以下命令
npm install --g vue-cli
2、在將要構(gòu)建項(xiàng)目的目錄下
vue init webpack myproject(項(xiàng)目目錄名稱)
一路回車如下

中間會讓選擇ESLint進(jìn)行項(xiàng)目代碼風(fēng)格檢查,為了美觀和效率,可以開起來,vue-router用起來,紅框框中的兩個測試,不要也罷,后面是問要使用哪個進(jìn)行install依賴包,默認(rèn)npm好了;然后回車,等待下載依賴;慢的話可以用鏡像。
下載完成之后會看到如下提示:

按照步驟往下走就好了
接下來在瀏覽器里輸入localhost:8080,就可以進(jìn)入到vue的世界了

只有這些還不夠,這距離一個響應(yīng)式的app框架還差好多,接下來就正式搭建一個移動端的項(xiàng)目吧。
首先我們來看一下剛構(gòu)建好的vue的項(xiàng)目結(jié)構(gòu)

可以發(fā)現(xiàn)項(xiàng)目中有assets和static兩個文件夾可存放靜態(tài)文件,那豈不是沖突了?其實(shí)不然,assets中存放的靜態(tài)文件是會經(jīng)過webpack處理的,一般放一些圖片之類的靜態(tài)資源,而static則不會收到webpack的影響,調(diào)用的時候也是通過絕對路徑調(diào)用的,通常用來存放一些第三方的靜態(tài)資源庫。
此項(xiàng)目將基于vue-cli的項(xiàng)目目錄進(jìn)行改造,使其集成vue-router、vuex、axios,而且可以自動適配移動端大小。
在開始寫代碼之前,先說一下ESlint警告和報(bào)錯,可以選擇性修改校驗(yàn)規(guī)則,點(diǎn)擊參考修改,也可以使用 /* eslint-disable */ 選擇性忽略校驗(yàn)
路由(vue-router)
一個項(xiàng)目的路由是一個項(xiàng)目的基礎(chǔ),我們先從路由開始,在剛一開始初始化項(xiàng)目的時候,vue-router就被引進(jìn)項(xiàng)目里來了,上面的圖片里在src\router里面放的就是路由配置文件,按照個人習(xí)慣我將對上面的目錄結(jié)構(gòu)進(jìn)行調(diào)整,如下

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

如圖引入新的頁面,路由跳轉(zhuǎn)可通過this.$router.push('/Home')
路由vue-cli都給封裝的差不多了,倒也沒什么要大改的地方,接下來來看下vuex
vuex(狀態(tài)管理模塊)
關(guān)于vuex的介紹官網(wǎng)也給了比較詳細(xì)的介紹,對其作用不太了解的話可以參考什么是vuex,這里只說怎么集成在項(xiàng)目里面,并且簡單介紹其用法
(1)安裝vuex
npm install vuex --save
(2)配置vuex
根據(jù)個人開發(fā)習(xí)慣,項(xiàng)目中vuex的配置也不相同,不過大體都差不多,也有差別大的地方,比方說官網(wǎng)推薦在actions里寫異步操作改變state狀態(tài),但是我還是比較喜歡將請求數(shù)據(jù)等異步操作放在store外面操作,在通過commit去改變狀態(tài),具體將會在下面的數(shù)據(jù)請求模塊的封裝里提到
廢話不多說了,看下面圖片

首先創(chuàng)建了一個狀態(tài)的文件夾,用于管理整個狀態(tài);在modules里面分開來寫各個模塊的狀態(tài),如下
/**
* home.js
* 用于home模塊的狀態(tài)管理
*/
import * as types from '../mutation-type' // 引入定義的方法
const home = {
state: {
number: 1
},
mutations: {
[types.SET_NUM](state, num) { // 修改state 可通過mapMutations調(diào)用
state.number = num
}
},
actions: {},
getters: { // 定義getters,可以通過mapGetters拓展函數(shù)調(diào)用
number: state => {
return state.number
}
}
}
export default home // 輸出home模塊
mutation-type定義了一些修改state的方法,如下

在index.js統(tǒng)一輸出,如下
import Vue from 'vue'
import Vuex from 'vuex'
import home from './modules/home'
import createLogger from 'vuex/dist/logger'
Vue.use(Vuex)
const debug = true
export default new Vuex.Store({
modules: {
home
},
plugins: debug ? [createLogger()] : [] // 是否開啟vuex的debug模式
})
這里用到了一個vuex的內(nèi)置插件,如上圖,開啟之后狀態(tài)的每次改變都可以在console里面查看修改信息如下圖

這里的index配置好之后就是要在main.js里注冊一下

通過以上幾步設(shè)置,就可以在項(xiàng)目里面使用狀態(tài)了,這里以home.vue為例,看下面代碼
import {mapMutations, mapGetters, mapState} from 'vuex' // 引入map方法
export default {
data () {
return {
num: 0
}
},
methods: {
...mapMutations({ // 調(diào)用setNum方法
setNum: 'SET_NUM'
}),
increase() {
this.num++
this.setNum(this.num) // 將this.num轉(zhuǎn)入setNum
}
},
computed: {
// ...mapGetters([ // 通過getters獲取state數(shù)據(jù)
// 'number'
// ]),
...mapState({ // 通過state獲取state數(shù)據(jù)
number: state => state.home.number
})
}
到這里vuex的引入就結(jié)束了,下面來繼續(xù)看數(shù)據(jù)請求模塊(axios)
axios(數(shù)據(jù)請求模塊)
之前vue數(shù)據(jù)請求模塊用的是vue-resource,官方不推薦,棄之;說下axios的集成步驟,以及需要注意的一些地方
(1)安裝axios和js-cookie
npm install axios --save
(2)配置axios
在src目錄下面新建apiconfig文件夾,用來封裝請求和定義一些關(guān)于請求的全局變量;同時創(chuàng)建api文件夾,用來分別聲明各個模塊的請求方法,如下圖

先來看apiconfig里的公共封裝部分;這里會對請求做以下處理
- 定義一些像請求返回成功的狀態(tài)、請求超時時間等常量,
- 對請求做一次公共的封裝,
- 對token的存儲和攔截當(dāng)操作,
下面看代碼
/* eslint-disable */
import axios from 'axios'
/**
* 定義請求常量
* TIME_OUT、ERR_OK
*/
export const TIME_OUT = 1000; // 請求超時時間
export const ERR_OK = true; // 請求成功返回狀態(tài),字段和后臺統(tǒng)一
export const baseUrl = process.env.BASE_URL // 引入全局url,定義在全局變量process.env中,開發(fā)環(huán)境為了方便轉(zhuǎn)發(fā),值為空字符串
// 請求超時時間
axios.defaults.timeout = TIME_OUT
// 封裝請求攔截
axios.interceptors.request.use(
config => {
let token = localStorage.getItem('token') // 獲取token
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
config.headers['Authorization'] = ''
if(token != null){ // 如果token不為null,否則傳token給后臺
config.headers['Authorization'] = token
}
return config
},
error => {
return Promise.reject(error)
}
)
// 封裝響應(yīng)攔截,判斷token是否過期
axios.interceptors.response.use(
response => {
let {data} = response
if (data.message === 'token failure!') { // 如果后臺返回的錯誤標(biāo)識為token過期,則重新登錄
localStorage.removeItem('token') // token過期,移除token
// 進(jìn)行重新登錄操作
} else {
return Promise.resolve(response)
}
},
error => {
return Promise.reject(error)
}
)
// 封裝post請求
export function fetch(requestUrl, params = '') {
return axios({
url: requestUrl,
method: 'post',
data: {
'body': params
}
})
}
以上代碼以post請求為例,對請求進(jìn)行公共封裝,并且定義了一些常量以供請求使用,另外分別對請求和響應(yīng)進(jìn)行了攔截,方便在請求或者數(shù)據(jù)返回時,對數(shù)據(jù)進(jìn)行統(tǒng)一處理,具體在代碼的注釋里都可以看到,下面就以登錄為例,對封裝的請求方法進(jìn)行調(diào)用。
下面來看api模塊部分,以home-api為例,看代碼
/**
* 引入fetch、baseUrl
* @param params
* @returns {*}
*/
import {fetch, baseUrl} from 'config/index'
// 登錄接口
export function loginUserNo(params) {
return fetch(`${baseUrl}/root/login/checkMemberLogin`, params)
}
在文件里引入fetch方法和baseUrl,這里為什么可以簡寫成'config/index'呢,需要在'build/webpack.base.conf.js'里添加以下代碼,后面引入api同理

這里export登錄方法loginUserNo之后,就可以在組件里面使用這個登錄方法了,如下代碼
import * as homeApi from 'api/home-api' // 引入api
import { ERR_OK } from 'config/index' // 引入請求成功狀態(tài)
// 請求方法
login() {
let params = {
password: '*******',
storeNo: '',
userName: '*********'
}
homeApi.loginUserNo(params).then((res) => {
let {data} = res
if (data.success === ERR_OK) {
// 請求成功操作,存儲token
localStorage.setItem('token', data.value.token)
} else {
}
}).catch(() => {
})
}
}
在點(diǎn)擊登錄之后執(zhí)行登錄方法,就可以調(diào)用請求方法了,但是這里還有一個問題
關(guān)于數(shù)據(jù)請求,避不開的一個老生常談的問題就是跨域,同樣的上面點(diǎn)擊登錄也會涉及到跨域無法請求的問題,不過好在vue-cli里面已經(jīng)配置了解決跨域問題的模塊,我們可以在config/index.js里面配置以下要代理的地址,如下圖

將以root開頭的api轉(zhuǎn)發(fā)出去,將地址指向接口地址,這樣就解決了跨域的問題。
到此,vue全家桶的引入及應(yīng)用就基本完成了,但是到目前為止這個項(xiàng)目還只能進(jìn)行簡單的路由跳轉(zhuǎn)、狀態(tài)存儲以及數(shù)據(jù)請求,而我們的目標(biāo)是一個移動端應(yīng)用框架,接下來我們還要解決如下幾個問題
- 移動端適配問題
- 移動端ui框架的引入
- 項(xiàng)目組織架構(gòu)的優(yōu)化問題
下面我們就先從移動端適配問題入手
項(xiàng)目的適配
因?yàn)橐苿佣嗽O(shè)備屏幕大小,屏幕比例什么的差別比較大,所以移動端項(xiàng)目的適配問題就顯得尤為重要,這里我們主要使用flexible.js進(jìn)行適配,關(guān)于flexible.js,不懂得話可以點(diǎn)這里,這里我們以最常用的750*1334的尺寸為例
引入flexible.js,在main.js里引入flexible.js文件,可將flexible.js作為靜態(tài)文件放在最外層static文件夾里引入,如下圖

使用less作為css預(yù)處理器,首先安裝less
(1)安裝less和less-loader
npm install lessless-loader --save-dev
(2)配置less
在build/webpack.base.conf.js 的module.exports.module.rules 里面添加
{
test: /\.less$/,
loader: 'style-loader!css-loader!less-loader'
},
然后在組件里面使用的時候,在style標(biāo)簽上加上 lang="less",就可以正常的使用less了,這里我們來引入幾個初始化項(xiàng)目的less文件,在src下面創(chuàng)建styles文件夾,放入以下文件

在每個組件里的style標(biāo)簽里引入index.less和variable.less
<style scoped lang="less">
@import "~styles/index.less";
@import "~styles/variable.less";
.hello{
h1{
color: red;
.fs(38); // mixin里數(shù)字大小函數(shù)
}
}
</style>
然后上面寫關(guān)于像素的樣式的時候,都在mixin.less定義下,就可以實(shí)現(xiàn)對所有移動端的適配問題。
移動端頁面切換及切換動畫
此處將切換動畫單獨(dú)拿出來說以下,作為移動端一般要實(shí)現(xiàn)的需求是,第一級菜單切換不需要轉(zhuǎn)場動畫,第一級菜單向第二級菜單轉(zhuǎn)場時需要過渡動畫;針對這一需求提供以下解決方案。
需要用到動畫的話肯定會用到vue的transition,不熟悉的話可以看這里,這里實(shí)現(xiàn)動畫的解決方案是判斷要執(zhí)行路由的方向,如下代碼,在路由配置文件里定義路由的方法
// 需要左方向動畫的路由用this.$router.to('****')
Router.prototype.togo = function (path) {
this.isleft = true
this.isright = false
this.push(path)
}
// 需要右方向動畫的路由用this.$router.goRight('****')
Router.prototype.goRight = function (path) {
this.isright = true
this.isleft = false
this.push(path)
}
// 需要返回按鈕動畫的路由用this.$router.goBack(),返回上一個路由
Router.prototype.goBack = function () {
this.isright = true
this.isleft = false
this.go(-1)
}
// 點(diǎn)擊瀏覽器返回按鈕執(zhí)行,此時不需要路由回退
Router.prototype.togoback = function () {
this.isright = true
this.isleft = false
}
上面在執(zhí)行路由跳轉(zhuǎn)的時候,在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() { // 監(jiān)聽路由變化重新賦值
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>
在組件中使用的話則使用
this.$router.goBack() // 返回
this.$router.to('****') // 進(jìn)入到詳情
還有一步,就是監(jiān)聽點(diǎn)擊瀏覽器返回按鈕,在main.js里寫如下代碼
window.addEventListener('popstate', function(e) {
router.togoback() // router已經(jīng)在上面import進(jìn)來
}, false)
移動端UI框架選擇
作為移動端項(xiàng)目,上面步驟其實(shí)已經(jīng)算完善了,但是往往會遇到項(xiàng)目工期緊,或者缺少人手的時候,這個時候引入一個移動端的UI就如虎添翼了,不用自己去封裝一些ui組件了,這里使用mint-ui,優(yōu)點(diǎn)可自行搜索,這里講一下對mint-ui的引入。
(1)安裝mint-ui
npm install mint-ui --save
(2)引入mint-ui
在main.js里引入mint-ui
import Mint from 'mint-ui' import 'mint-ui/lib/style.css' // 引入css Vue.use(Mint) // 全局使用
這樣就可以在整個vue項(xiàng)目里面使用mint-ui的組件了。
打包
打包遇到的一些問題
(1)打包之后在ios上點(diǎn)擊元素會閃出來一個半透明的灰色框,這里需要加一句css做下兼容-webkit-tap-highlight-color:rgba(0,0,0,0); 放入#app的css里
(2)點(diǎn)擊事件右300ms的延遲,可采用fastclick.js解決,參考以下代碼
npm install fastclick --save // 在main.js引入 import FastClick from 'fastclick' FastClick.attach(document.body)
打包注意事項(xiàng)
如果將項(xiàng)目打包用于移動端瀏覽器,則直接打包,不需要更改其它的東西,在包之后上傳至服務(wù)器,使用nginx做下接口轉(zhuǎn)發(fā)即可
如果想將打包的靜態(tài)文件進(jìn)一步打包成移動端應(yīng)用,則需要修改以下config/index.js

在config/prod.env.js新增baseUrl

打包成app之后,移動端不會存在跨域問題。
寫在最后
上面項(xiàng)目純屬個人搭建,適用于移動端項(xiàng)目,包括瀏覽器端,微信公眾號以及打包之后的android,ios應(yīng)用,目前還存在一些不足的地方,不過基本功能可以正常使用,具體的代碼,如有需要可在我的github中下載使用,如果覺得對你有用,請給我點(diǎn)贊,如有修改建議,請?zhí)岢觥?/p>
項(xiàng)目地址:https://github.com/MrKaKaluote/vue-mobile.git
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解決uniapp項(xiàng)目在微信開發(fā)工具里打開報(bào)錯Error:app.json:在項(xiàng)目根目錄未找到app.json
這篇文章主要給大家介紹了關(guān)于解決uniapp項(xiàng)目在微信開發(fā)工具里打開報(bào)錯Error:app.json:在項(xiàng)目根目錄未找到app.json的相關(guān)資料,文中通過圖文將解決的辦法介紹的非常詳細(xì),需要的朋友可以參考下2024-03-03
vue實(shí)現(xiàn)websocket客服聊天功能
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)websocket客服聊天功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
Vue路由傳遞參數(shù)與重定向的使用方法總結(jié)
路由的本質(zhì)就是一種對應(yīng)關(guān)系,比如說我們在url地址中輸入我們要訪問的url地址之后,瀏覽器要去請求這個url地址對應(yīng)的資源,下面這篇文章主要給大家介紹了關(guān)于Vue路由傳遞參數(shù)與重定向的使用方法,需要的朋友可以參考下2022-10-10
vue elementUI實(shí)現(xiàn)自定義正則規(guī)則驗(yàn)證
本文主要介紹了vue elementUI實(shí)現(xiàn)自定義正則規(guī)則驗(yàn)證,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
vue-cli的build的文件夾下沒有dev-server.js文件配置mock數(shù)據(jù)的方法
這篇文章主要介紹了vue-cli的build的文件夾下沒有dev-server.js文件配置mock數(shù)據(jù)的方法,非常不錯,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04
van-picker組件default-index屬性設(shè)置不生效踩坑及解決
這篇文章主要介紹了van-picker組件default-index屬性設(shè)置不生效踩坑及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01

