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

讓Vue項目更絲滑的幾個小技巧

開發(fā) 前端
今天小編就整理了幾個在項目中會用到的一些實戰(zhàn)技巧點,希望可以幫助到正在努力賺錢的你。

[[334646]]

陣陣鍵盤聲,隱隱測試言。產(chǎn)品不穩(wěn)定,今夜無人還。

在開發(fā)Vue的過程中,我們經(jīng)常會遇到一些這樣那樣的問題,然后要卡好半天,等問題解決了才發(fā)現(xiàn)原來一些細節(jié)知識點還是沒有掌握好。今天小編就整理了幾個在項目中會用到的一些實戰(zhàn)技巧點,希望可以幫助到正在努力賺錢的你。江湖規(guī)矩,先贊后看,艷遇不斷。

數(shù)據(jù)不響應,可能是用法有問題

前幾天有朋友給我發(fā)了一段代碼,然后說Vue有bug,他明明寫的沒問題,為啥數(shù)據(jù)就不響應呢,一定是Vue的bug?我感覺他比尤雨溪要牛逼,高攀不起,就沒有理他了。但是確實有時候我們在開發(fā)時候會遇到數(shù)據(jù)不響應的情況,那怎么辦呢?比如下面這段代碼: 

  1. <template>  
  2.   <div>  
  3.     <div>  
  4.       <span>用戶名: {{ userInfo.name }}</span>  
  5.       <span>用戶性別: {{ userInfo.sex }}</span>  
  6.       <span v-if="userInfo.officialAccount">  
  7.         公眾號: {{ userInfo.officialAccount }}  
  8.       </span>  
  9.     </div>  
  10.     <button @click="handleAddOfficialAccount">添加公眾號</button>  
  11.   </div>  
  12. </template>  
  13. <script>  
  14. export default {  
  15.   data() {  
  16.     return {  
  17.       userInfo: {  
  18.         name: '子君',  
  19.         sex: '男'  
  20.       }  
  21.     }  
  22.   },  
  23.   methods: {  
  24.     // 在這里添加用戶的公眾號  
  25.     handleAddOfficialAccount() {  
  26.       this.userInfo.officialAccount = '前端有的玩'  
  27.     }  
  28.   }  
  29.  
  30. </script> 

在上面的代碼中,我們希望給用戶信息里面添加公眾號屬性,但是通過this.userInfo.officialAccount = '前端有的玩' 添加之后,并沒有生效,這是為什么呢?

這是因為在Vue內(nèi)部,數(shù)據(jù)響應是通過使用Object.definePrototype監(jiān)聽對象的每一個鍵的getter,setter方法來實現(xiàn)的,但通過這種方法只能監(jiān)聽到已有屬性,新增的屬性是無法監(jiān)聽到的,但我就是想監(jiān)聽,小編你說咋辦吧。下面小編提供了四種方式,如果有更多方式,歡迎下方評論區(qū)告訴我。

1. 將本來要新增的屬性提前在data中定義好

比如上面的公眾號,我可以提前在userInfo里面定義好,這樣就不是新增屬性了,就像下面這樣 

  1. data() {  
  2.     return {  
  3.       userInfo: {  
  4.         name: '子君',  
  5.         sex: '男',  
  6.         // 我先提前定義好  
  7.         officialAccount: ''  
  8.       }  
  9.     }  
  10.   }  

2. 直接替換掉userInfo

雖然無法給userInfo里面添加新的屬性,但是因為userInfo已經(jīng)定義好了,所以我直接修改userInfo的值不就可以了么,所以也可以像下面這樣寫 

  1. this.userInfo = {  
  2.   // 將原來的userInfo 通過擴展運算法復制到新的對象里面  
  3.   ...this.userInfo,  
  4.   // 添加新屬性  
  5.   officialAccount: '前端有的玩' 
  6.  
  7.  

3. 使用Vue.set

其實上面兩種方法都有點取巧的嫌疑,其實對于新增屬性,Vue官方專門提供了一個新的方法Vue.set用來解決新增屬性無法觸發(fā)數(shù)據(jù)響應。

Vue.set 方法定義 

  1. /**  
  2. * target 要修改的對象  
  3. * prpertyName 要添加的屬性名稱  
  4. * value 要添加的屬性值  
  5. */  
  6. Vue.set( target, propertyName, value )  

上面的代碼使用Vue.set可以修改為 

  1. import Vue from 'vue'  
  2. // 在這里添加用戶的公眾號  
  3. handleAddOfficialAccount() {  
  4.   Vue.set(this.userInfo,'officialAccount', '前端有的玩')  
  5.  

但是每次要用到set方法的時候,還要把Vue引入進來,好麻煩,所以為了簡便起見,Vue又將set方法掛載到了Vue的原型鏈上了,即Vue.prototype.$set = Vue.set,所以在Vue組件內(nèi)部可以直接使用this.$set代替Vue.set 

  1. this.$set(this.userInfo,'officialAccount', '前端有的玩') 

小編發(fā)現(xiàn)有許多同學不知道什么時候應該用Vue.set,其實只有當你要賦值的屬性還沒有定義的時候需要使用Vue,set,其他時候一般不會需要使用。

4. 使用$forceUpdate

我覺得$forceUpdate的存在,讓許多前端開發(fā)者不會再去注意數(shù)據(jù)雙向綁定的原理,因為不論什么時候,反正我修改了data之后,調(diào)用一下$forceUpdate就會讓Vue組件重新渲染,bug是不會存在的。但是實際上這個方法并不建議使用,因為它會引起許多不必要的性能消耗。

針對數(shù)組的特定方式

其實不僅僅是對象,數(shù)組也存在數(shù)據(jù)修改之后不響應的情況,比如下面這段代碼 

  1. <template>  
  2.   <div>  
  3.     <ul>  
  4.       <li v-for="item in list" :key="item">  
  5.         {{ item }}  
  6.       </li>  
  7.     </ul>  
  8.     <button @click="handleChangeName">修改名稱</button>  
  9.   </div>  
  10. </template>  
  11. <script>  
  12. export default {  
  13.   data() {  
  14.     return {  
  15.       list: ['張三', '李四']  
  16.     }  
  17.   },  
  18.   methods: {  
  19.     // 修改用戶名稱  
  20.     handleChangeName() {  
  21.       this.list[0] = '王五'  
  22.     }  
  23.   }  
  24.  
  25. </script>  

上面的代碼希望將張三的名字修改為王五,實際上這個修改并不能生效,這是因為Vue不能檢測到以下變動的數(shù)組:

  1. 當你利用索引直接設(shè)置一個項時,例如: this.list[index] = newValue
  2. 修改數(shù)組的length屬性,例如: this.list.length = 0

所以在上例中通過this.list[0] = '王五' 是無法觸發(fā)數(shù)據(jù)響應的,那應該怎么辦呢?像上面提到的Vue.set$forceUpdate都可以解決這個問題,比如Vue.set可以這樣寫 

  1. Vue.set(this.list,0,'王五')  
  2. 復制代碼  

除了那些方法之外,Vue還針對數(shù)組提供了變異方法

在操作數(shù)組的時候,我們一般會用到數(shù)據(jù)提供的許多方法,比如push,pop,splice等等,在Vue中調(diào)用數(shù)組上面提供的這些方法修改數(shù)組的值是可以觸發(fā)數(shù)據(jù)響應的,比如上面的代碼改為以下代碼即可觸發(fā)數(shù)據(jù)響應 

  1. this.list.splice(0,1,'王五') 

實際上,如果Vue僅僅依賴gettersetter,是無法做到在數(shù)組調(diào)用push,pop等方法時候觸發(fā)數(shù)據(jù)響應的,因此Vue實際上是通過劫持這些方法,對這些方法進行包裝變異來實現(xiàn)的。

Vue對數(shù)組的以下方法進行的包裝變異:

  • push
  • pop
  • shift
  • unshift
  • splice
  • sort
  • reverse

所以在操作數(shù)組的時候,調(diào)用上面這些方法是可以保證數(shù)據(jù)可以正常響應,下面是Vue源碼中包裝數(shù)組方法的代碼: 

  1. var original = arrayProto[method];  
  2.   def(arrayMethods, method, function mutator () {  
  3.     // 將 arguments 轉(zhuǎn)換為數(shù)組  
  4.     var args = [], len = arguments.length;  
  5.     while ( len-- ) args[ len ] = arguments[ len ];  
  6.     var result = original.apply(this, args);  
  7.     // 這兒的用法同dependArray(value),就是為了取得dep  
  8.     var ob = this.__ob__;  
  9.     var inserted;  
  10.     switch (method) {  
  11.       case 'push':  
  12.       case 'unshift':  
  13.         inserted = args 
  14.         break  
  15.       case 'splice':  
  16.         inserted = args.slice(2);  
  17.         break  
  18.     }  
  19.     // 如果有新的數(shù)據(jù)插入,則插入的數(shù)據(jù)也要進行一個響應式  
  20.     if (inserted) { ob.observeArray(inserted); }  
  21.    // 通知依賴進行更新  
  22.     ob.dep.notify();  
  23.     return result  
  24.   });  

文本格式化,filter更簡單

使用filter 簡化邏輯

我想把時間戳顯示成yyyy-MM-DD HH:mm:ss的格式怎么辦?是需要在代碼中先將日期格式化之后,再渲染到模板嗎?就像下面這樣 

  1. <template>  
  2.   <div>  
  3.     {{ dateStr }}  
  4.     <ul>  
  5.       <li v-for="(item, index) in getList" :key="index">  
  6.         {{ item.date }}  
  7.       </li>  
  8.     </ul>  
  9.   </div>  
  10. </template>  
  11. <script> 
  12.  import { format } from '@/utils/date'  
  13. export default {  
  14.   data() {  
  15.     return {  
  16.       date: Date.now(),  
  17.       list: [  
  18.         {  
  19.           date: Date.now()  
  20.         }  
  21.       ]  
  22.     }  
  23.   },  
  24.   computed: {  
  25.     dateStr() {  
  26.       return format(this.date, 'yyyy-MM-DD HH:mm:ss')  
  27.     },  
  28.     getList() {  
  29.       return this.list.map(item => {  
  30.         return {  
  31.           ...item,  
  32.           date: format(item.date, 'yyyy-MM-DD HH:mm:ss') 
  33.          }  
  34.       })  
  35.     }  
  36.   }  
  37.  
  38. </script>  

像上面的寫法,針對每一個日期字段都需要調(diào)用format,然后通過計算屬性進行轉(zhuǎn)換?這時候可以考慮使用Vue提供的filter去簡化 

  1. <template>  
  2.   <div>  
  3.     <!--使用過濾器-->  
  4.     {{ dateStr | formatDate }}  
  5.     <ul>  
  6.       <li v-for="(item, index) in list" :key="index">  
  7.         <!--在v-for中使用過濾器-->  
  8.         {{ item.date | formatDate }}  
  9.       </li>  
  10.     </ul>  
  11.   </div>  
  12. </template>  
  13. <script>  
  14. import { format } from '@/utils/date'  
  15. export default {  
  16.   filters: {  
  17.     formatDate(value) {  
  18.       return format(value, 'yyyy-MM-DD HH:mm:ss')  
  19.     }  
  20.   },  
  21.   data() {  
  22.     return {  
  23.       date: Date.now(),  
  24.       list: [  
  25.         {  
  26.           date: Date.now()  
  27.         }  
  28.       ]  
  29.     }  
  30.   }  
  31.  
  32. </script>  

通過上面的修改是不是就簡單多了

注冊全局filter

有些過濾器使用的很頻繁,比如上面提到的日期過濾器,在很多地方都要使用,這時候如果在每一個要用到的組件里面都去定義一遍,就顯得有些多余了,這時候就可以考慮Vue.filter注冊全局過濾器

對于全局過濾器,一般建議在項目里面添加filters目錄,然后在filters目錄里面添加 

  1. // filters\index.js  
  2. import Vue from 'vue'  
  3. import { format } from '@/utils/date'  
  4. Vue.filter('formatDate', value => {  
  5.   return format(value, 'yyyy-MM-DD HH:mm:ss')  
  6. })  

然后將filters里面的文件引入到main.js里面,這時候就可以在組件里面直接用了,比如將前面的代碼可以修改為 

  1. <template>  
  2.   <div>  
  3.     <!--使用過濾器-->  
  4.     {{ dateStr | formatDate }}  
  5.     <ul>  
  6.       <li v-for="(item, index) in list" :key="index">  
  7.         <!--在v-for中使用過濾器-->  
  8.         {{ item.date | formatDate }}  
  9.       </li>  
  10.     </ul>  
  11.   </div>  
  12. </template>  
  13. <script>  
  14. export default {  
  15.   data() {  
  16.     return {  
  17.       date: Date.now(),  
  18.       list: [  
  19.         {  
  20.           date: Date.now()  
  21.         }  
  22.       ]  
  23.     }  
  24.   }  
  25.  
  26. </script>  

是不是更簡單了

開發(fā)了插件庫,來安裝一下

在使用一些UI框架的時候,經(jīng)常需要使用Vue.use來安裝, 比如使用element-ui時候,經(jīng)常會這樣寫: 

  1. import Vue from 'vue';  
  2. import ElementUI from 'element-ui';  
  3. import 'element-ui/lib/theme-chalk/index.css';  
  4. Vue.use(ElementUI,{size: 'small'});  

使用了Vue.use之后,element-ui就可以直接在組件里面使用了,好神奇哦(呸,娘炮)。接下來我們實現(xiàn)一個簡化版的element來看如何去安裝。

了解Vue.use的用法

Vue.use是一個全局的方法,它需要在你調(diào)用 new Vue() 啟動應用之前完成,Vue.use的參數(shù)如下 

  1. /**  
  2. * plugin: 要安裝的插件 如 ElementUI  
  3. * options: 插件的配置信息 如 {size: 'small'}  
  4. */ 
  5. Vue.use(plugin, options)  

模擬element-ui的安裝邏輯

想一下,使用 之后我們可以用到哪些element-ui提供的東西 

  1. 可以直接在組件里面用element-ui的組件,不需要再import
  2. 可以直接使用v-loading指令
  3. 通過this.$loading在組件里面顯示loading
  4. 其他... 
  1. // 這個是一個按鈕組件  
  2. import Button from '@/components/button'  
  3. // loading 指令  
  4. import loadingDirective from '@/components/loading/directive'  
  5. // loading 方法  
  6. import loadingMethod from '@/components/loading'  
  7. export default {  
  8.   /**  
  9.    * Vue.use 需要插件提供一個install方法  
  10.    * @param {*} Vue Vue  
  11.    * @param {*} options 插件配置信息  
  12.    */  
  13.   install(Vue, options) {  
  14.     console.log(options)  
  15.     // 將組件通過Vue.components 進行注冊  
  16.     Vue.components(Button.name, Button)  
  17.     // 注冊全局指令  
  18.     Vue.directive('loading', loadingDirective)  
  19.     // 將loadingMethod 掛載到 Vue原型鏈上面,方便調(diào)用  
  20.     Vue.prototype.$loading = loadingMethod 
  21.    }  
  22.  

通過上面的代碼,已經(jīng)實現(xiàn)了一個丐版的element-ui插件,這時候就可以在main.js里面通過Vue.use進行插件安裝了。大家可能會有疑問,為什么我要用這種寫法,不用這種寫法我照樣可以實現(xiàn)功能啊。小編認為這種寫法有兩個優(yōu)勢

  1. 標準化,通過提供一種統(tǒng)一的開發(fā)模式,無論對插件開發(fā)者還是使用者來說,都有一個規(guī)范去遵循。
  2. 插件緩存,Vue.use 在安裝插件的時候,會對插件進行緩存,即一個插件如果安裝多次,實際上只會在第一次安裝時生效。

插件的應用場景

  1. 添加全局方法或者 property。
  2. 添加全局資源:指令/過濾器/過渡等。
  3. 通過全局混入來添加一些組件選項。
  4. 添加 Vue 實例方法,通過把它們添加到 Vue.prototype 上實現(xiàn)。
  5. 一個庫,提供自己的 API,同時提供上面提到的一個或多個功能。如element-ui

提高Vue渲染性能,了解一下Object.freeze

當一個 Vue 實例被創(chuàng)建時,它將 data 對象中的所有的 property 加入到 Vue 的響應式系統(tǒng)中。當這些 property 的值發(fā)生改變時,視圖將會產(chǎn)生“響應”,即匹配更新為新的值。但是這個過程實際上是比較消耗性能的,所以對于一些有大量數(shù)據(jù)但只是展示的界面來說,并不需要將property加入到響應式系統(tǒng)中,這樣可以提高渲染性能,怎么做呢,你需要了解一下Object.freeze。

在Vue官網(wǎng)中,有這樣一段話:這里唯一的例外是使用 Object.freeze(),這會阻止修改現(xiàn)有的 property,也意味著響應系統(tǒng)無法再_追蹤_變化。這段話的意思是,如果我們的數(shù)據(jù)使用了Object.freeze,就可以讓數(shù)據(jù)脫離響應式系統(tǒng),那么該如何做呢?

比如下面這個表格,因為只是渲染數(shù)據(jù),這時候我們就可以通過Object.freeze來優(yōu)化性能 

  1. <template>  
  2.   <el-table :data="tableData" >  
  3.     <el-table-column prop="date" label="日期" width="180" />  
  4.     <el-table-column prop="name" label="姓名" width="180" />  
  5.     <el-table-column prop="address" label="地址" />  
  6.   </el-table>  
  7. </template>  
  8. <script>  
  9. export default {  
  10.   data() {  
  11.     const data = Array(1000)  
  12.       .fill(1)  
  13.       .map((item, index) => {  
  14.         return {  
  15.           date: '2020-07-11',  
  16.           name: `子君${index}`,  
  17.           address: '大西安'  
  18.         }  
  19.       })  
  20.     return {  
  21.       // 在這里我們用了Object.freeze  
  22.       tableData: Object.freeze(data)  
  23.     }  
  24.   }  
  25.  
  26. </script>  

有的同學可能會有疑問,如果我這個表格的數(shù)據(jù)是滾動加載的,你這樣寫我不就沒法再給tableData添加數(shù)據(jù)了嗎?是,確實沒辦法去添加數(shù)據(jù)了,但還是有辦法解決的,比如像下面這樣 

  1. export default {  
  2.   data() {  
  3.     return {  
  4.       tableData: []  
  5.     }  
  6.   },  
  7.   created() {  
  8.     setInterval(() => {  
  9.       const data = Array(1000)  
  10.         .fill(1)  
  11.         .map((item, index) => {  
  12.           // 雖然不能凍結(jié)整個數(shù)組,但是可以凍結(jié)每一項數(shù)據(jù)  
  13.           return Object.freeze({  
  14.             date: '2020-07-11',  
  15.             name: `子君${index}`,  
  16.             address: '大西安'  
  17.           })  
  18.         })  
  19.       thisthis.tableData = this.tableData.concat(data)  
  20.     }, 2000)  
  21.   }  
  22.  

合理的使用Object.freeze,是可以節(jié)省不少渲染性能,特別對于IE瀏覽器,效果還是很明顯的,趕快去試試吧。

最后如果你現(xiàn)在需要開發(fā)移動端項目,可以了解一下小編整理的一個開箱即用框架 vue-vant-base,也許可以幫到你哦

結(jié)語

不要吹滅你的靈感和你的想象力; 不要成為你的模型的奴隸。 ——文森特・梵高 

 

責任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2025-03-03 12:00:00

JavaScriptfor 循環(huán)語言

2025-03-10 08:44:17

2022-08-28 10:08:53

前端代碼前端

2023-03-15 15:54:36

Java代碼

2024-05-16 12:03:54

Python代碼開發(fā)

2023-09-27 07:49:23

2023-09-13 16:34:47

Java工具開發(fā)

2011-09-19 15:01:31

vistaAero特效

2023-06-26 08:01:42

debugger技巧代碼

2024-05-30 11:44:37

2021-02-23 18:38:11

iPhone地圖蘋果

2023-07-06 08:10:57

Vue3參數(shù)請求

2021-07-14 13:46:28

KubeVela阿里云容器

2024-07-25 09:40:00

2021-11-17 08:16:03

內(nèi)存控制Go

2015-02-04 10:32:57

Objective-CSwift

2020-05-07 17:03:49

Python編碼開發(fā)

2011-05-29 14:37:42

筆記本技巧

2011-01-19 09:07:20

Thunderbird

2023-11-28 10:17:37

點贊
收藏

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