Vue-Cli 項目基礎搭建

寫在開頭的開頭

目標搭建一個Vue Cli 中後臺項目的基礎。一步一步搭建,衆多知識點已經有不少文字,這裏會綜合比較多的鏈接。接觸的點會多,可是篇幅,不但願太大。
學習的時候,但願多翻閱文檔,資料地址也會引入到原文

資料

後臺多是這樣的以 iview-admin 爲栗子在線 Demo

拆解(結合將要作的作一個iView 拆解)

  • 側邊欄菜單權限過濾,這部分實現須要配合路由,權限數據保存,跨組件通訊(iview 使用了vuex)
  • 標籤頁,這部分也須要吧打開的頁面使用數據存起來,也搭配 keep-alive 附錄中的 VUE 9個性能優化祕密?(vue-9-perf-secrets) 其中之一優化辦法就是 keep-alive

將要作什麼

@vue/cli 建立項目

開發環境:
+ Win10 x64
+ node v10.15.3
+ npm v6.4.1
+ @vue/cli 3.6.3
複製代碼
vue create project-name
複製代碼

縮減篇幅,省略具體建立過程。html

  1. step.1 選擇設置,默認設置或者自定義Manually
  1. step.2 自定義配置,有 TypeScript支持,也有PWA。
  1. step.3 路由模式選擇 history
  1. step.4 CSS 編譯器選擇
  1. step.5 ESLint 以及配置選擇
  1. step.6 什麼時候檢查 Lint
  1. step.7 ESLint 配置文件寫在哪裏,能夠單獨文件,也能夠在package.json
  1. step.8 是否保存配置信息,下次項目使用 N
  2. 自動安裝依賴

目錄規劃

.
├── build  項目構建配置
├── public  打包所需靜態資源
└── src
    ├── api  AJAX請求
    └── assets  項目靜態資源
        ├── icons  SVG 圖標資源
        ├── fonts  字體圖標資源
        └── images  圖片資源
    ├── components  業務組件
    ├── config  項目運行配置
    ├── directive  自定義指令
    ├── libs  封裝工具函數
    ├── router  路由配置
    ├── store  Vuex配置
    └── views  頁面文件
複製代碼

字體庫 && SVG

main.js 引入全局 阿里 Ant 圖標字體庫

SVG

圖標字體,也能夠用SVG代替,方案能夠作一個SVG組件,經過名字,載入不一樣的 SVG圖標,經過size,控制圖標大小,color,控制顏色便可vue


網絡請求 axios封裝api

給axios作個挺靠譜的封裝(報錯,鑑權,跳轉,攔截,提示) iview-admin axios 用繼承封裝。當中亮點,對請求隊列作了處理,屢次請求同一個地址,會節流。node

// 安裝
npm i axios
複製代碼
  • 統一捕獲接口報錯 : 用的axios內置的攔截器
  • 彈窗提示: 引入 Element UI的Message組件
  • 報錯重定向: 路由鉤子
  • 基礎鑑權: 服務端過時時間戳和token,還有藉助路由的鉤子
  • 客戶端支持防止 CSRF/XSRF
  • 表單序列化: 我這邊直接用qs(npm模塊),你有時間也能夠本身寫
  • 號外,對請求隊列優化,尤爲是翻頁時屢次請求。(未完成)

請求攔截器 Axios.interceptors.request

帶上本身須要的參數,好比CSRF/XSRF,基礎鑑權 token,請求時間戳
對請求數據作處理,轉表單,或轉Json
對錯誤的狀況統一處理webpack

響應攔截器 Axios.interceptors.interceptors

對響應結果統一處理,響應結果狀態status 判斷解封裝,錯誤處理等ios

axios可配置

iview-admin libs/axios.jsgit

import axios from 'axios'
import store from '@/store'
// import { Spin } from 'iview'
const addErrorLog = errorInfo => {
  const { statusText, status, request: { responseURL } } = errorInfo
  let info = {
    type: 'ajax',
    code: status,
    mes: statusText,
    url: responseURL
  }
  if (!responseURL.includes('save_error_logger')) store.dispatch('addErrorLog', info)
}

class HttpRequest {
  constructor (baseUrl = baseURL) {
    this.baseUrl = baseUrl
    this.queue = {}
  }
  getInsideConfig () {
    const config = {
      baseURL: this.baseUrl,
      headers: {
        //
      }
    }
    return config
  }
  destroy (url) {
    delete this.queue[url]
    if (!Object.keys(this.queue).length) {
      // Spin.hide()
    }
  }
  interceptors (instance, url) {
    // 請求攔截
    instance.interceptors.request.use(config => {
      // 添加全局的loading...
      if (!Object.keys(this.queue).length) {
        // Spin.show() // 不建議開啓,由於界面不友好
      }
      this.queue[url] = true
      return config
    }, error => {
      return Promise.reject(error)
    })
    // 響應攔截
    instance.interceptors.response.use(res => {
      this.destroy(url)
      const { data, status } = res
      return { data, status }
    }, error => {
      this.destroy(url)
      let errorInfo = error.response
      if (!errorInfo) {
        const { request: { statusText, status }, config } = JSON.parse(JSON.stringify(error))
        errorInfo = {
          statusText,
          status,
          request: { responseURL: config.url }
        }
      }
      addErrorLog(errorInfo)
      return Promise.reject(error)
    })
  }
  request (options) {
    const instance = axios.create()
    options = Object.assign(this.getInsideConfig(), options)
    this.interceptors(instance, options.url)
    return instance(options)
  }
}
export default HttpRequest


複製代碼

Vuex 數據管理

面試一般都會被問到,數據通訊的問題,跨組件之間如何實現數據管理。github

固然方法不止 vuex ,web

  • props
  • provide / inject
  • 本地存儲Local Storage,Cookies 也能夠實現。
  • vuex,項目比較簡單時,store 都在一個文件中,或者 getter,actions,mutations,mutations-types,state拆分。應用比較大的時候,能夠按模塊拆分。

擴展閱讀

沒有廢話的vue高級進階( 二 ) 8種組件通訊詳解面試

import Vue from 'vue'
import Vuex from 'vuex'
// 按模塊拆分
import app from './module/app'
// 打開 vuex logs
import createLogger from 'vuex/dist/logger'

Vue.use(Vuex)

const debug = process.env.NODE_ENV !== 'production'

export default new Vuex.Store({
  state: {

  },
  mutations: {

  },
  actions: {

  },
  // 按模塊引入
  modules: {
    app
  },
  strict: debug,
  plugins: debug ? [createLogger()] : []
})
複製代碼

Vue Router. 作好路由守衛

包含的功能:

  • 嵌套的路由/視圖表
  • 模塊化的、基於組件的路由配置
  • 路由參數、查詢、通配符
  • 基於 Vue.js 過渡系統的視圖過渡效果
  • 細粒度的導航控制
  • 帶有自動激活的 CSS class 的連接
  • HTML5 歷史模式或 hash 模式,在 IE9 中自動降級
  • 自定義的滾動條行爲

高級進階

  • 導航守衛
  • 路由元信息
  • 過分動效
  • 數據獲取
  • 滾動行爲
  • 路由懶加載

咱們能夠作什麼

  • 嵌套路由/視圖表,子路由 children 能夠更好的組織頁面
  • 路由參數,跳轉,傳參,匹配
  • 過渡效果,滾動行爲
  • 導航守衛,權限限定
  • 路由懶加載,結合 Vue 的異步組件和 Webpack 的代碼分割功能,輕鬆實現路由組件的懶加載
  • 判斷用戶是否已經登陸,控制進入權限頁面。
  • 定義路由的時候能夠配置 meta 字段,個性化定製一些功能
  • 等等

全局前置守衛

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // todo 在路由守衛中,能夠判斷用戶登陸狀況,鑑權,
})
複製代碼

菜單欄權限過濾

iview-admin 中側邊菜單欄權限,是在 router meta增長一個字段,ajax

流程

  • vuex 搭配使用 vuex-persistedstate vuex 數據持久化
  • 1.用戶登陸後,獲取用戶權限,權限列表(列表必須能和,router meta 字段對比)
  • 2.提交用戶數據,權限等到 Vuex(數據中心)
  • 3.用戶權限和 router meta 生成權限列表,提交到vuex
  • 4.菜單欄頁面,getter 到數據變化,更新菜單欄
  • 5.注意:思考是否須要,數據須要本地化一份,在用戶刷新頁面,或者vuex(數據中心)數據丟失時,還要能拿到用戶權限,token等數據。

vue.config.js

Vue CLI.

調整 webpack 配置最簡單的方式就是在 vue.config.js 中的 configureWebpack 選項提供一個對象:

// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      new MyAwesomeWebpackPlugin()
    ]
  }
}
複製代碼

該對象將會被 webpack-merge 合併入最終的 webpack 配置。

文檔中,說起鏈式操做 (高級)、修改 Loader 選項、替換Loader、新建Loader、修改插件,等等。

環境變量和模式

NODE_ENV
若是在環境中有默認的 NODE_ENV,你應該移除它或在運行 vue-cli-service 命令的時候明確地設置 NODE_ENV。

模式

模式是 Vue CLI 項目中一個重要的概念。默認狀況下,一個 Vue CLI 項目有三個模式:

  • development 模式用於 vue-cli-service serve
  • production 模式用於 vue-cli-service buildvue-cli-service test:e2e
  • test 模式用於 vue-cli-service test:unit

注意模式不一樣於 NODE_ENV,一個模式能夠包含多個環境變量。也就是說,每一個模式都會將 NODE_ENV 的值設置爲模式的名稱——好比在 development 模式下 NODE_ENV 的值會被設置爲 "development"

你能夠經過爲 .env 文件增長後綴來設置某個模式下特有的環境變量。好比,若是你在項目根目錄建立一個名爲 .env.development 的文件,那麼在這個文件裏聲明過的變量就只會在 development 模式下被載入。

你能夠經過傳遞 --mode 選項參數爲命令行覆寫默認的模式。例如,若是你想要在構建命令中使用開發環境變量,請在你的 package.json 腳本中加入:

"dev-build": "vue-cli-service build --mode development",
複製代碼

在客戶端側代碼中使用環境變量

只有以 VUE_APP_ 開頭的變量會被 webpack.DefinePlugin 靜態嵌入到客戶端側的包中。你能夠在應用的代碼中這樣訪問它們:

console.log(process.env.VUE_APP_SECRET)
複製代碼

vue.config.js

  • 有了 NODE_ENV 能夠對不一樣環境作出不一樣的配置
  • 文件夾別名 resolve.alias
  • 設置代理 devServer,解決跨域開發問題
const path = require('path')
// Webpack包文件分析器
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

function resolve (dir) {
  return path.join(__dirname, './', dir)
}

// 項目部署基礎 (webpack 的 devServer 地址)
// process.env.NODE_ENV
// 正式環境 production
// 開發環境 development
// 默認狀況下,咱們假設你的應用將被部署在域的根目錄下,
// 例如:https://www.my-app.com/
// 默認:'/'
// 若是您的應用程序部署在子路徑中,則須要在這指定子路徑
// 例如:https://www.foobar.com/my-app/
// 須要將它改成'/my-app/'
const BASE_URL = process.env.NODE_ENV === 'production'
  ? '/my-app/'
  : '/'

module.exports = {
  // 這裏是對環境的配置,不一樣環境對應不一樣的BASE_API,以便 axios 的請求地址不一樣 baseUrl 從 Vue CLI 3.3 起已棄用,請使用publicPath
  publicPath: BASE_URL,
  // tweak internal webpack configuration.
  // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
  // 若是你不須要使用eslint,把lintOnSave設爲false便可
  lintOnSave: false,

  /**
   * 對內部的 webpack 配置進行更細粒度的修改
   * https://github.com/neutrinojs/webpack-chain see
   * https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
   * @param config
   */
  chainWebpack: (config) => {
    // key,value自行定義,好比.set('@@', resolve('src/components'))
    config.resolve.alias
      .set('@', resolve('src'))
      .set('api', resolve('src/api'))
      .set('common', resolve('src/common'))
      .set('components', resolve('src/components'))
  },
  /**
   * 調整 webpack 配置
   * https://cli.vuejs.org/zh/guide/webpack.html#%E7%AE%80%E5%8D%95%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F
   * @param config
   */
  configureWebpack: config => {
    // 生產and測試環境
    let pluginsPro = [
      // Webpack包文件分析器(https://github.com/webpack-contrib/webpack-bundle-analyzer)
      // new BundleAnalyzerPlugin()
    ]
    // 開發環境
    let pluginsDev = []
    if (process.env.NODE_ENV === 'production') {
      // 爲生產環境修改配置... process.env.NODE_ENV !== 'development'
      config.plugins = [...config.plugins, ...pluginsPro]
    } else {
      // 爲開發環境修改配置...
      config.plugins = [...config.plugins, ...pluginsDev]
    }
  },
  // 打包時不生成.map文件
  productionSourceMap: false,
  // webpack-dev-server 相關配置 https://webpack.js.org/configuration/dev-server/
  // 這裏寫你調用接口的基礎路徑,來解決跨域,若是設置了代理,那你本地開發環境的axios的baseUrl要寫爲 '' ,即空字符串
  // devServer: {
  //   proxy: 'localhost:3000'
  // }
  devServer: {
    // host: 'localhost',
    host: '0.0.0.0',
    port: 8000, // 端口號
    https: false, // https:{type:Boolean}
    open: true, // 配置自動啓動瀏覽器
    hotOnly: true, // 熱更新
    // 配置跨域處理,只有一個代理
    proxy: {
      '/my-app/*': {
        target: 'http://xxx.xxx.xxx.xxx:xxxx/',
        changeOrigin: true,
        pathRewrite: {
          '^/my-app': ''
        }
      },
      '/SocketWeb/*': {
        target: 'http://xxx.xxx.xxx.xxx:xxxx',
        changeOrigin: true,
        // websocket支持
        ws: true,
        secure: false
      }
    }
  }
}

複製代碼
開發基礎環境能夠了,開發中遇到的文件夾別名,請求跨域的問題解決了,自定義配置,也能夠更具本身公司的狀況配置。還有比較自定義的部分能夠參照文檔配置。

webpack-bundle-analyzer

安裝

$ npm intall webpack-bundle-analyzer --save-dev
複製代碼
  1. 配置vue.config.js 打開註釋 webpack-bundle-analyzer 的部分。
  2. 在script中添加
// 在運行 build 時,後臺面添加  --report
npm run build --report
// 或者在script中添加新命令
"analyze": "npm_config_report=true npm run build"
複製代碼

VUE 9個性能優化祕密?(vue-9-perf-secrets)

相關文章
相關標籤/搜索