自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

基于Vue的前端架構(gòu),我做了這15點

開發(fā) 前端
本文幾乎就是一篇軟件設(shè)計文檔。Vue 中后臺項目可能遇到的問題幾乎都覆蓋了,并且提供了詳盡合理的解決方法,值得收藏學(xué)習(xí)。

[[360028]]

1.分解需求

技術(shù)棧

  •  考慮到后續(xù)招人和現(xiàn)有人員的技術(shù)棧,選擇 Vue 作為框架。
  •  公司主要業(yè)務(wù)是 GIS 和 BIM,通常開發(fā)一些中大型的系統(tǒng),所以 vue-router 和 vuex 都是必不可少的。
  •  放棄了 Element UI 選擇了 Ant Design Vue(最近 Element 好像復(fù)活了,麻蛋)。
  •  工具庫選擇 lodash。

建立腳手架

  •  搭建 NPM 私服。
  •  使用 Node 環(huán)境開發(fā) CLI 工具,參考我自己寫過的一篇 -【 搭建自己的腳手架—“優(yōu)雅”生成前端工程】。
  •  基于 @vue/cli 搭建基礎(chǔ)的模板(大家都比較了解,節(jié)省開發(fā)時間,遠(yuǎn)勝于從零開始搭建)。
  •  根據(jù)業(yè)務(wù)需求定義各種開發(fā)中可能用到的功能(組件庫、狀態(tài)管理、過濾器、指令、CSS內(nèi)置變量、CSS Mixins、表單驗證、工具函數(shù)等)。
  •  性能優(yōu)化,例如對 Ant Design Vue 組件庫的優(yōu)化。

開發(fā)規(guī)范

  •  對代碼風(fēng)格、命名規(guī)則、目錄結(jié)構(gòu)進行統(tǒng)一規(guī)范。
  •  靜態(tài)資源的使用規(guī)范。
  •  單元測試、提交線上測試規(guī)范。
  •  Git 提交記錄和多人協(xié)作規(guī)范。

2.樣式

CSS 預(yù)處理器的選擇

  •  Sass/Scss ✅
  •  Less ✅
  •  Stylus ⭕

為什么選擇了兩個?因為公司團隊跟傾向于使用 scss 開發(fā),less 是為了覆蓋 ant design vue 的樣式,stylus 只有我自己喜歡這種風(fēng)格。

局部樣式與全局樣式

局部樣式

一般都是使用 scoped 方案: 

  1. <style lang="scss" scoped>  
  2.   ...  
  3. </style>  
  4. 復(fù)制代碼 

全局樣式

全局樣式 目錄:@/styles

variable.scss: 全局變量管理 mixins.scss: 全局 Mixins 管理 global.scss: 全局樣式

其中 variable.scss 和 mixins.scss 會優(yōu)先于 global.css 加載,并且可以不通過 import 的方式在項目中任何位置使用這些變量和 mixins。 

  1. // vue.config.js  
  2. module.exports = {  
  3.   css: {  
  4.     loaderOptions: {  
  5.       sass: {  
  6.         prependData: `  
  7.         @import '@/styles/variable.scss';  
  8.         @import '@/styles/mixins.scss';  
  9.         `,  
  10.       },  
  11.     },  
  12.   },  
  13.  
  14. 復(fù)制代碼 

體驗優(yōu)化

頁面載入進度條

使用 nprogress 對路由跳轉(zhuǎn)時做一個偽進度條,這樣做在網(wǎng)絡(luò)不好的情況下可以讓用戶知道頁面已經(jīng)在加載了: 

  1. import NProgress from 'nprogress';  
  2. router.beforeEach(() => {  
  3.   NProgress.start();  
  4. });  
  5. router.afterEach(() => {  
  6.   NProgress.done();  
  7. });  
  8. 復(fù)制代碼 

美化滾動條

一直用 Mac 做前端,突然發(fā)現(xiàn)同事的 Windows 上出現(xiàn)了十分丑陋的滾動條,為了保持一致: 

  1. ::-webkit-scrollbar {  
  2.   width: 6px; 
  3.    height: 6px;  
  4.  
  5. ::-webkit-scrollbar-track {  
  6.   width: 6px;  
  7.   background: rgba(#101F1C, 0.1);  
  8.   -webkit-border-radius: 2em;  
  9.   -moz-border-radius: 2em;  
  10.   border-radius: 2em;  
  11.  
  12. ::-webkit-scrollbar-thumb {  
  13.   background-color: rgba(#101F1C, 0.5);  
  14.   background-clip: padding-box;  
  15.   min-height: 28px;  
  16.   -webkit-border-radius: 2em;  
  17.   -moz-border-radius: 2em;  
  18.   border-radius: 2em;  
  19.  
  20. ::-webkit-scrollbar-thumb:hover {  
  21.   background-color: rgba(#101F1C, 1);  
  22.  
  23. 復(fù)制代碼 

靜態(tài)資源加載頁面

首次加載頁面時,會產(chǎn)生大量的白屏?xí)r間,這時做一個 loading 效果看起來會很友好,其實很簡單,直接在 public/index.html 里寫一些靜態(tài)的樣式即可。

移動端 100vh 問題

在移動端使用 100vh 時,發(fā)現(xiàn)在 Chrome、Safari 瀏覽器中,因為瀏覽器欄和一些導(dǎo)航欄、鏈接欄導(dǎo)致不一樣的呈現(xiàn):

你以為的 100vh === 視口高度

實際上 100vh === 視口高度 + 瀏覽器工具欄(地址欄等等)的高度

解決方案

安裝 vh-check npm install vh-check \--save 

  1. import vhCheck from 'vh-check';  
  2. vhCheck('browser-address-bar');  
  3. 復(fù)制代碼 

定義一個 CSS Mixin 

  1. @mixin vh($height: 100vh) {  
  2.   height: $height;  
  3.   height: calc(#{$height} - var(--browser-address-bar, 0px));  
  4.  
  5. 復(fù)制代碼 

之后就是哪里不會點哪里。

3.組件庫

因為 Element UI 長期沒更新,并且之前使用過 React 的 Ant Design(重點),所以組件庫選擇了Ant Design Vue。

覆蓋 Ant Design Vue 樣式

設(shè)計師眼中的 Ant Design === '丑'(心酸)。

1.使用 .less 文件

Ant Design Vue 的樣式使用了 Less 作為開發(fā)語言,并定義了一系列全局/組件的樣式變量,所以需要安裝了 less、less-loader,在 @/styles/antd-theme.less 可以覆蓋默認(rèn)樣式。

優(yōu)點是:

方便快捷,可以修改 class,覆蓋默認(rèn)變量。

缺點是:

必須引入 @import '~ant-design-vue/dist/antd.less'; ,引入后會將所有的組件樣式全部引入,導(dǎo)致打包后的 css 體積達(dá)到 500kb 左右。

2.使用 JavaScript 對象

通過 JavaScript 對象的方式可以修改內(nèi)置變量,需要對 Less 進行配置: 

  1. // vue.config.js  
  2. const modifyVars = require('./src/styles/antdTheme.js');  
  3. module.exports = {  
  4.   css: {  
  5.     loaderOptions: {  
  6.       less: {  
  7.         lessOptions: {  
  8.           javascriptEnabled: true,  
  9.           modifyVars,  
  10.         },  
  11.       },  
  12.     },  
  13.   },  
  14.  
  15. 復(fù)制代碼 

這一步還可以繼續(xù)優(yōu)化,通過 babel-plugin-import 使 Ant Design Vue 的組件樣式可以按需加載: 

  1. // babel.config.js  
  2. module.exports = {  
  3.   presets: [  
  4.     '@vue/cli-plugin-babel/preset',  
  5.   ],  
  6.   plugins: [  
  7.     [  
  8.       'import',  
  9.       { libraryName: 'ant-design-vue', libraryDirectory: 'es', style: true },  
  10.     ],  
  11.   ],  
  12. };  
  13. 復(fù)制代碼 

優(yōu)點是:

可以按需引入,打包后的 CSS 體積取決于你引用了多少個組件。

缺點是:

不能使用 class 進行樣式覆蓋。

干掉無用的圖標(biāo)

Ant Design Vue 把所有的 Icon 一次性引入(不管你因用了多少個組件),這使得體積打包后圖標(biāo)所占的體積竟然有幾百 kb 之多。這些圖標(biāo)大多數(shù)不會被設(shè)計師所采納,所以部分圖標(biāo)都應(yīng)該被干掉:

創(chuàng)建一個 icons.js 來管理 Ant Design Vue 圖標(biāo),這里以一個 Loading 圖標(biāo)為例: 

  1. // @/src/assets/icons.js  
  2. export { default as LoadingOutline } from '@ant-design/icons/lib/outline/LoadingOutline';  
  3. 復(fù)制代碼 

如何知道你要加載的圖標(biāo)在什么路徑下?

在 @ant-design/icons/lib 目錄下有三種風(fēng)格的圖標(biāo),分別是 fill、outline、twotone,這里面內(nèi)部的文件并不是 svg 格式,而是 js 和 ts 格式,這就是為什么我們可以這么引入圖標(biāo)的關(guān)鍵所在了。

下一步是通過配置 vue.config.js 將這個文件引入進來: 

  1. // vue.config.js  
  2. module.exports = {  
  3.   configureWebpack: {  
  4.     resolve: {  
  5.       alias: {  
  6.         '@ant-design/icons/lib/dist$': path.resolve(__dirname, './src/assets/icons.js'), 
  7.       },  
  8.     },  
  9.   },  
  10.  
  11. 復(fù)制代碼 

解決 Moment 多國語

解決到這之后,Ant Design Vue 居然還很大,這是因為 moment 是 Ant Design Vue 中有強依賴該插件,所以使用 webpack 插件減小打包體積,這里我們只保留 zh-cn 語言包: 

  1. // vue.config.js  
  2. module.exports = {  
  3.   chainWebpack: (config) => {  
  4.     config  
  5.       .plugin('ContextReplacementPlugin')  
  6.       .use(webpack.ContextReplacementPlugin, [/moment[/\\]locale$/, /zh-cn/]);  
  7.   },  
  8.  
  9. 復(fù)制代碼 

部分組件需要在頁面內(nèi)引用

Ant Design Vue 中部分體積較大的組件,例如 DatePicker,根據(jù)業(yè)務(wù)需求,應(yīng)考慮在頁面中進行加載,盡量保證首屏加載的速度: 

  1. <script>  
  2. import { DatePicker } from 'ant-design-vue';  
  3. export default {  
  4.   components: {  
  5.     ADatePicker: DatePicker,  
  6.   },  
  7.  
  8. </script>  
  9. 復(fù)制代碼 

4.靜態(tài)資源與圖標(biāo)

靜態(tài)資源

所有的靜態(tài)資源文件都會上傳到 阿里云 OSS 上,所以在環(huán)境變量上加以區(qū)分。

.env.development 與 .env.production 的 VUE_APP_STATIC_URL 屬性分別配置了本地的靜態(tài)資源服務(wù)器地址和線上 OSS 的地址。

本地的靜態(tài)資源服務(wù)器是通過 pm2 + http-server 創(chuàng)建的,設(shè)計師切完直接扔進來就好了。

自動注冊 Svg 圖標(biāo)

在日常的開發(fā)中,總是會有著大量的圖標(biāo)需要使用,這里我們直接選擇使用 SVG 圖標(biāo)。但是如果每次使用圖標(biāo)還需要通過路徑找到這張圖標(biāo)豈不是很麻煩?

下面這種才是我想要的方案(直接 name 等于 文件名即可): 

  1. <template>  
  2.     <svg name="logo" />  
  3. </template>  
  4. 復(fù)制代碼 

而且最后打包后需要合并成一張雪碧圖。

首先需要對 @/assets/icons 文件夾下的 svg 圖標(biāo)進行自動注冊,需要對 webpack 和 svg-sprite-loader 進行了相關(guān)設(shè)置,文件全部打包成 svg-sprite。 

  1. module.exports = {  
  2.   chainWebpack: (config) => {  
  3.     config.module  
  4.       .rule('svg')  
  5.       .exclude.add(resolve('src/assets/icons'))  
  6.       .end();  
  7.     config.module  
  8.       .rule('icons')  
  9.       .test(/\.svg$/)  
  10.       .include.add(resolve('src/assets/icons'))  
  11.       .end()  
  12.       .use('svg-sprite-loader')  
  13.       .loader('svg-sprite-loader');  
  14.   },  
  15.  
  16. 復(fù)制代碼 

寫一個全局用的 Vue 組件 <m-svg />:

// @/components/m-svg/index.js 

  1. const requireAll = (requireContext) => requireContext.keys().map(requireContext);  
  2. const req = require.context('@/assets/icons', false, /\.svg$/);  
  3. requireAll(req);  
  4. 復(fù)制代碼 

@/components/m-svg/index.vue 

  1. <template>  
  2.   <svg class="mw-svg" aria-hidden="true">  
  3.     <use :xlink:href="iconName"></use>  
  4.   </svg>  
  5. </template>  
  6. <script>  
  7. export default {  
  8.   name: 'm-svg',  
  9.   props: {  
  10.     name: { type: String, default: '' },  
  11.   },  
  12.   computed: {  
  13.     iconName() {  
  14.       return `#${this.name}`; 
  15.     },  
  16.   },  
  17. };  
  18. </script>  
  19. <style lang="scss" scoped>  
  20. .mw-svg {  
  21.   width: 1.4em;  
  22.   height: 1.4em;  
  23.   fill: currentColor;  
  24.   overflow: hidden;  
  25.   line-height: 1em;  
  26.   display: inline-block;  
  27.  
  28. </style>  
  29. 復(fù)制代碼 

參數(shù) name

  •  類型:String
  •  默認(rèn)值:null
  •  說明:放置在 @/assets/icons 文件夾下的文件名

樣式

  •  圖標(biāo)的大小可以通過 width + height 屬性改變。
  •  通過改變 font-size 屬性改變,寬高 = font-zise * 1.4

5.異步請求

封裝 Axios

在 @/libs/request.js 路徑下對 Axios 進行封裝,封裝了請求參數(shù),請求頭,以及錯誤提示信息、 request 攔截器、response 攔截器、統(tǒng)一的錯誤處理、baseURL 設(shè)置等。

廢話不說直接貼代碼: 

  1. import axios from 'axios';  
  2. import get from 'lodash/get';  
  3. import storage from 'store';  
  4. // 創(chuàng)建 axios 實例  
  5. const request = axios.create({  
  6.  // API 請求的默認(rèn)前綴  
  7.  baseURL: process.env.VUE_APP_BASE_URL,  
  8.  timeout: 10000, // 請求超時時間  
  9. });  
  10. // 異常攔截處理器  
  11. const errorHandler = (error) => {  
  12.  const status = get(error, 'response.status');  
  13.  switch (status) {  
  14.    /* eslint-disable no-param-reassign */  
  15.    case 400: error.message = '請求錯誤'; break;  
  16.    case 401: error.message = '未授權(quán),請登錄'; break;  
  17.    case 403: error.message = '拒絕訪問'; break;  
  18.    case 404: error.message = `請求地址出錯: ${error.response.config.url}`; break;  
  19.    case 408: error.message = '請求超時'; break;  
  20.    case 500: error.message = '服務(wù)器內(nèi)部錯誤'; break;  
  21.    case 501: error.message = '服務(wù)未實現(xiàn)'; break;  
  22.    case 502: error.message = '網(wǎng)關(guān)錯誤'; break;  
  23.    case 503: error.message = '服務(wù)不可用'; break;  
  24.    case 504: error.message = '網(wǎng)關(guān)超時'; break;  
  25.    case 505: error.message = 'HTTP版本不受支持'; break;  
  26.    default: break;  
  27.    /* eslint-disabled */  
  28.  }  
  29.  return Promise.reject(error);  
  30. };  
  31. // request interceptor  
  32. request.interceptors.request.use((config) => {  
  33.  // 如果 token 存在  
  34.  // 讓每個請求攜帶自定義 token 請根據(jù)實際情況自行修改  
  35.  // eslint-disable-next-line no-param-reassign 
  36.   config.headers.Authorization = `bearer ${storage.get('ACCESS_TOKEN')}`;  
  37.  return config;  
  38. }, errorHandler);  
  39. // response interceptor  
  40. request.interceptors.response.use((response) => {  
  41.  const dataAxios = response.data;  
  42.  // 這個狀態(tài)碼是和后端約定的  
  43.  const { code } = dataAxios;  
  44.  // 根據(jù) code 進行判斷  
  45.  if (code === undefined) {  
  46.    // 如果沒有 code 代表這不是項目后端開發(fā)的接口  
  47.    return dataAxios;  
  48.  // eslint-disable-next-line no-else-return  
  49.  } else {  
  50.    // 有 code 代表這是一個后端接口 可以進行進一步的判斷  
  51.    switch (code) {  
  52.      case 200:  
  53.        // [ 示例 ] code === 200 代表沒有錯誤  
  54.        return dataAxios.data;  
  55.      case 'xxx':  
  56.        // [ 示例 ] 其它和后臺約定的 code  
  57.        return 'xxx';  
  58.      default:  
  59.        // 不是正確的 code  
  60.        return '不是正確的code';  
  61.    }  
  62.  }  
  63. }, errorHandler);  
  64. export default request;  
  65. 復(fù)制代碼 
  •  通過 VUE_APP_BASE_URL 區(qū)分線上與開發(fā)環(huán)境的 API 地址。
  •  code 起到一個比較關(guān)鍵的作用,例如 token 過期時的驗證。
  •  使用了一個叫 sotre 的包作為本地儲存的工具用來存儲 token。

跨域問題

跨域問題一般情況直接找后端解決了,你要是不好意思打擾他們的話,可以用 devServer 提供的 proxy 代理: 

  1. // vue.config.js  
  2. devServer: {  
  3.   proxy: {  
  4.     '/api': {  
  5.       target: 'http://47.100.186.132/your-path/api',  
  6.       ws: true,  
  7.       changeOrigin: true,  
  8.       pathRewrite: {  
  9.         '^/api': ''  
  10.       }  
  11.     }  
  12.   }  
  13.  
  14. 復(fù)制代碼 

Mock 數(shù)據(jù)

一個很常見的情況,后端接口沒出來,前端在這干瞪眼。

Mock 數(shù)據(jù)功能是基于 mock.js (opens new window)開發(fā),通過 webpack 進行自動加載 mock 配置文件。

規(guī)則

  •  所有的 mock 配置文件均應(yīng)放置在 @/mock/services 路徑內(nèi)。
  •  在 @/mock/services 內(nèi)部可以建立業(yè)務(wù)相關(guān)的文件夾分類存放配置文件。
  •  所有的配置文件應(yīng)按照 ***.mock.js 的命名規(guī)范創(chuàng)建。
  •  配置文件使用 ES6 Module 導(dǎo)出 export default 或 export 一個數(shù)組。

入口文件 

  1. import Mock from 'mockjs';  
  2. Mock.setup({  
  3.   timeout: '500-800',  
  4. });  
  5. const context = require.context('./services', true, /\.mock.js$/);  
  6. context.keys().forEach((key) => {  
  7.   Object.keys(context(key)).forEach((paramKey) => {  
  8.     Mock.mock(...context(key)[paramKey]);  
  9.   }); 
  10. });  
  11. 復(fù)制代碼 

示例模板 

  1. import Mock from 'mockjs';  
  2. const { Random } = Mock;  
  3. export default [  
  4.   RegExp('/example.*'),  
  5.   'get',  
  6.   {  
  7.     'range|50-100': 50,  
  8.     'data|10': [  
  9.       {  
  10.         // 唯一 ID  
  11.         id: '@guid()',  
  12.         // 生成一個中文名字  
  13.         cname: '@cname()',  
  14.         // 生成一個 url  
  15.         url: '@url()',  
  16.         // 生成一個地址  
  17.         county: Mock.mock('@county(true)'),  
  18.         // 從數(shù)組中隨機選擇一個值  
  19.         'array|1': ['A', 'B', 'C', 'D', 'E'], 
  20.         // 隨機生成一個時間  
  21.         time: '@datetime()',  
  22.         // 生成一張圖片  
  23.         image: Random.dataImage('200x100', 'Mock Image'),  
  24.       },  
  25.     ],  
  26.   },  
  27. ];  
  28. 復(fù)制代碼 

6.路由

Layout

布局暫時分為三大類:

  •  frameIn:基于 BasicLayout,通常需要登錄或權(quán)限認(rèn)證的路由。
  •  frameOut:不需要動態(tài)判斷權(quán)限的路由,如登錄頁或通用頁面。
  •  errorPage:例如404。

權(quán)限驗證

通過獲取當(dāng)前用戶的權(quán)限去比對路由表,生成當(dāng)前用戶具的權(quán)限可訪問的路由表,通過 router.addRoutes 動態(tài)掛載到 router 上。

  •  判斷頁面是否需要登陸狀態(tài),需要則跳轉(zhuǎn)到 /user/login
  •  本地存儲中不存在 token 則跳轉(zhuǎn)到 /user/login
  •  如果存在 token,用戶信息不存在,自動調(diào)用 vuex '/system/user/getInfo'

在路由中,集成了權(quán)限驗證的功能,需要為頁面增加權(quán)限時,在 meta 下添加相應(yīng)的 key:

auth

  •  類型:Boolean
  •  說明:當(dāng) auth 為 true 時,此頁面需要進行登陸權(quán)限驗證,只針對 frameIn 路由有效。

permissions

  •  類型:Object
  •  說明:permissions 每一個 key 對應(yīng)權(quán)限功能的驗證,當(dāng) key 的值為 true 時,代表具有權(quán)限,若 key 為 false,配合 v-permission 指令,可以隱藏相應(yīng)的 DOM。

在這里貼一下路由跳轉(zhuǎn)時權(quán)限驗證的代碼: 

  1. import router from '@/router';  
  2. import store from '@/store';  
  3. import storage from 'store';  
  4. import util from '@/libs/utils';  
  5. // 進度條  
  6. import NProgress from 'nprogress';  
  7. import 'nprogress/nprogress.css';  
  8. const loginRoutePath = '/user/login' 
  9. const defaultRoutePath = '/home' 
  10. /** 
  11.  * 路由攔截  
  12.  * 權(quán)限驗證  
  13.  */  
  14. router.beforeEach(async (to, from, next) => {  
  15.   // 進度條  
  16.   NProgress.start();  
  17.   // 驗證當(dāng)前路由所有的匹配中是否需要有登錄驗證的  
  18.   if (to.matched.some((r) => r.meta.auth)) {  
  19.     // 是否存有token作為驗證是否登錄的條件  
  20.     const token = storage.get('ACCESS_TOKEN');  
  21.     if (token && token !== 'undefined') {  
  22.       // 是否處于登錄頁面  
  23.       if (to.path === loginRoutePath) {  
  24.         next({ path: defaultRoutePath });  
  25.         // 查詢是否儲存用戶信息  
  26.       } else if (Object.keys(store.state.system.user.info).length === 0) {  
  27.         store.dispatch('system/user/getInfo').then(() => {  
  28.           next();  
  29.         });  
  30.       } else {  
  31.         next();  
  32.       }  
  33.     } else {  
  34.       // 沒有登錄的時候跳轉(zhuǎn)到登錄界面  
  35.       // 攜帶上登陸成功之后需要跳轉(zhuǎn)的頁面完整路徑  
  36.       next({  
  37.         name: 'Login',  
  38.         query: {  
  39.           redirect: to.fullPath,  
  40.         },  
  41.       });  
  42.       NProgress.done();  
  43.     }  
  44.   } else {  
  45.     // 不需要身份校驗 直接通過  
  46.     next();  
  47.   }  
  48. });  
  49. router.afterEach((to) => {  
  50.   // 進度條  
  51.   NProgress.done();  
  52.   util.title(to.meta.title);  
  53. });  
  54. 復(fù)制代碼 

頁面開發(fā)

  •  根據(jù)業(yè)務(wù)需要劃分,按照路由層級在 views 中創(chuàng)建相對應(yīng)的頁面組件,以文件夾的形式創(chuàng)建,并在文件夾內(nèi)創(chuàng)建 index.vue 文件作為頁面的入口文件。
  •  頁面內(nèi)的組件:在頁面文件夾下創(chuàng)建 components 文件夾,在其內(nèi)部對應(yīng)創(chuàng)建相應(yīng)的組件文件,如果是復(fù)雜組件,應(yīng)以文件夾的形式創(chuàng)建組件。
  •  工具模塊:能夠高度抽象的工具模塊,應(yīng)創(chuàng)建在 @/src/libs 內(nèi)創(chuàng)建 js 文件。

7、構(gòu)建優(yōu)化

包分析工具

構(gòu)建代碼之后,到底是什么占用了這么多空間?靠直覺猜測或者使用 webpack-bundle-analyzer。 

  1. const WebpackBundleAnalyzer = require('webpack-bundle-analyzer');  
  2. module.exports = {  
  3.   chainWebpack: (config) => {  
  4.     if (process.env.use_analyzer) {  
  5.       config  
  6.         .plugin('webpack-bundle-analyzer')  
  7.         .use(WebpackBundleAnalyzer.BundleAnalyzerPlugin);  
  8.     }  
  9.   }, 
  10. };  
  11. 復(fù)制代碼 

開啟 Gzip

對,這這么一句話,后端就得支持你的 .gz 文件了,而你只需要坐著等老板夸: 

  1. chainWebpack: (config) => {  
  2.   config  
  3.     .plugin('CompressionPlugin')  
  4.     .use(CompressionPlugin, []);  
  5. },  
  6. 復(fù)制代碼 

路由懶加載

這塊 @vue/cli 已經(jīng)幫忙處理好了,但也需要了解一下他的原理和如何配置。 

  1.  
  2.   path: 'home',  
  3.   name: 'Home',  
  4.   component: () => import(  
  5.     /* webpackChunkName: "home" */ '@/views/home/index.vue'  
  6.   ),  
  7. },  
  8. 復(fù)制代碼 

webpackChunkName 這條注釋還是很有必要加的,至少你打包后知道又是哪個頁面變得又臭又大。

Preload & Prefetch

不清楚這兩個功能的去 @vue/cli 補課,這兩個功能非常有助于你處理加載的性能。

8.測試框架

直接使用了官方提供的 Vue Test Utils,這東西可以對組件進行測試,很不錯。

寫單元測試在團隊里其實很難推進,不知道大家怎么看。

9.組件庫

對于很多第三方的工具,我堅持認(rèn)為二次封裝成 vue 插件并沒有多少開發(fā)成本,反而讓你在后續(xù)的開發(fā)中變得很靈活。

我對以下庫進行了 vue 插件的封裝,并提交到 npm 私服:

  •  數(shù)字動畫
  •  代碼高亮
  •  大文件上傳(切片、斷點續(xù)傳、秒傳)需要與后端配合
  •  圖片預(yù)覽
  •  Excel 導(dǎo)入導(dǎo)出
  •  富文本編輯器
  •  Markdown 編輯器
  •  代碼編輯器

大文件上傳有興趣的可以留言,我后續(xù)單獨拎出來詳細(xì)的寫一下這塊。

10.Vuex

內(nèi)置一些功能,主要是對以下這些功能做了一些封裝:

  •  用戶信息管理(儲存信息、對 token 進行操作等)
  •  登陸(調(diào)接口)
  •  菜單管理(儲存路由信息,生成菜單,模糊查詢等功能)
  •  UA信息
  •  全屏操作
  •  Loading
  •  日志管理(消息提醒、日志留存、日志上報)

11.過濾器

過濾器是 Vue 提供的一個很好用的功能,聽說 vue3 沒了? 

  1. {{ message | capitalize }}  
  2. 復(fù)制代碼 

我寫了幾個常用的過濾器:

  •  日期時間
  •  剩余時間
  •  區(qū)分環(huán)境的鏈接(主要針對本地靜態(tài)資源服務(wù)器和 OSS )
  •  文件大小
  •  數(shù)字金額
  •  浮點型精度

12.指令

自定義指令可以提供很好的幫助:

  •  組件權(quán)限驗證
  •  文本復(fù)制
  •  快捷鍵綁定
  •  滾動至指定位置
  •  圖片懶加載
  •  焦點

13.開發(fā)規(guī)范

ESLint

不管是多人合作還是個人項目,代碼規(guī)范都是很重要的。這樣做不僅可以很大程度地避免基本語法錯誤,也保證了代碼的可讀性。

這里我們采用了 Airbnb JavaScript Style Guide。

這套規(guī)范給我的感覺就是 很嚴(yán)謹(jǐn)!

CSS 規(guī)范

降低選擇器復(fù)雜性

瀏覽器讀取選擇器,遵循的原則是從選擇器的右邊到左邊讀取。 

  1. #block .text p {  
  2.  color: red;  
  3.  
  4. 復(fù)制代碼 
  •  查找所有 P 元素。
  •  查找結(jié)果 1 中的元素是否有類名為 text 的父元素
  •  查找結(jié)果 2 中的元素是否有 id 為 block 的父元素

選擇器優(yōu)先級

內(nèi)聯(lián) > ID選擇器 > 類選擇器 > 標(biāo)簽選擇器

  •  選擇器越短越好。
  •  盡量使用高優(yōu)先級的選擇器,例如 ID 和類選擇器。
  •  避免使用通配符 *。

使用 flexbox

在早期的 CSS 布局方式中我們能對元素實行絕對定位、相對定位或浮動定位。而現(xiàn)在,我們有了新的布局方式 flexbox,它比起早期的布局方式來說有個優(yōu)勢,那就是性能比較好。不過 flexbox 兼容性還是有點問題,不是所有瀏覽器都支持它,所以要謹(jǐn)慎使用。各瀏覽器兼容性:

  •  Chrome 29+
  •  Firefox 28+
  •  Internet Explorer 11
  •  Opera 17+
  •  Safari 6.1+ (prefixed with -webkit-)
  •  Android 4.4+
  •  iOS 7.1+ (prefixed with -webkit-)

動畫性能優(yōu)化

在 CSS 中,transforms 和 opacity 這兩個屬性更改不會觸發(fā)重排與重繪,它們是可以由合成器(composite)單獨處理的屬性。

屬性值

  •  當(dāng)數(shù)值為 0 - 1 之間的小數(shù)時,建議省略整數(shù)部分的 0。
  •  當(dāng)長度為 0 時建議省略單位。
  •  建議不使用命名色值。
  •  建議當(dāng)元素需要撐起高度以包含內(nèi)部的浮動元素時,通過對偽類設(shè)置 clear 或觸發(fā) BFC 的方式進行 clearfix。盡量不使用增加空標(biāo)簽的方式。
  •  除公共樣式之外,在業(yè)務(wù)代碼中盡量不能使用 !important。
  •  建議將 z-index 進行分層,對文檔流外絕對定位元素的視覺層級關(guān)系進行管理。

字體排版

  •  字號應(yīng)不小于 12px(PC端)。
  •  font-weight 屬性建議使用數(shù)值方式描述。
  •  line-height 在定義文本段落時,應(yīng)使用數(shù)值。

Vue 代碼規(guī)范

常規(guī)

  •  當(dāng)在組件中使用 data 屬性的時候 (除了 new Vue 外的任何地方),它的值必須是返回一個對象的函數(shù) data() { return {...} }。
  •  prop 的定義應(yīng)該盡量詳細(xì),至少需要指定其類型。
  •  布爾類型的 attribute, 為 true 時直接寫屬性值。
  •  不要在computed中對vue變量進行操作。
  •  應(yīng)該優(yōu)先通過 prop 和事件進行父子組件之間的通信,而不是 this.$parent 或改變 prop。
  •  在組件上總是必須用 key 配合 v-for,以便維護內(nèi)部組件及其子樹的狀態(tài)。
  •  v-if 和 v-for 不能同時使用
  •  公共方法盡量不要掛到原型上, 可以寫在 utils 文件,也可以使用 mixin 文件。不要將業(yè)務(wù)公共組件注冊到全局。
  •  不要將任何第三方插件掛載到 vue 原型上。
  •  具有高度通用性的方法,要封裝到 libs、全局組件或指令集里。
  •  為組件樣式設(shè)置作用域。
  •  盡量使用指令縮寫。

vuex

State (opens new window)為單一狀態(tài)樹,在 state 中需要定義我們所需要管理的數(shù)組、對象、字符串等等,只有在這里定義了,在 vue 的組件中才能獲取你定義的這個對象的狀態(tài)。

  •  修改 state 中數(shù)據(jù)必須通過 mutations。
  •  每一個可能發(fā)生改變的 state 必須同步創(chuàng)建一條或多條用來改變它的 mutations。
  •  服務(wù)端獲取的數(shù)據(jù)存放在 state 中,作為原始數(shù)據(jù)保留,不可變動。

Getters (opens new window)有點類似 vue.js 的計算屬性,當(dāng)我們需要從 store 的 state 中派生出一些狀態(tài),那么我們就需要使用 getters,getters 會接收 state 作為第一個參數(shù),而且 getters 的返回值會根據(jù)它的依賴被緩存起來,只有 getters 中的依賴值(state 中的某個需要派生狀態(tài)的值)發(fā)生改變的時候才會被重新計算。

  •  通過 getters 處理你需要得到的數(shù)據(jù)格式,而不是通過修改 state 原始數(shù)據(jù)。
  •  組件內(nèi)不強制使用 mapGetters,因為你可能需要使用 getter 和 setter。
  •  改變 state 的唯一方法就是提交 mutations (opens new window)。
  •  組件內(nèi)使用 mapMutations 輔助函數(shù)將組件中的 methods 映射為 store.commit 調(diào)用。
  •  命名采用 大寫字母 + 下劃線 的規(guī)則。
  •  定義 CLEAR,以確保路由切換時可以初始化數(shù)據(jù)。

Actions

  •  頁面重的數(shù)據(jù)接口盡量在 actions (opens new window)中調(diào)用。
  •  服務(wù)端返回的數(shù)據(jù)盡量不作處理,保留原始數(shù)據(jù)。
  •  獲取到的數(shù)據(jù)必須通過調(diào)用 mutations 改變 state。

Modules

  •  通常情況下按照頁面劃分 modules (opens new window)。
  •  默認(rèn)內(nèi)置了 system 保證了腳手架的基礎(chǔ)功能。
  •  每個頁面模塊或頁面的子模塊添加屬性 namespaced: true。

14.完成詳細(xì)的使用文檔

不論是功能還是組件庫等等的工具,都需要完善的文檔提供查閱,即使是輪子的構(gòu)建者,也抵不住時間長了會忘記許多細(xì)節(jié)。

這里我使用 vuepress 構(gòu)建文檔,方便快捷。

參考【拯救懶癌文檔君 - VuePress + Travis CI + Github Pages 自動線上生成文檔】

15.Git 多人協(xié)作流程

公司使用內(nèi)部搭建的 GitLab 托管代碼

Root 倉庫

項目啟動時,由項目管理者搭建起最原始的倉庫,稱為 Root 倉庫(源倉庫)。

源倉庫的有個作用 :

  •  匯總參與該項目的各個開發(fā)者的代碼。
  •  存放趨于穩(wěn)定和可發(fā)布的代碼。
  •  向 Master 分支提交 Merge Requests 可以觸發(fā)測試環(huán)境構(gòu)建(CI/CD)。
  •  源倉庫是受保護的,開發(fā)者不可直接對其進行開發(fā)工作。

開發(fā)者倉庫

任何開發(fā)者都沒有權(quán)限對 Root 倉庫進行直接的操作,源倉庫建立以后,每個開發(fā)者需要做的事情就是把源倉庫的 Fork 一份,作為自己日常開發(fā)的倉庫。

  •  每個開發(fā)者所Fork的倉庫是完全獨立的,互不干擾。
  •  每個開發(fā)者提交到代碼到自己的倉庫中,開發(fā)工作完成以后,開發(fā)者可以向源倉庫發(fā)送 Pull Request ,本地倉庫先合并源倉庫,解決沖突。
  •  發(fā)起 Merge Request 請求管理員把自己的代碼合并到源倉庫中的 master 或 其他分支。

Git 流程

  •  前端項目會在 Root 倉庫下創(chuàng)建 dev 分支,用于代碼的拉取和合并,如果有多個不同的測試環(huán)境,按照測試環(huán)境創(chuàng)建分支。
  •  在本地的倉庫中創(chuàng)建你的 dev 分支和其他功能性的分支。
  •  開發(fā)過程中不允許直接在 master 分支上開發(fā),創(chuàng)建一個新的分支進行開發(fā),git checkout –b {branch_name}。
  •  規(guī)范且詳細(xì)的書寫 commit ,推薦使用 git-cz 工具進行提交。
  •  完成開發(fā)后將相應(yīng)的分支合并到自己倉庫的 master 分支。
  •  將 master 分支 push 到自己的遠(yuǎn)程倉庫(Fork倉庫)。
  •  向 Root 倉庫 dev 分支提交 Merge Requests。
  •  提醒前端負(fù)責(zé)人審查代碼、解決沖突或測試環(huán)境上線。
  •  解決沖突后 git pull upstream dev 拉取解決后的最新代碼。 

 

責(zé)任編輯:龐桂玉 來源: 前端大全
相關(guān)推薦

2020-12-10 16:20:30

Vue前端架構(gòu)

2020-02-07 11:50:24

代碼開發(fā)工具

2020-11-09 09:23:43

Vue組織架構(gòu)

2023-09-05 23:29:49

前端Vue

2020-04-14 14:30:43

Redis數(shù)據(jù)庫開源

2015-09-02 09:02:21

阿里無線前端架構(gòu)

2023-11-20 08:12:15

2021-04-27 10:02:40

股票數(shù)組代碼

2023-04-27 08:23:38

JavaScriptVue.jsMVVC

2025-02-13 08:04:00

2019-12-16 08:00:00

ReactAngularVue

2021-03-15 08:40:42

Vue組件函數(shù)

2018-06-14 14:59:26

Redis數(shù)據(jù)庫運維

2018-05-14 09:05:40

Redis數(shù)據(jù)庫String

2020-05-14 19:10:37

微服務(wù)架構(gòu)書籍

2019-02-25 08:05:34

架構(gòu) IT 技術(shù)系統(tǒng)

2022-11-28 17:21:24

2021-09-26 07:37:33

前端技術(shù)編程

2022-10-26 11:47:45

2018-11-08 09:56:03

AndroidJava程序員
點贊
收藏

51CTO技術(shù)棧公眾號