分享一個vue項目腳手架項目

搭建原因

源於公司每次新啓動一個由多人協同開發的項目都由負責人初始化項目以後,每一個人再去從私服pull一下項目纔開始開發。可是每次初始化工程都是一步步的造輪子,一個個依賴去安裝,新建一個個不一樣功能的文件夾,而每一個負責人所初始化的項目目錄、以及模塊引入方式良莠不齊,以致於開發中後期因每一個人開發風格的不一樣致使git提交時總會產生各類各樣的「衝突」,也會產生後期代碼維護成本增長,因此就有必要考慮一下作一個統一的相似「腳手架」的功能了,用來給團隊開發帶來便捷的、統一的、易擴展的項目基礎。css

預實現的功能

  • 公共樣式統一管理,全局sass的友好引入
  • 公共js統一管理
  • 解決vue腳手架初始化的部分問題
  • 路由形式、接口統一管理
  • store模塊化管理
  • 定義vue前端項目必用的方法
  • 修改好統一的config配置
  • 全局混入/指令的封裝

必要的依賴項

  • node-sass sass sass-loader sass-resources-loader
  • vuex vuex-persistedstate
  • axios
  • babel-polyfill

項目目錄以下

配置公共sass

目錄assets>scss文件形式前端

mixin.scss內容詳見 mixin公共sass函數vue

common.scss內容以下node

@import './mixin.scss'; // 公共函數
@import './icomoon.css'; //字體圖標
@import './wvue-cli.scss'; //項目公共樣式

修改utils.js引入commom.css,就不用在main.js 或其餘項目中的頁面引入了ios

//57行開始
function resolveResouce(name) {
    return path.resolve(__dirname, '../src/assets/scss/' + name);
  }
  function generateSassResourceLoader() {
      var loaders = [
   cssLoader,
   // 'postcss-loader',
   'sass-loader',
   {
       loader: 'sass-resources-loader',
       options: {
         // it need a absolute path
         resources: [resolveResouce('common.scss')]    
       }
   }
      ];
      if (options.extract) {
   return ExtractTextPlugin.extract({
     use: loaders,
     fallback: 'vue-style-loader'
   })
      } else {
   return ['vue-style-loader'].concat(loaders)
      }
  }
  // 注意這裏
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateSassResourceLoader(),
    scss: generateSassResourceLoader(),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }

接口統一管理

js目錄下的urlConfig.jsgit

// 開發環境用config下proxyTable的代理地址
var BASE_URL = '/api';
var isPro = process.env.NODE_ENV === 'production'
if(isPro){
    BASE_URL= 'http://113.113.113.113:8011'  //生產環境下的地址
}

const UrlConfig = {
  getUserInfo:BASE_URL +'user/getinfo',  //獲取用戶信息
}
export default {
  UrlConfig
};

頁面使用方式例如:github

this.$http.post(this.URL_CONFIG.UrlConfig.getUserInfo,datas)
.then(res =>{
    console.log(res)
}).catch(error =>{
    console.log(error)
})
// URL_CONFIG見全局混入中的方法

全局混入管理

全局混入主要用於項目中每一個頁面或模塊都會用到的函數方法、計算屬性、過濾方法等。ajax

文件所屬components>common>mixins>index.jsvuex

//如下只是其中一種思路
import URL_CONFIG from '@/assets/js/urlConfig.js';
const mixin = {
     data(){
      return {
        URL_CONFIG:URL_CONFIG
     },
     methods: {
     //像時間戳轉換這種方法大多數項目都能用的到,能夠寫在filter裏也能夠寫在computed裏,取決於運用場景
      formatDate(date, fmt) {
          if (/(y+)/.test(fmt)) {
              fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
          }
          let o = {
              'M+': date.getMonth() + 1,
              'd+': date.getDate(),
              'h+': date.getHours(),
              'm+': date.getMinutes(),
              's+': date.getSeconds()
          };
          for (let k in o) {
              if (new RegExp(`(${k})`).test(fmt)) {
                  let str = o[k] + '';
                  fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : this.padLeftZero(str));
              }
          }
          return fmt;
      },
      padLeftZero(str) {
          return ('00' + str).substr(str.length);
      },
      loadPage(path,params){
        this.$router.push({
          path:path,
          query:params
        })
      }
    }
}
export default mixin

在main.js中引入vue-cli

//自定義全局mixin
import mixins from '@/components/common/mixins'
Vue.mixin(mixins)

全局指令管理

全局指令主要用於各個項目中因爲vue指令不能知足需求,自定義的指令形式,在頁面編寫過程當中能夠帶來不少的便利。

文件所屬components>common>directive>index.js

//如下只是一種思路,主要目的是分享自定義指令的方法
let mydirective = {}
mydirective.install = function (Vue) {
  //背景顏色
  Vue.directive('bg', {
    bind(el, binding) {
        el.style.color = '#f6f6f6';
    }
  }),
  //主題色
  Vue.directive('color', {
    bind(el, binding) {
        el.style.color = '#42E5D3';
    }
  }),
  Vue.directive('theme',function(el){
    el.style.color = '#42E5D3'
    el.style.background = '#f6f6f6'
  }),
  // 圖片未加載完以前先用隨機背景色佔位
  Vue.directive('img', {
  inserted:function (el, binding) {
    var color = Math.floor(Math.random()*1000000);
    el.style.backgroundColor = "#" + color;
    var img = new Image();
    img.src = binding.value;
    img.onload = function(){
      el.style.backgroundImage = 'url('+ binding.value +')'
    }
  }
  })
}

export default mydirective;

在main.js中引入

//自定義全局指令
import directive from '@/components/common/directive'
Vue.use(directive)

store 模塊化管理

store模塊化管理主要是知足不一樣開發人員的需求、避免使用單一store文件致使命名衝突。同時在main裏定義了統一的模塊文件知足大多數項目開發的場景需求。

文件所屬store>main.js

import Vue from 'vue'
import Vuex from 'vuex'
import router from '@/router'
import Axios from 'axios'
import createPersistedState from 'vuex-persistedstate'

import baseInfo_store from './baseInfo'
Vue.use(Vuex)

const store = new Vuex.Store({
// 用不一樣的模塊管理vuex存儲數據
  modules: {
    baseInfoStore: baseInfo_store,  //userInfo模塊
  },
  plugins: [createPersistedState({
      storage: window.sessionStorage 
  })]
})
//切換頁面通常須要的loading動畫狀態
store.registerModule('pageSwitch', {
  state: {
    isLoading: false
  },
  mutations: {
    updateLoadingStatus (state, payload) {
      state.isLoading = payload.isLoading
    }
  }
})
//切換路由的同時切換title
router.beforeEach(function (to, from, next) {
  if(to.meta.title){
    document.title = to.meta.title
  }
  store.commit('updateLoadingStatus', {isLoading: true})
  next()
})

router.afterEach(function (to) {
  store.commit('updateLoadingStatus', {isLoading: false})
})
//ajax請求的動畫狀態
store.registerModule('ajaxSwitch', {
  state: {
    ajaxIsLoading: false,
    ajaxIsPrompt: false,
  },
  mutations: {
    ajaxStar (state) {
      state.ajaxIsLoading = true
    },
    ajaxEnd (state) {
      state.ajaxIsLoading = false
    },
    ajaxPromptShow (state) {
      state.ajaxIsPrompt = true
    },
    ajaxPromptHide (state) {
      state.ajaxIsPrompt = false
    }
  },
  getter : {
    ajaxIsLoading: state => state.ajaxIsLoading
  }
})
//請求攔截
Axios.interceptors.request.use(config => {
  store.commit('ajaxStar')
  return config;
})
//響應攔截
Axios.interceptors.response.use(config => {
  //須要攔截的請求頭
  return config
})
export default store;

在main.js引入

import store from '@/store/main.js';

main.js的最終形式

import Vue from 'vue'
import App from './App'
import router from './router'

import axios from 'axios';
import "babel-polyfill";
import store from '@/store/main.js';
//自定義全局mixin
import mixins from '@/components/common/mixins'
Vue.mixin(mixins)
//自定義全局指令
import directive from '@/components/common/directive'
Vue.use(directive)

Vue.config.productionTip = false
Vue.prototype.$http = axios;
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

解決vue-cli 初始配置的打包路徑問題

其實這個在上面文件中已經有體現了,在這裏再次說起一下。

  • 步驟1:修改config>index.js文件

將build{ }下的assetsPublicPath改成以下

assetsPublicPath: './',
  • 步驟2:修改build>utils.js文件

找到 fallback: 'vue-style-loader',在其下加入下面這一行

publicPath: '../../'

結語

至此,一個基本完備的vue項目腳手架就完成了,之後每次初始化項目均可以按照這套方案來進行,省去了不少協做開發的交流環節,造成了可以知足大多數項目的目錄及文件構成形式,將此項目託管至私服每次初始化項目只需拉取這個腳手架便能省區很多初始化項目的時間,豈不美哉!

此腳手架項目已開源至github,歡迎你們提出建議和互相交流,同時也可隨意將項目拉下來進行使用。

A scaffolding based on vue.js

開箱即用操做方式

npm i wwvue-cli -g wwvue-cli init project-name
相關文章
相關標籤/搜索