分享一個vue項目“腳手架”項目的實現(xiàn)步驟
搭建緣由
源于公司每次新啟動一個由多人協(xié)同開發(fā)的項目都由負責(zé)人初始化項目之后,每個人再去從私服pull一下項目才開始開發(fā)。但是每次初始化工程都是一步步的造輪子,一個個依賴去安裝,新建一個個不同功能的文件夾,而每個負責(zé)人所初始化的項目目錄、以及模塊引入方式參差不齊,以至于開發(fā)中后期因每個人開發(fā)風(fēng)格的不同導(dǎo)致git提交時總會產(chǎn)生各種各樣的“沖突”,也會產(chǎn)生后期代碼維護成本增加,所以就有必要考慮一下做一個統(tǒng)一的類似“腳手架”的功能了,用來給團隊開發(fā)帶來便捷的、統(tǒng)一的、易擴展的項目基礎(chǔ)。
預(yù)實現(xiàn)的功能
- 公共樣式統(tǒng)一管理,全局sass的友好引入
- 公共js統(tǒng)一管理
- 解決vue腳手架初始化的部分問題
- 路由形式、接口統(tǒng)一管理
- store模塊化管理
- 定義vue前端項目必用的方法
- 修改好統(tǒng)一的config配置
- 全局混入/指令的封裝
必要的依賴項
- node-sass sass sass-resources sass-loader sass-recources-loader
- vuex vuex-persistedstate
- axios
- babel-polyfill
項目目錄如下
配置公共sass
目錄assets>scss文件形式
mixin.scss內(nèi)容詳見mixin公共sass函數(shù)
common.scss內(nèi)容如下
@import './mixin.scss'; // 公共函數(shù)
@import './icomoon.css'; //字體圖標
@import './wvue-cli.scss'; //項目公共樣式
修改utils.js
引入commom.css,就不用在main.js 或其他項目中的頁面引入了
//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') }
接口統(tǒng)一管理
js目錄下的urlConfig.js
// 開發(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 };
頁面使用方式例如:
this.$http.post(this.URL_CONFIG.UrlConfig.getUserInfo,datas) .then(res =>{ console.log(res) }).catch(error =>{ console.log(error) }) // URL_CONFIG見全局混入中的方法
全局混入管理
全局混入主要用于項目中每個頁面或模塊都會用到的函數(shù)方法、計算屬性、過濾方法等。
文件所屬components>common>mixins>index.js
//以下只是其中一種思路 import URL_CONFIG from '@/assets/js/urlConfig.js'; const mixin = { data(){ return { URL_CONFIG:URL_CONFIG }, methods: { //像時間戳轉(zhuǎn)換這種方法大多數(shù)項目都能用的到,可以寫在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中引入
//自定義全局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模塊化管理主要是滿足不同開發(fā)人員的需求、避免使用單一store文件導(dǎo)致命名沖突。同時在main里定義了統(tǒng)一的模塊文件滿足大多數(shù)項目開發(fā)的場景需求。
文件所屬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存儲數(shù)據(jù) modules: { baseInfoStore: baseInfo_store, //userInfo模塊 }, plugins: [createPersistedState({ storage: window.sessionStorage })] }) //切換頁面一般需要的loading動畫狀態(tài) 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請求的動畫狀態(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 } }) //請求攔截 Axios.interceptors.request.use(config => { store.commit('ajaxStar') return config; }) //響應(yīng)攔截 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 初始配置的打包路徑問題
其實這個在上面文件中已經(jīng)有體現(xiàn)了,在這里再次提及一下。
步驟1:修改config>index.js文件
將build{ }下的assetsPublicPath改為如下
assetsPublicPath: './',
步驟2:修改build>utils.js文件
找到 fallback: 'vue-style-loader',在其下加入下面這一行
publicPath: '../../'
結(jié)語
至此,一個基本完備的vue項目“腳手架”就完成了,以后每次初始化項目都可以按照這套方案來進行,省去了很多協(xié)作開發(fā)的交流環(huán)節(jié),形成了能夠滿足大多數(shù)項目的目錄及文件構(gòu)成形式,將此項目托管至私服每次初始化項目只需拉取這個“腳手架”便能省區(qū)不少初始化項目的時間,豈不美哉!
此“腳手架”項目已開源至github,歡迎大家提出建議和互相交流,同時也可隨意將項目拉下來進行使用。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue中el-table單元格復(fù)制功能實現(xiàn)
這篇文章主要介紹了vue中el-table單元格復(fù)制功能實現(xiàn),本文給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧2024-07-07Vue3中的ref為何要用.value進行值的調(diào)用呢
這篇文章主要介紹了Vue3中的ref為何要用.value進行值的調(diào)用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09解決vue的 v-for 循環(huán)中圖片加載路徑問題
今天小編就為大家分享一篇解決vue的 v-for 循環(huán)中圖片加載路徑問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09vue.js樣式布局Flutter業(yè)務(wù)開發(fā)常用技巧
這篇文章主要為大家介紹了vue.js樣式布局Flutter業(yè)務(wù)開發(fā)中的常用技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2021-11-11vue?cli3配置image-webpack-loader方式
這篇文章主要介紹了vue?cli3配置image-webpack-loader方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07