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




  • 項(xiàng)目運(yùn)行指南(#項(xiàng)目運(yùn)行指南)
  • 開發(fā)本地環(huán)境(#開發(fā)本地環(huán)境)
  • 開發(fā)相關(guān)插件/工具(#開發(fā)相關(guān)插件工具)
  • 開發(fā)規(guī)范(#開發(fā)規(guī)范)
    • vue(#vue)
      • 【數(shù)據(jù)流向】(#數(shù)據(jù)流向)
      • 【慎用全局注冊(cè)】(#慎用全局注冊(cè))
      • 【組件名稱】(#組件名稱)
      • 【組件中的 CSS】(#組件中的-css)
      • 【統(tǒng)一標(biāo)簽順序】(#統(tǒng)一標(biāo)簽順序)
      • 【其它注意事項(xiàng)】(#其它注意事項(xiàng))
      • 【 !!!其它則嚴(yán)格遵守 vue 官方風(fēng)格指南】(#a-target_blank-hrefhttpscnvuejsorgv2style-guide其它則嚴(yán)格遵守-vue-官方風(fēng)格指南a)
    • vue-router(#vue-router)
    • vuex(#vuex)
    • 模塊復(fù)用(#模塊復(fù)用)
    • 其它雜項(xiàng)(#其它雜項(xiàng))
    • 代碼注釋(#代碼注釋)
    • 工程目錄結(jié)構(gòu)(#工程目錄結(jié)構(gòu))
    • 前端部署(#前端部署)
    • 給 UI 的建議(#給-ui-的建議)



項(xiàng)目運(yùn)行指南

  • 安裝/更新依賴包:npm install
    • 說明:進(jìn)入正式開發(fā)前需要提交 package-lock.json,正式開發(fā)后慎用 npm update
  • 運(yùn)行:
    • 啟動(dòng)為 dev 環(huán)境:npm run servenpm start
    • 打包為 stage 環(huán)境:npm run build:stage
    • 打包為 prod 環(huán)境:npm run build
    • 檢查并修復(fù)源碼:npm run lint
    • 運(yùn)行單元測(cè)試:npm run test:unit
    • 啟用靜態(tài)資源服務(wù):npm run dist
    • 版本號(hào)操作:npm version major|minor|patch
      • 版本號(hào)格式說明:major(主版本號(hào)).minor(次版本號(hào)).patch(修訂號(hào))

開發(fā)本地環(huán)境

  • 在 VSCode 中給予獨(dú)立的工作區(qū),而非文件夾,以獲得最佳的智能感知
  • 新建 .env.development.local 來重寫部分環(huán)境變量,如:
    • 模擬數(shù)據(jù):VUE_APP_MOCK = true
    • 接口服務(wù):DEV_PROXY_TARGET_API = http://10.25.73.159:8081
    • ...

開發(fā)相關(guān)插件/工具

  • VSCode 相關(guān)插件
    • 必要插件
      • ESLint
      • Vetur
      • Prettier - Code formatter
      • path Autocomplete
    • 推薦插件
      • stylelint
      • vscode-element-helper (element-ui 專用)
      • Debugger for Chrome
      • GitLens -- Git supercharged
  • Chrome 相關(guān)插件
    • 必要插件
      • vue-devtools
    • 推薦插件
      • json-formatter
  • 其它工具
    • 推薦:PostmanPostwoman

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

vue

【數(shù)據(jù)流向】

  • 單個(gè)組件的數(shù)據(jù)流

    props、data/$store/$route、computed (由前面派生)
      ↓
    template/render
      ↓
    用戶交互事件、初始化的異步回調(diào)
      ↓
    data/$store/$route
    
  • 組件間的數(shù)據(jù)流

    • 父向子傳遞用 props
    • 子向父?jìng)鬟f用 vue 內(nèi)置的自定義事件,即 this.$emit
    • 父子雙向傳遞用 <a target="_blank" >v-model</a> 或 <a target="_blank" >.sync</a>
    • 跨越傳遞用 vuex(慎用 EventBus)
    • 緊密耦合的祖孫間傳遞也可以考慮用父組件作為中間運(yùn)輸層
    • 緊密耦合的兄弟間傳遞也可以考慮用父組件作為中轉(zhuǎn)運(yùn)輸層

【慎用全局注冊(cè)】

  • 組件、混入 ... 應(yīng)使用局部注冊(cè)

    局部注冊(cè)可保持清晰的依賴關(guān)系,并且 IDE 智能感知更為友好

【組件名稱】

  • 名稱大小寫

    <script>
      import MyComponent from '@/components/MyComponent.vue' // 文件名使用 PascalCase 命名法
      export default {
        name: 'ComponentName', // 必須有 name
        components: { MyComponent },
      }
    </script>
    
    <template>
      <div>
        <!-- 在 template 中一律使用 kebab-case 方式調(diào)用 -->
        <my-component />
        <el-input />
      </div>
    </template>
    
  • 使用前綴

    • 非業(yè)務(wù)通用組件使用 Base 前綴
    • <a href="#hash_Ex">擴(kuò)展/包裝第三方開源組件或內(nèi)部公共庫組件 (不建議使用高階組件)</a> 使用 Ex 前綴
    • 單例組件使用 The 前綴

【組件中的 CSS】

  • 使用 <a target="_blank" >CSS Modules</a>,基于如下考慮:

    • 不讓外部進(jìn)行樣式重寫,避免強(qiáng)耦合 (可通過 props 來處理內(nèi)部樣式的變化)
    • 放心使用簡(jiǎn)短且語義強(qiáng)的 class 名,無需多余的命名空間
  • 使用方式

    • 語法

      /* 默認(rèn)為局部 */
      .xxx {
      }
      
      /* 從局部轉(zhuǎn)到全局 */
      :global(.yyy) {
      }
      // or
      :global {
      }
      
      /* 從全局轉(zhuǎn)到局部 */
      :local(.zzz) {
      }
      // or
      :local {
      }
      
    • 單個(gè)組件專屬

      <style lang="less" module></style>
      
    • 多個(gè)組件共用 (*.module.less)

      import style from './style.module.less'
      

【統(tǒng)一標(biāo)簽順序】

  • script --> template --> style,并使用空行分隔

【其它注意事項(xiàng)】

  • 慎用 this.$refs、this.$parent、this.$root、provide/inject
    • this.$refs 一般用在第三方開源組件或內(nèi)部公共庫組件或非常穩(wěn)定的組件,以調(diào)用顯式聲明的方法
    • 在萬不得已的情況下需要暴露方法給外部調(diào)用時(shí)需要加 pub 前綴,如:this.$refs.pubFocus()
  • 盡量不要在 watch 中直接變更數(shù)據(jù),易造成死循環(huán)。數(shù)據(jù)變更應(yīng)該交給用戶交互事件或初始化的異步回調(diào)
  • 組件中的 data 及 vuex 中的 state 應(yīng)該可序列化,即不要存 undefined、function 等

【 <a target="_blank" >!!!其它則嚴(yán)格遵守 vue 官方風(fēng)格指南</a>】


vue-router

  • url 定義準(zhǔn)則

    • path 對(duì)應(yīng)視圖變化,query 對(duì)應(yīng)數(shù)據(jù)變化,hash 對(duì)應(yīng)滾動(dòng)條位置

    • path 使用 kebab-case 命名法,并且盡量與組件名相匹配(即一眼看到 path 就能迅速找到對(duì)應(yīng)的組件)

      路由 path:/project-list
        ↓
      路由組件:@/views/ProjectList.vue | @/views/ProjectList/index.vue
      
  • 命名路由的 name 值使用 kebab-case 命名法,并且嵌套時(shí)要帶命名空間(使用簡(jiǎn)寫)

    export const routes = {
      path: '/user-center',
      name: 'user-center',
      // ...
      children: [
        {
          path: 'base-info',
          name: 'uc-base-info', // 帶命名空間 uc-
          // ...
        },
      ],
    }
    
  • 當(dāng)組件依賴 $route 作為核心數(shù)據(jù)時(shí),要使用<a target="_blank" >路由組件傳參</a>,與 $route 解耦,也使得依賴更為顯式清晰

    export const routes = {
      path: '/project-detail',
      props: ({ query: { id } }) => ({ id }),
      // ...
    }
    
  • 視圖跳轉(zhuǎn)盡量使用聲明式(特別是 PC 端)

    <router-link :to="path | { name, ... }">使用聲明式</router-link>
    <a @click="$router.push(...)">使用命令式</a>
    

vuex

  • 需要由 vuex 管理的數(shù)據(jù)

    • 組件間共享的響應(yīng)式數(shù)據(jù)
    • 組件間需要跨越傳遞的數(shù)據(jù)
  • getter、mutation、action、module 使用駝峰命名法

  • module 應(yīng)避免嵌套,盡量扁平化

  • module 應(yīng)該啟用命名空間 namespaced: true


模塊復(fù)用

  • 避免重復(fù)造輪子,多使用成熟的現(xiàn)成工具/類庫/組件,如:lodash、qs、url-parse、date-fns/format 等

  • 模塊設(shè)計(jì)原則:

    • 高內(nèi)聚低耦合、可擴(kuò)展
    • 不要去改變模塊輸入的數(shù)據(jù) (引用類型),如:函數(shù)參數(shù)、組件 prop
    • 模塊的入?yún)榭蛇x Boolean 時(shí),默認(rèn)值應(yīng)設(shè)計(jì)為 false
      • 如:hasToolbar?=false 或 noToolbar?=false
  • 方法接口的設(shè)計(jì)

    // 參數(shù)類型與個(gè)數(shù)要保持穩(wěn)定
    // 建議參數(shù)不要超過3個(gè),且預(yù)留一個(gè) options 對(duì)象,以提高擴(kuò)展性
    // 方法盡量純凈 (純函數(shù)思想)
    export function myMethod1(a, options) {} // 當(dāng)必選參數(shù)只有一個(gè)時(shí)
    export function myMethod2(a, b, options) {} // 當(dāng)必選參數(shù)只有兩個(gè)時(shí)
    export function myMethod3(options) {} // 當(dāng)必選參數(shù)有兩個(gè)以上時(shí)
    export function myMethod4(options) {} // 當(dāng)所有參數(shù)都是可選時(shí)
    
    // 有時(shí)為了提高靈活性,參數(shù)類型可以是兩重,一重是期望值,另一重是返回期望值的函數(shù) (可帶參)
    export function myMethod5(a) {
      a = typeof a === 'function' ? a() : a
    }
    
  • <span id="hash_Ex">擴(kuò)展/包裝第三方開源組件或內(nèi)部公共庫組件 (不建議使用高階組件)</span>

    • 使用 extends 混入 (相關(guān)命名需要加 ex 前綴,防止覆蓋)
    • 使用<a target="_blank" >函數(shù)式組件</a>包裝

其它雜項(xiàng)

  • IDE 統(tǒng)一使用 VSCode,并統(tǒng)一使用相關(guān)插件及配置

  • js 變量聲明盡量使用 const

  • js 變量或?qū)ο髮傩允褂民劮迕?/p>

  • js 私有變量或?qū)ο笏接袑傩允褂?_ 前綴 (注意: <a target="_blank" >vue 組件屬性不要使用 _ 前綴</a>)

    // 表明該變量?jī)H在 createId 方法中使用 (與 createId 方法緊挨著)
    let _count = 0
    const createId = () => `${Date.now()}_${++_count}`
    
    // 適時(shí)使用立即執(zhí)行函數(shù)可以簡(jiǎn)潔作用域及保護(hù)私有變量
    const createId = (() => {
      let count = 0
      return () => `${Date.now()}_${++count}`
    })()
    
  • 導(dǎo)入模塊時(shí)不要省略后綴(js 除外),利于 IDE 感知

  • 導(dǎo)入當(dāng)前目錄以外的模塊時(shí),建議使用'@'別名

    // js
    import XxxXxx from '@/components/XxxXxx.vue'
    
    <!-- template -->
    <img src="@/assets/logo.png" />
    
    /* style */
    @import '~@/styles/vars.less';
    .xxx {
      background: url('~@/assets/logo.png');
    }
    
  • 嚴(yán)格遵守 ESLint 語法校驗(yàn),警告級(jí)別的也要處理 (暫時(shí)用不到的代碼可以先注釋掉)

  • css

    • 全局 class 使用 g- 前綴
    • CSS 選擇器應(yīng)避免深嵌套,盡量的扁平化
    • 關(guān)鍵選擇器 (最右邊) 避免使用通配符 *

代碼注釋

  • 文件頭部注釋

    • 腳本文件、樣式文件

      /**
       * 說明
       * @author 作者
       */
      
    • vue 文件

      <!-- 說明 -->
      <!-- @author 作者 -->
      
  • js 注釋 (結(jié)合 <a target="_blank" >JSDoc 注釋標(biāo)準(zhǔn)</a>,幫助 IDE 智能感知)

    • 注釋格式

      /**
       * 文件頭部、大的區(qū)塊、JSDoc
       */
      
      /* 一般的區(qū)塊 */
      
      // 小的區(qū)塊、行
      
    • <a target="_blank" >ES 2015 Modules</a>

      /**
       * 使用 param 表示函數(shù)形參
       * 使用 returns 表示函數(shù)返回值
       * @param {類型} data
       * @param {object} [options] 可選參數(shù)
       * @param {類型} options.xxx
       * @param {類型 =} options.yyy 可選屬性
       * @returns {類型}
       */
      export function myMethod(data, options) {}
      
      /**
       * 使用 type 進(jìn)行類型斷言
       * @type {import('vue-router').RouteConfig[]}
       */
      const routes = []
      
      /**
       * 使用 typedef 定義類型,方便多處使用(命名時(shí)需要首字母大寫)
       * @typedef {routes[0]} RouteConfig
       * @param {(meta: object, route: RouteConfig) => boolean} filterCallback
       * @returns {RouteConfig[]}
       */
      export const filterMapRoutes = function(filterCallback) {}
      
      /**
       * 類型參考:https://www.tslang.cn/docs/handbook/basic-types.html
       *
       * 基本
       * @type {boolean}
       * @type {number}
       * @type {string}
       * @type {1 | 2 | 3}
       * @type {'a' | 'b' | 'c'}
       *
       * 數(shù)組
       * @type {Array}
       * @type {string[]}
       *
       * 函數(shù)
       * @type {Function}
       * @type {(data) => void}
       * @type {(data: Array) => void | boolean}
       *
       * 對(duì)象
       * @type {object}
       *
       * 聯(lián)合
       * @type {number | string}
       * @type {boolean | (() => boolean)}
       *
       * 導(dǎo)入 ts 類型
       * @type {import('xxx').yyy}
       *
       * 從現(xiàn)有的 js 變量或 ts 類型進(jìn)行推導(dǎo)
       * @type {Parameters<fn>} 取函數(shù)形參的類型
       * @type {Parameters<fn>[0]} 取函數(shù)第一個(gè)形參的類型
       * @type {ReturnType<fn>} 取函數(shù)返回值的類型
       * @type {obj['xxx']} 取指定屬性值的類型(不能使用點(diǎn)語法)
       * ...
       */
      
    • <a target="_blank" >ES 2015 Classes</a>

    • 待完成或待優(yōu)化的地方

      /* TODO: 說明 */
      
  • css 注釋

    • 全局樣式需要寫注釋

      /* 說明 */
      .g-class1 {
      }
      
      /* 說明 */
      .g-class2 {
      }
      
  • vue template 注釋

    • 適當(dāng)使用注釋與空行

      <!-- 說明 -->
      <div>block1</div>
      
      <!-- 說明 -->
      <div>block2</div>
      

工程目錄結(jié)構(gòu)

|-- .env.development ------------ dev 環(huán)境變量
|-- .env.development.local ------ dev 本地環(huán)境變量 (被 git 忽略,需手動(dòng)新建,用來重寫部分環(huán)境變量)
|-- .env.production-stage ------- stage 環(huán)境變量
|-- .env.production ------------- prod 環(huán)境變量
|-- .env.test
|-- .vscode --------------------- 統(tǒng)一 VSCode 插件及配置
|-- static-server.js ------------ 靜態(tài)資源服務(wù) (node 運(yùn)行),通常用于預(yù)覽/檢查打包結(jié)果,或者臨時(shí)給其他人員啟用前端服務(wù)
|-- docs ------------------------ 開發(fā)文檔
|   |-- README.html ------------- 由 ../README.md 手動(dòng)生成 (使用 VSCode 插件 Markdown Preview Enhanced)
|   |-- xxx.md
|   |-- xxx.html
|-- public
|   |-- favicon.ico
|   |-- index.html
|   |-- libs -------------------- 不支持模塊化加載的第三方 ES5 類庫/模塊 (只能通過全局變量引用)
|-- src
    |-- main.js
    |-- App.vue
    |-- libs -------------------- 支持模塊化加載但是無法通過 npm 安裝的第三方 ES5 類庫/模塊
    |-- assets
    |-- styles
    |   |-- global.less
    |   |-- reset.less
    |   |-- vars.less ----------- less 全局變量/函數(shù) (webpack 自動(dòng)注入)
    |   |-- xxx.less
    |-- scripts
    |   |-- utils --------------- 通用方法
    |   |-- constants ----------- 常量 (多使用 Object.freeze)
    |   |-- xxx.js
    |   |-- http ---------------- axios 實(shí)例
    |       |-- index.js
    |       |-- http.js
    |       |-- createAxios.js
    |       |-- xxx.js
    |-- injects ----------------- vue 全局注冊(cè) (慎用)
    |   |-- index.js
    |   |-- $xxx.js
    |   |-- v-xxx.js
    |   |-- mixin_xxx.js
    |   |-- xxx.js
    |-- element-ui
    |   |-- index.js
    |   |-- rewrite ------------- 主題樣式復(fù)寫
    |       |-- index.less
    |       |-- xxx.less
    |-- vant
    |   |-- index.js
    |   |-- vars.less ----------- 內(nèi)置變量復(fù)寫
    |   |-- rewrite ------------- 主題樣式復(fù)寫
    |       |-- index.less
    |       |-- xxx.less
    |-- router
    |   |-- index.js
    |   |-- routes.js
    |   |-- registerInterceptor.js
    |-- store
    |   |-- index.js
    |   |-- root.js
    |   |-- xxx.js
    |-- api
    |   |-- xxx.js
    |   |-- mock ---------------- 模擬數(shù)據(jù)
    |       |-- index.js
    |       |-- createMock.js
    |       |-- xxx.js
    |-- components
    |   |-- BaseXxx.vue --------- 非業(yè)務(wù)通用組件
    |   |-- TheXxx.vue ---------- 單例組件
    |   |-- ExXxx.vue ----------- 擴(kuò)展/包裝第三方開源組件或內(nèi)部公共庫組件
    |   |-- XxxXxx.vue
    |   |-- ComponentExamples --- 非單例公共組件需要在這里寫示例
    |   |   |-- index.vue
    |   |   |-- XxxXxx.vue
    |   |-- SvgIcon ------------- svg-sprite 圖標(biāo)組件
    |   |   |-- index.vue
    |   |   |-- icons
    |   |-- directives ---------- 可復(fù)用的自定義指令(局部注冊(cè))
    |   |   |-- xxx.js
    |   |-- mixins -------------- 可復(fù)用的混入(局部注冊(cè))
    |       |-- xxx.js
    |-- views
        |-- Xxx.vue
        |-- Xxx ----------------- 除了 api 和 vuex,其它的專屬模塊要內(nèi)聚在同一目錄下
            |-- index.vue
            |-- Xxx.vue --------- 相關(guān)頁面/子頁面/子路由
            |-- xxx.js
            |-- xxx.module.less
            |-- components ------ 存放私有組件

前端部署

  • 跨域處理

    • 使用代理或 <a target="_blank" >CORS</a>
  • history 模式<a target="_blank" >路由處理</a>

    • 如果 url 匹配的不是靜態(tài)資源 (不帶后綴的),則返回 /index.html 頁面
  • 客戶端緩存處理 (配置響應(yīng)頭)

    • 靜態(tài)資源

      • 不緩存 /index.html

        Cache-Control: no-store
        
      • 強(qiáng)緩存 /static-hash/**/*

        Cache-Control: public,max-age=31536000
        
      • <a target="_blank" >協(xié)商緩存</a> (默認(rèn))

        Cache-Control: no-cache
        Etag: xxx
        Last-Modified: xxx
        
    • XHR (解決 IE 緩存問題)

      Cache-Control: no-cache
      
  • gzip 壓縮

    • 靜態(tài)資源:?jiǎn)⒂?gzip 壓縮 (除了像素型圖片)

    • XHR:發(fā)給客戶端的響應(yīng)數(shù)據(jù)超過指定閥值時(shí)應(yīng)啟用 gzip 壓縮


給 UI 的建議

  • 對(duì)于中后臺(tái)項(xiàng)目,在畫 UI 界面時(shí),建議參考前端已選型的開源組件庫,并推薦使用開源組件庫提供的制圖元件/模板,如:<a target="_blank" >element-ui</a>
  • 對(duì)于 H5 項(xiàng)目,如:<a target="_blank" >vant</a>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文檔為前端vue 開發(fā)規(guī)范 ·規(guī)范目的 ·命名規(guī)范 ·結(jié)構(gòu)化規(guī)范 ·注釋規(guī)范 ·編碼規(guī)范 ·CSS 規(guī)范 規(guī)范目...
    近朱者熾閱讀 1,024評(píng)論 0 3
  • 由于所在公司前端代碼較不規(guī)范,近期應(yīng)公司領(lǐng)導(dǎo)要求,整理出了一份公司內(nèi)部的前端開發(fā)規(guī)范標(biāo)準(zhǔn)。這里參考了一些文章,并對(duì)...
    追尋1989閱讀 1,240評(píng)論 0 3
  • 前端通用規(guī)范文檔,猛戳這里 一.react一般規(guī)范 1.基本結(jié)構(gòu)(使用mobx) ├── build ...
    lemonzoey閱讀 3,442評(píng)論 2 4
  • 為了前端代碼形成統(tǒng)一的風(fēng)格,制定該代碼規(guī)范(該規(guī)范部分參照VUE官網(wǎng)介紹的風(fēng)格指南以及常用的規(guī)范) 1.文件夾命名...
    朋_朋閱讀 682評(píng)論 0 1
  • Vue 開發(fā)規(guī)范目錄及說明 規(guī)范目的 命名規(guī)范 結(jié)構(gòu)化規(guī)范注 釋規(guī)范 編碼規(guī)范 CSS 規(guī)范 規(guī)范目的 為提高團(tuán)隊(duì)...
    凌枝閱讀 5,322評(píng)論 1 49

友情鏈接更多精彩內(nèi)容