溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

分享一個(gè)vue項(xiàng)目“腳手架”項(xiàng)目的實(shí)現(xiàn)步驟

發(fā)布時(shí)間:2020-10-12 18:53:03 來(lái)源:腳本之家 閱讀:186 作者:vannvan 欄目:web開(kāi)發(fā)

搭建緣由

源于公司每次新啟動(dòng)一個(gè)由多人協(xié)同開(kāi)發(fā)的項(xiàng)目都由負(fù)責(zé)人初始化項(xiàng)目之后,每個(gè)人再去從私服pull一下項(xiàng)目才開(kāi)始開(kāi)發(fā)。但是每次初始化工程都是一步步的造輪子,一個(gè)個(gè)依賴去安裝,新建一個(gè)個(gè)不同功能的文件夾,而每個(gè)負(fù)責(zé)人所初始化的項(xiàng)目目錄、以及模塊引入方式參差不齊,以至于開(kāi)發(fā)中后期因每個(gè)人開(kāi)發(fā)風(fēng)格的不同導(dǎo)致git提交時(shí)總會(huì)產(chǎn)生各種各樣的“沖突”,也會(huì)產(chǎn)生后期代碼維護(hù)成本增加,所以就有必要考慮一下做一個(gè)統(tǒng)一的類似“腳手架”的功能了,用來(lái)給團(tuán)隊(duì)開(kāi)發(fā)帶來(lái)便捷的、統(tǒng)一的、易擴(kuò)展的項(xiàng)目基礎(chǔ)。

預(yù)實(shí)現(xiàn)的功能

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

必要的依賴項(xiàng)

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

項(xiàng)目目錄如下

分享一個(gè)vue項(xiàng)目“腳手架”項(xiàng)目的實(shí)現(xiàn)步驟

配置公共sass

目錄assets>scss文件形式

mixin.scss內(nèi)容詳見(jiàn)mixin公共sass函數(shù)

common.scss內(nèi)容如下

@import './mixin.scss'; // 公共函數(shù)
@import './icomoon.css'; //字體圖標(biāo)
@import './wvue-cli.scss'; //項(xiàng)目公共樣式

修改utils.js引入commom.css,就不用在main.js 或其他項(xiàng)目中的頁(yè)面引入了

//57行開(kāi)始
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')
 }

接口統(tǒng)一管理

js目錄下的urlConfig.js

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

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

頁(yè)面使用方式例如:

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

全局混入管理

全局混入主要用于項(xiàng)目中每個(gè)頁(yè)面或模塊都會(huì)用到的函數(shù)方法、計(jì)算屬性、過(guò)濾方法等。

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

//以下只是其中一種思路
import URL_CONFIG from '@/assets/js/urlConfig.js';
const mixin = {
   data(){
   return {
    URL_CONFIG:URL_CONFIG
   },
   methods: {
   //像時(shí)間戳轉(zhuǎn)換這種方法大多數(shù)項(xiàng)目都能用的到,可以寫(xiě)在filter里也可以寫(xiě)在computed里,取決于運(yùn)用場(chǎng)景
   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中引入

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

全局指令管理

全局指令主要用于各個(gè)項(xiàng)目中由于vue指令不能滿足需求,自定義的指令形式,在頁(yè)面編寫(xiě)過(guò)程中可以帶來(lái)很多的便利。

文件所屬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'
 }),
 // 圖片未加載完之前先用隨機(jī)背景色占位
 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模塊化管理主要是滿足不同開(kāi)發(fā)人員的需求、避免使用單一store文件導(dǎo)致命名沖突。同時(shí)在main里定義了統(tǒng)一的模塊文件滿足大多數(shù)項(xiàng)目開(kāi)發(fā)的場(chǎng)景需求。

文件所屬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存儲(chǔ)數(shù)據(jù)
 modules: {
  baseInfoStore: baseInfo_store, //userInfo模塊
 },
 plugins: [createPersistedState({
   storage: window.sessionStorage 
 })]
})
//切換頁(yè)面一般需要的loading動(dòng)畫(huà)狀態(tài)
store.registerModule('pageSwitch', {
 state: {
  isLoading: false
 },
 mutations: {
  updateLoadingStatus (state, payload) {
   state.isLoading = payload.isLoading
  }
 }
})
//切換路由的同時(shí)切換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請(qǐng)求的動(dòng)畫(huà)狀態(tài)
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
 }
})
//請(qǐng)求攔截
Axios.interceptors.request.use(config => {
 store.commit('ajaxStar')
 return config;
})
//響應(yīng)攔截
Axios.interceptors.response.use(config => {
 //需要攔截的請(qǐng)求頭
 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 初始配置的打包路徑問(wèn)題

其實(shí)這個(gè)在上面文件中已經(jīng)有體現(xiàn)了,在這里再次提及一下。

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

將build{ }下的assetsPublicPath改為如下

assetsPublicPath: './',

步驟2:修改build>utils.js文件

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

publicPath: '../../'

結(jié)語(yǔ)

至此,一個(gè)基本完備的vue項(xiàng)目“腳手架”就完成了,以后每次初始化項(xiàng)目都可以按照這套方案來(lái)進(jìn)行,省去了很多協(xié)作開(kāi)發(fā)的交流環(huán)節(jié),形成了能夠滿足大多數(shù)項(xiàng)目的目錄及文件構(gòu)成形式,將此項(xiàng)目托管至私服每次初始化項(xiàng)目只需拉取這個(gè)“腳手架”便能省區(qū)不少初始化項(xiàng)目的時(shí)間,豈不美哉!

此“腳手架”項(xiàng)目已開(kāi)源至github,歡迎大家提出建議和互相交流,同時(shí)也可隨意將項(xiàng)目拉下來(lái)進(jìn)行使用。

A scaffolding based on vue.js

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI