<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Vue開發(fā)規(guī)范經(jīng)驗總結(jié)(部分)

          共 7409字,需瀏覽 15分鐘

           ·

          2021-10-19 19:50

          規(guī)范與每個團隊和個人都是息息相關的,因為其影響的不只是只是代碼的維護和理解成本,嚴重的時候是會影響成員開發(fā)的心情 一個團隊的編碼規(guī)范、git規(guī)范等,并沒有絕對的最優(yōu)解,心里要清楚明白沒有銀彈,規(guī)范是為了讓團隊統(tǒng)一,提高代碼閱讀性、降低代碼維護成本等,本文是記錄一些在項目code review中常見的規(guī)范,僅供參考

          JS部分

          和渲染無關的數(shù)據(jù)

          vue中data的數(shù)據(jù)默認便會進行雙向數(shù)據(jù)綁定,若是將大量的和渲染無關的數(shù)據(jù)直接放置在data中,將會浪費雙向數(shù)據(jù)綁定時所消耗的性能,將這些和渲染無關的數(shù)據(jù)進行抽離并配合Object.freeze進行處理。

          tablecolumns數(shù)據(jù)可以單獨提取一個外部js文件作為配置文件,也可以在當前.vue文件中定義一個常量定義columns數(shù)據(jù),因為無論如何都是固定且不會修改的數(shù)據(jù),應該使用Object.freeze進行包裹,既可以提高性能還可以將固定的數(shù)據(jù)抽離,一些下拉框前端固定的數(shù)據(jù)也建議此操作

          const?columnList?=?Object.freeze([
          ??{?title:?'姓名',?key:?'name',?align:?'center'?},
          ??{?title:?'性別',?key:?'gender',?align:?'center'?}
          ])

          需要注意的是 Object.freeze() 凍結(jié)的是值,這時仍然可以將變量的引用替換掉,還有確保數(shù)據(jù)不會變才可以使用這個語法,如果要對數(shù)據(jù)進行修改和交互,就不適合使用凍結(jié)了。

          Modal框的控制

          一個頁面種通常會存在很多個不同功能的彈框,若是每一個彈框都設置一個對應的變量來控制其顯示,則會導致變量數(shù)量比較冗余和命名困難,可以使用一個變量來控制同一頁面中的所有Modal彈框的展示

          比如某個頁面中存在三個Modal彈框

          //?bad
          //?每一個數(shù)據(jù)控制對應的Modal展示與隱藏
          new?Vue({
          ????data()?{
          ????????return?{
          ????????????modal1:?false,
          ????????????modal2:?false,
          ????????????modal3:?false,
          ????????}
          ????}
          })

          //?good
          //?當modalType為對應的值時?展示其對應的彈框
          new?Vue({
          ????data()?{
          ????????return?{
          ????????????modalType:?''?//?modalType值為?modal1,modal2,modal3
          ????????}
          ????}
          })

          debounce使用

          例如遠程搜索時需要通過接口動態(tài)的獲取數(shù)據(jù),若是每次用戶輸入都接口請求,是浪費帶寬和性能的

          當一個按鈕多次點擊時會導致多次觸發(fā)事件,可以結(jié)合場景是否立即執(zhí)行immediate

          <Select?:remote-method="remoteMethod">
          ????<Option?v-for="item?in?temoteList"?:value="item.value"?:key="item.id">{{item.label}}Option>
          Select>
          import?{debounce}?from?'lodash'

          methods:{
          ??? remoteMethod:debounce(function?(query)?{
          ????????//?to?do?...
          ???????//?this?的指向沒有問題
          ????},?200),
          }

          圖片

          功能的開發(fā)過程中,圖片的處理往往是比較容易被忽略的環(huán)節(jié),也會在一定程度影響開發(fā)的效率和頁面的性能

          • 圖片壓縮問題,除非特別要求圖片必須高質(zhì)量的顯示,否則都應該進行對應的壓縮處理

          • 不同業(yè)務場景進行圖片格式的選型

            • JPG 適用于呈現(xiàn)色彩豐富的圖片,JPG 圖片經(jīng)常作為大的背景圖、輪播圖或 Banner 圖出現(xiàn)等
            • Logo、顏色簡單且對比強烈的圖片或背景、需要透明度等
            • 將常用且變動頻率很低的小圖片進行合并成雪碧圖,對于變動比較頻繁和小于6KB的圖片進行base64
            • 處理根據(jù)項目圖片數(shù)量和項目的用戶機型分布等,考慮采取webp進行圖片的處理

          路由組件傳參

          在組件中使用 $route 會使之與其對應路由形成高度耦合,從而使組件只能在某些特定的 URL 上使用,限制了其靈活性。

          使用 props 將組件和路由解耦:

          • 取代與 $route 的耦合
          const?User?=?{
          ??template:?'
          User?{{?$route.params.id?}}
          '

          }
          const?router?=?new?VueRouter({
          ??routes:?[
          ????{?path:?'/user/:id',?component:?User?}
          ??]
          })
          • 通過 props 解耦

          這樣你便可以在任何地方使用該組件,使得該組件更易于重用和測試。

          const?User?=?{
          ??props:?['id'],
          ??template:?'
          User?{{?id?}}
          '

          }
          const?router?=?new?VueRouter({
          ??routes:?[
          ????{?path:?'/user/:id',?component:?User,?props:?true?},

          ????//?對于包含命名視圖的路由,你必須分別為每個命名視圖添加?`props`?選項:
          ????{
          ??????path:?'/user/:id',
          ??????components:?{?default:?User,?sidebar:?Sidebar?},
          ??????props:?{?default:?true,?sidebar:?false?}
          ????}
          ??]
          })

          Vue生命周期

          在父子組件中,掌握父子組件對應的生命周期鉤子加載順序可以讓開發(fā)者在更合適的時候做適合的事情,這個問題在最近的面試中起碼被問到了三次,還是需要注意的

          父組件

          <template>
          ??<div>
          ????<h3>homeh3>
          ????<list?@hook:mounted="listMounted"?/>
          ??div>
          template>
          <script>
          import?List?from?'./list'
          export?default?{
          name:?"home",
          components:?{
          List
          },
          methods:?{
          listMounted(){
          console.log('------------?listMounted');
          }
          },
          beforeCreate()?{
          console.log("home?beforeCreate");
          },
          created()?{
          console.log("home?created");
          },
          beforeMount()?{
          console.log("home?beforeMount");
          },
          mounted()?{
          console.log("home?mounted");
          },
          beforeDestroy()?{
          console.log("home?beforeDestroy");
          },
          destroyed()?{
          console.log("home?destroyed");
          }
          }
          script>

          子組件

          <template>
          ??<div>
          ????list
          ??div>
          template>
          <script>
          export?default?{
          naem:?"list",
          beforeCreate()?{
          console.log("list?beforeCreate");
          },
          created()?{
          console.log("list?created");
          },
          beforeMount()?{
          console.log("list?beforeMount");
          },
          mounted()?{
          console.log("list?mounted");
          },
          beforeDestroy()?{
          console.log("list?beforeDestroy");
          },
          destroyed()?{
          console.log("list?destroyed");
          }
          }
          script>

          加載時父子組件的加載順序

          home?beforeCreate?-->?home?created?-->?home?beforeMount?-->?list?created?-->?list?beforeMount?-->?list?mounted

          銷毀時父子組件的銷毀順序

          home?beforeDestroy?-->?list?beforeDestroy?-->?list?destroyed?-->?home?destroyed

          實際開發(fā)過程中會遇到當子組件某個生命周期完成之后通知父組件,然后在父組件做對應的處理

          emit up

          //?子組件在對應的鉤子中發(fā)布事件
          created(){
          ??this.$emit('done')
          }
          //?父組件訂閱其方發(fā)
          "childDone">

          hook

          通過@hook監(jiān)聽子組件的生命周期

          "listMounted"?/>

          Select優(yōu)化

          下拉框遍歷時,需要注意options標簽保持同一行,若是存在換行,會導致選中時的值存在多余的空白


          <Select?:remote-method="remoteMethod">
          ????<Option?v-for="item?in?temoteList"?:value="item.value"?:key="item.id">
          ????????{{item.label}}
          ????Option>
          Select>

          需要將Options和下拉框的值保持在同一行。


          <Select?:remote-method="remoteMethod">
          ????<Option?v-for="item?in?temoteList"?:value="item.value"?:key="item.id">{{item.label}}Option>
          Select>

          data數(shù)據(jù)層級

          data數(shù)據(jù)具有數(shù)據(jù)層級結(jié)構(gòu),切勿過度扁平化或者嵌套層級過深,若是過度扁平化會導致數(shù)據(jù)命名空間沖突,參數(shù)傳遞和處理,若是層級嵌套過深也會導致vue數(shù)據(jù)劫持的時候遞歸層級過深,若是嵌套層級喪心病狂那種的,小心遞歸爆棧的問題。而且層級過深會導致數(shù)據(jù)操作和處理不便,獲取數(shù)據(jù)做容錯處理也比較繁瑣。一般層級保持2-3層最好。

          若是只有一層數(shù)據(jù),過于扁平

          {
          ????name:?'',
          ????age:?'',
          ????gender:?''
          }

          導致處理不方便

          //?作為接口參數(shù)傳遞
          ajax({
          ?this.name,?this.age,?this.gender
          })

          //?接口獲取數(shù)據(jù),批量處理
          ajax().then(res?=>?{
          ?const?{name,?age,?gender}?=?res.data
          ????this.name?=?name
          ????this.age?=?age
          ????this.gender?=?gender
          })

          適當?shù)膶蛹壗Y(jié)構(gòu)不僅增加代碼的維護和閱讀性,還可以增加操作和處理的便捷性

          {
          ????person:?{?//?個人信息
          ????????name:?'',
          ????????age:?'',
          ????????gender:?''
          ????}
          }

          可以針對person進行操作

          //?作為接口參數(shù)傳遞
          ajax(this.person)

          //?接口獲取數(shù)據(jù),批量處理
          ajax().then(res?=>?{
          ?const?{name,?age,?gender}?=?res.data
          ????this.$set(this,?'person',?{name,?age,?gender})
          })

          策略模式

          策略模式的使用,避免過多的if else判斷,也可以替代簡單邏輯的switch。

          const?formatDemandItemType?=?(value)?=>?{
          ????switch?(value)?{
          ????????case?1:
          ????????????return?'基礎'
          ????????case?2:
          ????????????return?'高級'
          ????????case?3:
          ????????????return?'VIP'
          ????}
          }

          //?策略模式
          const?formatDemandItemType2?=?(value)?=>?{
          ????const?obj?=?{
          ????????1:?'基礎',
          ????????2:?'高級',
          ????????3:?'VIP',
          ????}
          ????
          ????return?obj[value]
          }

          解構(gòu)

          解構(gòu)賦值以及默認值,當解構(gòu)的數(shù)量小于多少時適合直接解構(gòu)并賦值默認值,數(shù)據(jù)是否進行相關的聚合處理

          const?{
          ??naem?=?'',
          ??age?=?10,
          ??gender?=?'man'
          }?=?res.data

          //?bad
          this.name?=?name
          this.age?=?age
          this.gender?=?gender

          //?good
          this.person?=?{
          ??naem,
          ??age,
          ??gender
          }

          職責單一

          任何時候盡量是的一個函數(shù)就做一件事情,而不是將各種邏輯全部耦合在一起,提高單個函數(shù)的復用性和可讀性

          每個頁面都會在加載完成時進行數(shù)據(jù)的請求并展示到頁面

          created()?{
          ??this.init();
          },
          methods:?{
          ??//?將全部的請求行為聚合在init函數(shù)中
          ??//?將每個請求單獨拆分
          ??init()?{
          ????this.getList1()
          ????this.getList2()
          ??},
          ??getList1()?{
          ????//?to?do?...
          ??},
          ??getList2()?{
          ????//?to?do?...
          ??}
          }

          v-bind

          在日常的開發(fā)過程中, 提取和封裝組件是一件很常規(guī)的操作,但是當組件需要的參數(shù)非常多時,會導致傳遞一堆的prop,不僅書寫上面比較繁瑣,對代碼的維護和閱讀不是一件有利的事情

          例如組件test-demo需要一堆props傳遞

          使用時


          test-demo中需要接收處理

          {
          ?props:?['data1',?'data2',?'data3',?...]
          }
          //?or
          props:?{
          ??modalVisible:?{
          ????//?控制展示modal
          ????type:?Boolean,
          ????default:?false
          ??},
          ??data1:?{
          ????type:?String,
          ????default:?'1'
          ??},
          ??data2:?{
          ????type:?String,
          ????default:?'2'
          ??},
          ??data3:?{
          ????type:?String,
          ????default:?'3'
          ??}
          }

          建議將子組件需要的數(shù)據(jù)收集起來,集中在一個對象中,使用v-bind傳遞將這個對象傳遞,子組件的使用和普通的props一樣

          <template>
          ?<test-demo?
          ????v-bind="obj"
          ??/>

          template>
          <script>
          export?default?{
          data?()?{
          return?{
          obj:?{?//?將需要傳遞給子組件的數(shù)據(jù)收集
          data1:?'1',
          data2:?'2',
          data3:?'3'
          }
          }
          }
          }
          script>

          HTML部分

          html書寫

          編寫template模板時,屬性過多時,是否換行

          <template>
          ??
          ??<VueButton?class="icon-button?go-up"?icon-left="keyboard_arrow_up"?v-tooltip="$t('org.vue.components.folder-explorer.toolbar.tooltips.parent-folder')"?@click="openParentFolder"?/>


          <VueButton
          class="icon-button?go-up"
          icon-left="keyboard_arrow_up"
          v-tooltip="$t('org.vue.components.folder-explorer.toolbar.tooltips.parent-folder')"
          @click="openParentFolder"
          />

          template>

          實體使用

          html中展示一些如<,>,&等字符時,使用字符實體代替


          <div>
          ??>?1?&?12
          div>
          ??

          <div>
          ??>?1?&?<?12
          div>

          CSS部分

          樣式穿透

          在開發(fā)中修改第三方組件樣式是很常見,但由于 scoped 屬性的樣式隔離,可能需要去除 scoped 或是另起一個 style 。這些做法都會帶來副作用(組件樣式污染、不夠優(yōu)雅),樣式穿透在css預處理器中使用才生效。

          • less使用 /deep/
          <style?scoped?lang="less">
          .content?/deep/?.el-button?{
          ??height:?60px;
          }
          style>

          • scss使用 ::v-deep
          <style?scoped?lang="scss">
          .content?::v-deep?.el-button?{
          ??height:?60px;
          }
          style>
          • stylus使用 >>>
          <style?scoped?ang="stylus">
          外層?>>>?.custon-components{
          ??height:?60px;
          }
          style>

          空格

          適當?shù)目崭窨梢蕴嵘a的閱讀體驗,顯得更為優(yōu)雅和美觀

          選擇器后、屬性值

          .custom-style?{?//?選擇器和{?之間空格
          ??margin:?0;?//?屬性值前
          ??transform:?scale(1.5,?2.2);?//?逗號之后增加空格
          }

          換行

          和html類型,當某行的屬性很多,適當?shù)膿Q行可以提高閱讀和美觀

          .custom-style{
          ??//?可以在一次聲明中定義一個或多個屬性
          ??background:?background-clip
          ????background-color
          ????background-image
          ????background-origin
          ????background-position
          ????background-repeat
          ????background-size;
          }

          當一個規(guī)則包含多個選擇器時,每個選擇器聲明必須獨占一行,過長導致需要橫向滾動閱讀剩余的內(nèi)容,應該盡量使得閱讀順序縱向化

          .custom?.header?.title
          .other?.header?.title?{
          ??color:?#f0f;
          }

          嵌套層級

          瀏覽器在解析css時,是按照從右到左遞歸匹配的,過深的層級嵌套不僅影響性能,而且還會導致樣式閱讀性和代碼維護性降低,一般層架控制在5層之內(nèi)

          雙引號

          屬性選擇器中的值必須用雙引號包圍,不允許使用單引號,也不允許不使用引號,html的屬性值也是推薦使用雙引號,js中使用單引號

          .custom-style{
          ?font-family:?"PingFang?SC",?"STHeitiSC-Light";??
          }

          屬性順序

          同一 規(guī)則下的屬性在書寫時,應按功能進行分組。并以 Formatting Model(布局方式、位置) > Box Model(尺寸) > Typographic(文本相關) > Visual(視覺效果) 的順序書寫,以提高代碼的可讀性。

          解釋:

          • Formatting Model 相關屬性包括:position / top / right / bottom / left / float / display / overflow 等
          • Box Model 相關屬性包括:border / margin / padding / width / height 等
          • Typographic 相關屬性包括:font / line-height / text-align / word-wrap 等
          • Visual 相關屬性包括:background / color / transition / list-style 等

          另外,為增加可讀性,如果包含 content 屬性,應放在屬性的最前面。

          參考

          • 三年 Vue 前端開發(fā)的血與淚總結(jié)

          https://gitbook.cn/books/5dd7de04c023a6766a83cfc4/index.html#-1

          • 編碼規(guī)范作用

          https://www.zhihu.com/search?type=content&q=%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83%E4%BD%9C%E7%94%A8


          關于作者

          作者:Vam的金豆之路。曾獲得2019年CSDN年度博客之星稱號,CSDN博客、掘金技術社區(qū)訪問量累計已超過二百萬。公眾號:前端歷劫之路專注于前端技術分享與學習,謝謝你關注我。學習前端技術就如同經(jīng)歷一場場劫難,只有堅持、努力才會成為自己心中的大神!共勉~


          瀏覽 21
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲欧美日韩一区二区 | 黄色片网站在线免费观看 | 蜜臀久久久 | 免费在线观看黄色视频网站 | 日日夜夜青青草 |