分享一个vue项目“脚手架”项目的实现步骤

搭建缘由

源于公司每次新启动一个由多人协同开发的项目都由负责人初始化项目之后,每个人再去从私服pull一下项目才开始开发。但是每次初始化工程都是一步步的造轮子,一个个依赖去安装,新建一个个不同功能的文件夹,而每个负责人所初始化的项目目录、以及模块引入方式参差不齐,以至于开发中后期因每个人开发风格的不同导致git提交时总会产生各种各样的“冲突”,也会产生后期代码维护成本增加,所以就有必要考虑一下做一个统一的类似“脚手架”的功能了,用来给团队开发带来便捷的、统一的、易扩展的项目基础。

预实现的功能

公共样式统一管理,全局sass的友好引入

公共js统一管理

解决vue脚手架初始化的部分问题

路由形式、接口统一管理

store模块化管理

定义vue前端项目必用的方法

修改好统一的config配置

全局混入/指令的封装

必要的依赖项

node-sass sass sass-resources sass-loader sass-recources-loader

vuex vuex-persistedstate

axios

babel-polyfill

项目目录如下

配置公共sass

目录assets>scss文件形式

mixin.scss内容详见mixin公共sass函数

common.scss内容如下

@import './mixin.scss'; // 公共函数

@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')

}

接口统一管理

js目录下的urlConfig.js

// 开发环境用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

};

页面使用方式例如:

this.$http.post(this.URL_CONFIG.UrlConfig.getUserInfo,datas)

.then(res =>{

console.log(res)

}).catch(error =>{

console.log(error)

})

// URL_CONFIG见全局混入中的方法

全局混入管理

全局混入主要用于项目中每个页面或模块都会用到的函数方法、计算属性、过滤方法等。

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

//以下只是其中一种思路

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中引入

//自定义全局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

您可能感兴趣的文章:

使用vue脚手架(vue-cli)搭建一个项目详解

图文讲解用vue-cli脚手架创建vue项目步骤

使用vue-cli脚手架工具搭建vue-webpack项目

vue-cli3.0 脚手架搭建项目的过程详解

vue-cli脚手架搭建的项目去除eslint验证的方法

解决vue脚手架项目打包后路由视图不显示的问题

vue脚手架搭建项目的兼容性配置详解

使用vue-cli(vue脚手架)快速搭建项目的方法

详解使用vue-cli脚手架初始化Vue项目下的项目结构

详解vue-cli 脚手架项目-package.json

详解如何使用vue-cli脚手架搭建Vue.js项目

文章同步发布: https://www.geek-share.com/detail/2769911782.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容

  • ## 框架和库的区别?> 框架(framework):一套完整的软件设计架构和**解决方案**。> > 库(lib...
    Rui_bdad阅读 2,884评论 1 4
  • 1.脚手架: (1) npm install -g vue-cli (2) vue init webpac...
    苏苡阅读 3,376评论 1 2
  • 1、active-class是哪个组件的属性?嵌套路由怎么定义?答:vue-router模块的router-lin...
    jane819阅读 1,735评论 0 15
  • 一:什么是闭包?闭包的用处? (1)闭包就是能够读取其他函数内部变量的函数。在本质上,闭包就 是将函数内部和函数外...
    xuguibin阅读 9,474评论 1 52
  • vue-cli虽然强大,但是它有很多个步骤要我们去选择配置,而实际上公司业务很多配置是固定的,比如要安装vue-r...
    阿尔法乀阅读 3,462评论 1 0