前言:爲公司前端項目搭建整理的一份文檔javascript
下載地址:http://nodejs.cn/download/css
安裝檢查:html
命令: node -v npm -v
注:若需更改node模塊(node_modules)的安裝目錄自行百度,因爲建立的Vue項目中node模塊是安裝在項目文件夾下就不作更改了。前端
若使用淘寶npm鏡像(cnpm)經過如下命令安裝:vue
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
官方文檔:https://github.com/vuejs/vue-cli/tree/v2#vue-cli--java
注:使用的一些UI組件不適配vue-cli@3.x,因此須要安裝vue-cli@2.xnode
好比VUXwebpack
安裝命令:ios
$ npm install -g vue-cli
查看版本:git
$ vue –version
使用: $ vue init <template-name> <project-name> 例如: $ vue init webpack my-project
將從vuejs-templates/webpack中提取模板信息,根據此模板信息生成項目(./my-project/)
官方文檔:https://cli.vuejs.org/zh/guide/
安裝命令:
$ npm install -g @vue/cli
查看版本:
$ vue --version
使用:
$ vue create <project-name>
本項目使用的vue-cli版本:2.9.6
在本地/d/Projects目錄下建立名爲project-demo的項目
Vue build
第一個選項能夠不基於.vue文件開發,在運行時會進行編譯
第二個選項基於.vue文件開發,比第一個選項小6KB
使用vue-router
使用ESLint進行代碼檢測(ESLint 是一個語法規則和代碼風格的檢查工具,能夠用來保證寫出語法正確、風格統一的代碼。)
ESLint代碼檢測規則(本項目使用Standard),官方文檔鏈接:
Standard:https://github.com/standard/standard/blob/master/docs/README-zhcn.md
Airbnb:https://github.com/airbnb/javascript
安裝完成後運行上述命令:
$ cd project-demo
$ npm run dev
根據運行成功後的地址在瀏覽器進行訪問
. |-- README.md |-- build | |-- build.js | |-- check-versions.js | |-- logo.png | |-- utils.js | |-- vue-loader.conf.js | |-- webpack.base.conf.js | |-- webpack.dev.conf.js | `-- webpack.prod.conf.js |-- config | |-- dev.env.js | |-- index.js | `-- prod.env.js |-- index.html |-- package-lock.json |-- package.json |-- src | |-- App.vue | |-- assets | | `-- logo.png | |-- components | | `-- HelloWorld.vue | |-- main.js | `-- router | `-- index.js `-- static
$ cd /project-demo $ git init $ git remote add origin <線上git倉庫地址(SHH)> $ git add . $ git commit $ git push -u origin master
1) Vetur 2) ESLint 3) Beautify 4) GitLens — Git supercharged 5) Git History 6) HTML CSS Support 7) HTML Snippets 8) Vue 2 Snippets 9) Debugger for Chrome
項目結構多采用vue-element-admin項目結構:https://panjiachen.gitee.io/vue-element-admin-site/zh/guide/
|-- README.md |-- build # 項目打包配置 |-- config # 項目配置 |-- index.html # html模板 |-- package-lock.json # postcss 配置 |-- package.json # package.json |-- src # 源代碼 | |-- App.vue # 入口頁面 | |-- api # 全部請求 | |-- assets # 主題 字體等靜態資源 | |-- axios # axios通用配置 | |-- components # 全局公用組件 | |-- directive # 全局指令 | |-- filters # 全局 filter | |-- layout # 全局 layout | |-- main.js # 入口文件 加載組件 初始化等 | |-- router # 路由 | |-- store # vuex配置,全局 store管理 | |-- styles # 全局樣式、自定義主題等 | |-- utils # 全局公用方法 | `-- views # 全部頁面 `-- static
修改.eslintrc.js文件配置,在rules對象中添加如下配置(其餘配置默認):
// 在函數括號以前不容許空格 'space-before-function-paren': ['error', 'never']
修改package.json文件配置:
添加後運行如下命令能夠快速修復ESLint報錯:
$ npm run lint
官方文檔:https://element.eleme.cn/#/zh-CN/component/installation
npm安裝:
$ npm i element-ui -S
Element完整引入
在 main.js 中寫入如下內容:
import Vue from 'vue' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' import App from './App' import router from './router' Vue.config.productionTip = false Vue.use(ElementUI) /* eslint-disable no-new */ new Vue({ el: '#app', router, render: h => h(App) })
VUX文檔:https://doc.vux.li/zh-CN/
Mint UI文檔:https://mint-ui.github.io/docs/#/zh-cn2
本項目安裝sass預處理器
Sass文檔:https://www.sass.hk/docs/
安裝:
$ npm install node-sass --save-dev
$ npm install sass-loader --save-dev
文檔:https://www.kancloud.cn/yunye/axios/234845
$ npm install axios
於src目錄下建立axios文件夾,並於其中建立index.js文件,內容以下(PC端配置了element-ui的一個加載組件):
import axios from 'axios' import { Notification, Loading } from 'element-ui' // 根據環境設置請求baseURL axios.defaults.baseURL = process.env.API_ROOT // 請求超時時間 axios.defaults.timeout = 6000 // post請求頭 axios.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8' let loading // 請求攔截器 axios.interceptors.request.use( config => { // 加載提示 loading = Loading.service({ lock: true, text: '拼命加載中', spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.7)' // background: 'rgba(255, 255, 255, 0)' }) return config }, error => { return Promise.reject(error) } ) // 響應攔截器 axios.interceptors.response.use( response => { // 關閉加載提示 loading.close() return response }, error => { // 關閉加載提示 loading.close() if (error && error.response) { switch (error.response.status) { case 400: Notification.error({ message: '請求錯誤' }) break case 403: Notification.error({ message: '拒絕訪問' }) break case 404: Notification.error({ message: '請求地址出錯' }) break case 408: Notification.error({ message: '請求超時' }) break case 500: Notification.error({ message: '服務出錯' }) break case 501: Notification.error({ message: '網絡未實現' }) break case 502: Notification.error({ message: '網絡錯誤' }) break case 503: Notification.error({ message: '服務不可用' }) break case 504: Notification.error({ message: '網絡超時' }) break default: } } else if (error.message === 'Network Error') { Notification.error({ message: '網絡錯誤' }) } else if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) { Notification.error({ message: '請求超時,請重試' }) } return Promise.reject(error) } ) export default axios
於src目錄下新建api文件夾,文件夾中根據API類型新建對應的js文件模塊以便管理。
例如用戶信息請求API新建userApi.js文件
文件內容格式以下:
import request from '@/axios' /** * 用戶登陸 * @param {Object} data 用戶帳號信息對象 */ export function login(data) { return request({ url: '/user/login', method: 'post', data }) } /** * 獲取用戶信息 * @param {String} token token */ export function getInfo(token) { return request({ url: '/user/info', method: 'get', params: { token } }) }
//script標籤內進行導入 import * as userApi from '@/api/userApi' //使用: userApi.login({username: '張三', password: '123456'}) .then(res => { const { data } = res console.log(data) })
文檔:https://router.vuejs.org/zh/installation.html
|-- src … | |-- layout | | `-- index.vue … | |-- router | | |-- index.js | | `-- modules | | `-- userCenter.js
import Vue from 'vue' import Router from 'vue-router' import Layout from '@/layout' /* Router Modules */ import userRouter from './modules/userCenter' Vue.use(Router) const router = new Router({ // 路由跳轉後從新定位到頂部 scrollBehavior: () => ({ y: 0 }), routes: [ userRouter, { path: '/', name: 'Layout', component: Layout, meta: {title: '主頁'} }, { path: '*', component: () => import('@/components/404') } ] }) export default router
能夠根據項目須要可配置導航守衛、路由模塊等相關配置
在src目錄下新建layout文件夾,其中新建index.vue文件
<template> <div> Layout <router-view/> </div> </template> <script> export default { name: 'Layout' } </script> <style lang="scss" scoped> </style>
$ npm install vuex --save
文檔:https://github.com/robinvdvleuten/vuex-persistedstate
vuex-persistedstate是一個將vuex持久化的插件
$ npm install --save vuex-persistedstate
於src目錄下新建store文件夾,其下新建index.js、mutation-types.js文件和modules文件夾
-- store | |-- index.js | |-- modules | | `-- user.js | `-- mutation-types.js
將 store 分割成模塊(module),每一個模塊擁有本身的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行一樣方式的分割。
使用常量替代 mutation 事件類型(使用 ES2015 風格的計算屬性命名功能來使用一個常量做爲函數名),把這些常量放在單獨的文件中可讓你的代碼合做者對整個 app 包含的 mutation 一目瞭然。
新建mutation-types.js文件存放常量,例如:
// mutation-types.js // user modules export const SET_USER_NAME = 'SET_USER_NAME'
// user.js import * as types from '../mutation-types' const state = { userName: '' } const mutations = { [types.SET_USER_NAME](state, str) { state.userName = str } } const actions = { saveUserName({ commit }, str) { commit(types.SET_USER_NAME, str) } } export default { namespaced: true, state, mutations, actions }
index.js配置以下:
vuex-persistedstate插件僅將須要持久化的狀態值進行持久化。
import Vue from 'vue' import Vuex from 'vuex' import CreatePersistedState from 'vuex-persistedstate' Vue.use(Vuex) // webpack v4.35.2 依賴管理 // https://webpack.js.org/guides/dependency-management/#requirecontext const modulesFiles = require.context('./modules', false, /\.js$/) // 自動請求modules目錄下的模塊文件 const modules = modulesFiles.keys().reduce((modules, modulePath) => { // 模塊名爲modules目錄下的js文件名 const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1') // value 爲請求到的模塊文件內容 {default:{state:{...},mutations:{...},actions:{...}}, __esModule: true} const value = modulesFiles(modulePath) modules[moduleName] = value.default return modules }, {}) const vuexPersisted = new CreatePersistedState({ key: 'VuexPersisted', storage: window.localStorage, reducer: state => ({ user: { userName: state.user.userName } }) }) const store = new Vuex.Store({ modules, plugins: [vuexPersisted] }) export default store
使用方式就不一一列舉了,如下僅列舉其中一種,其餘的能夠去看官方文檔。
訪問state值時,使用對象展開運算符將此對象混入到局部計算屬性中。
import { mapState } from 'vuex' export default { computed: { ...mapState('user', ['userName']) }, mounted() { console.log(this.userName) } }
訪問actions,使用對象展開運算符將此對象混入到局部 methods 中。
import { mapActions } from 'vuex' export default { methods: { ...mapActions('user', ['saveUserName']), // 登陸時存儲用戶名 login() { this.saveUserName('80xxxxx06@qq.com') } } }
於src目錄下新建styles文件夾
|-- src … | |-- styles | | |-- border.css #app一像素邊框解決 | | |-- element-ui.scss #自定義的element-ui組件樣式 | | |-- element-variables.scss #經過element-ui樣式變量修改通用主題 | | |-- index.scss #全局通用樣式引入/定義 | | |-- mixin.scss #自定義的scss混合指令 | | |-- reset.css #css樣式重置文件 | | |-- transition.scss #自定義過渡樣式 | | `-- variables.scss #自定義樣式變量
在main.js中引入
import '@/styles/index.scss' // 全局 css 樣式
將文件中build對象中assetsPublicPath值改成’./’
assetsPublicPath: './',
if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, publicPath: '../../', fallback: 'vue-style-loader' }) } else { return ['vue-style-loader'].concat(loaders) }
以上配置中添加了 publicPath 配置 ’../../’
此配置解決打包後圖片讀取路徑錯誤問題
http://www.javashuo.com/article/p-seozhmxf-bp.html
注:因爲我以前寫文檔一的配置方式稍顯繁瑣,現將文檔一的配置進行簡化。這次文檔就只配置開發、測試、生產三個環境,添加其餘環境的配置方式同樣。
$ npm i --save-dev cross-env
"scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "lint": "eslint --fix --ext .js,.vue src", "build:dev": "cross-env NODE_ENV=production ENV_CONFIG=dev node build/build.js", "build:test": "cross-env NODE_ENV=production ENV_CONFIG=test node build/build.js", "build:prod": "cross-env NODE_ENV=production ENV_CONFIG=prod node build/build.js" },
目錄結構 |-- config | |-- dev.env.js | |-- index.js | |-- prod.env.js | `-- test.env.js
'use strict' const merge = require('webpack-merge') const prodEnv = require('./prod.env') const env = process.env.NODE_ENV module.exports = merge(prodEnv, { NODE_ENV: '"development"', ENV_CONFIG: '"dev"', API_ROOT: env === 'production' ? '"http://(線上開發環境請求地址)"' : '"/apis"' })
'use strict' const merge = require('webpack-merge') const prodEnv = require('./prod.env') module.exports = merge(prodEnv, { NODE_ENV: '"testing"', ENV_CONFIG: '"test"', API_ROOT: '"http://(線上測試環境請求地址)"' })
'use strict' module.exports = { NODE_ENV: '"production"', ENV_CONFIG: '"prod"', API_ROOT: '"http://(線上生產環境請求地址)"' }
解決本地開發啓動後瀏覽器跨域問題,在此處配置服務代理。
dev對象參數下修改以下配置:
proxyTable: { '/apis': { target: 'http://(本地開發環境請求地址)', changeOrigin: true, // 是否容許跨域 pathRewrite: { '^/apis': '' // 重寫 } }, },
build 對象參數下添加以下參數
devEnv: require('./dev.env'),
testEnv: require('./test.env'),
prodEnv: require('./prod.env'),
// process.env.NODE_ENV = 'production' // 將此行代碼註釋 // const spinner = ora('building for production...') const spinner = ora('building for ' + process.env.NODE_ENV + ' of ' + process.env.ENV_CONFIG + ' production...')
原代碼 const env = require('../config/prod.env') 修改後 const env = config.build[process.env.ENV_CONFIG+'Env']
配置文檔一中是在 API 文件中獲取配置的請求地址,也能夠在 axios 配置中設置統一的默認請求地址
詳見 axios 配置中,axios 文件夾下的 index.js 配置文件
// 根據環境設置請求baseURL axios.defaults.baseURL = process.env.API_ROOT