【實戰】Vue全家桶(vue + axios + vue-router + vuex)搭建移動端H5項目


使用Vue全家桶開發移動端頁面。
本博文默認已安裝node.js。
github鏈接

一.准備工作

  • 安裝vue
npm install vue
  • 安裝腳手架vue-cli
npm install -g @vue/cli
  • 創建webpack項目
vue init webpack my-app

image

  • 運行
cd my-app
npm run dev

運行效果
按照提示,在瀏覽器打開http://localhost:8082/,效果如下:
展示效果

  • 安裝狀態管理vuex
npm install vuex --save-dev
  • 目錄結構
    項目初始目錄如下:
    目錄結構.jpg

至此,准備工作已就緒,接下來將進行項目整體的結構設計。

二.項目設計

1.項目目錄設計

  • assets目錄下創建imagesjscss文件夾。

    • images文件夾下創建index文件夾,用於存放 首頁圖片(模塊化,讓項目結構一目了然)。
      assets.jpg
  • src目錄下創建pages目錄,用戶存放不同的功能頁面。

    • 再在pages目錄下創建index首頁目錄。
      首頁.jpg
    • index目錄下創建index.vue主文件。
      你好首頁.jpg
  • 修改router

    • 修改index.js
    import Vue from 'vue'
    import Router from 'vue-router'
    import Index from '@/pages/index'
    
    Vue.use(Router)
    
    export default new Router({
      routes: [
        {
          path: '/',
          name: 'Index',
          component: Index
        }
      ]
    })
    
    • 瀏覽器效果
      你好首頁2.jpg
  • 刪除components目錄下的文件,將此目錄作為頁面組件文件夾,在此目錄下創建index文件夾,存放index首頁的組件。
    首頁組件.jpg

  • pages/index/index.vue中引入header組件

<template>
  <div class="index-wrap">
    <comHeader />
    你好,首頁
  </div>
</template>

<script>
import header from '@/components/index/header'

export default {
  data() {
    return {

    }
  },
  components: {
    comHeader: header
  }
}

</script>

<style scoped>

</style>

至此,項目的整個結構被重新設計完成,接下來讓我們引入rem.jsless來讓我們開發起來更舒服。

2.移動端適配和less編譯,讓開發變得快樂起來。

  • 移動端適配 rem
    assets/js文件夾下創建common文件夾存放公共js,再在common文件夾下創建rem適配文件js。並在main.js中引入。
// rem.js
;(function (designWidth, maxWidth) {
    var doc = document,
        win = window;
    var docEl = doc.documentElement;
    var tid;
    var rootItem, rootStyle;

    function refreshRem() {
        var width = docEl.getBoundingClientRect().width;
        if (!maxWidth) {
            maxWidth = 540;
        }
        ;
        if (width > maxWidth) {
            width = maxWidth;
        }
        //與淘寶做法不同,直接采用簡單的rem換算方法1rem=100px
        var rem = width * 100 / designWidth;
        //兼容UC開始
        rootStyle = "html{font-size:" + rem + 'px !important}';
        rootItem = document.getElementById('rootsize') || document.createElement("style");
        if (!document.getElementById('rootsize')) {
            document.getElementsByTagName("head")[0].appendChild(rootItem);
            rootItem.id = 'rootsize';
        }
        if (rootItem.styleSheet) {
            rootItem.styleSheet.disabled || (rootItem.styleSheet.cssText = rootStyle)
        } else {
            try {
                rootItem.innerHTML = rootStyle
            } catch (f) {
                rootItem.innerText = rootStyle
            }
        }
        //兼容UC結束
        docEl.style.fontSize = rem + "px";
    };
    refreshRem();

    win.addEventListener("resize", function () {
        clearTimeout(tid); //防止執行兩次
        tid = setTimeout(refreshRem, 300);
    }, false);

    win.addEventListener("pageshow", function (e) {
        if (e.persisted) { // 瀏覽器后退的時候重新計算
            clearTimeout(tid);
            tid = setTimeout(refreshRem, 300);
        }
    }, false);
    if (doc.readyState === "complete") {
        
        doc.body.style.fontSize = "16px";
    } else {
        doc.addEventListener("DOMContentLoaded", function (e) {
            doc.body.style.fontSize = "16px";
        }, false);
    }
})(360, 750); // 360為設計圖的尺寸,請按照實際設計圖修改

// main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import '@/assets/js/common/rem.js' // 引入rem.js

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

至此,rem適配已完成,在寫style時便可直接按照 (設計圖尺寸 / 100) rem,例如設計圖給到元素height為200px,那么用rem則為height: 2rem;

  • less 編譯,在寫style時,為了高效開發,我們選用less編譯。
// 安裝less和依賴
npm install less less-loader style-loader --save-dev

以header.vue為例

<template>
  <div class="header-wrap">
    我是頭頭頭
    <div class="title">
      title
    </div>
  </div>
</template>

<script>

</script>

<style scoped lang="less">
.header-wrap{
  height: 1rem;
  background-color: #252627;
  .title{
    color: #fff;
    height: .5rem;
  }
}
</style>

至此就可以開始頁面的開發了。

3.狀態管理store

  • 安裝 vuex
npm install vuex --save
  • 創建store目錄結構,至於store原理望大家自已學習掌握。
    store.jpg

    • index.js
    /**
     * 組裝模塊並導出 store
     */
    
    import Vue from 'vue'
    import Vuex from 'vuex'
    import game from './modules/game'
    import * as actions from './actions'
    import mutations from './mutations'
    import getters from './getters'
    
    Vue.use(Vuex)
    
    const debug = process.env.NODE_ENV !== 'production'
    
    const state = {
      userInfo:{}
    }
    
    export default new Vuex.Store({
      state: state,
      actions: actions,
      mutations: mutations,
      getters:getters,
      modules: {
        game,
      },
      strict: debug
    })
    
    
  • 使用store

this.$store.dispatch('getData', response.data.data)

4.數據請求 axios

  • src目錄下穿件utils目錄用於存放工具js。在utils下創建request.jsaxios請求進行封裝。
import axios from 'axios'
import { Message, MessageBox } from 'element-ui'
import config from '../../config/config'
import toast from './toast'

import store from '@/store'

const service = axios.create({
  baseURL: 'www.baidu.com', 
  timeout:0// request timeout
})
service.interceptors.request.use(
    requestConfig => {
      let data = {
        // 公共請求參數
      };
      requestConfig.data = Object.assign({}, requestConfig.data, data)
      return requestConfig
    },
    error => {
      Promise.reject(error)
    }
)
// response interceptor
service.interceptors.response.use(response => {
  const res = response.data
  if (res.errno === 501) {
      MessageBox.alert('系統未登錄,請重新登錄', '錯誤', {
          confirmButtonText: '確定',
          type: 'error'
      }).then(() => {
      })
      return Promise.reject('error')
  } else if (res.errno === 502) {
      toast.showToast('系統內部錯誤,請聯系管理員維護',1200,'error')
      return Promise.reject('error')
  } else if (res.errno === 503) {
      toast.showToast('請求業務目前未支持',1200,'error')
      return Promise.reject('error')
  } else if (res.errno === 504) {
      toast.showToast('更新數據已經失效,請刷新頁面重新操作',1200,'error')
      return Promise.reject('error')
  } else if (res.errno === 505) {
      toast.showToast('更新失敗,請再嘗試一次',1200,'error')
      return Promise.reject('error')
  } else if (res.errno === 506) {
      toast.showToast('沒有操作權限,請聯系管理員授權',1200,'error')
      return Promise.reject('error')
  }  else {
      return response
    }
  }, error => {
    toast.showToast('登錄連接超時',5 * 1000,'error')
    return Promise.reject(error)
  })
export default service

  • src 目錄下常見 api 文件夾,並創建組件index.js
import request from '../utils/request'

/**
 * @method getUserInfo 獲取用戶信息
 * @param query {Object}
 */
export function getUserInfo(query){
  return request({
    url: 'user/info',
    method: 'post',
    data: query
  })
}
  • index.vue中調用
<template>
  <div class="index-wrap">
    <comHeader />
    你好,首頁
  </div>
</template>

<script>
import header from '@/components/index/header'
import { getUserInfo } from '@/api/index.js'  // 引入

export default {
  data() {
    return {

    }
  },
  components: {
    comHeader: header
  },
  methods: {
    getInfo(){
      getUserInfo()  //業務邏輯
      .then(res => {
        // do something
      })
      .catch(response => {})
    }
  },
  created() {
    this.getInfo(); //調用
  }
}

</script>

<style scoped lang="less">

</style>

三.編譯發布

1.編譯生成 dist

npm run build

//在根目錄下生成dis文件夾,可以將此文件夾放到oss上以供不同瀏覽器瀏覽。

總結

  • 在開發項目的過程中要考慮項目的模塊化。
  • 盡可能的做到代碼規范,具體的代碼規范可在我的其他博文參考下:
  • 實際項目中的具體問題可私信我,共同解決共同學習。為你能看完本博文而感到愉悅


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM