本文轉(zhuǎn)自公眾號 藝述思維
不少互聯(lián)網(wǎng)公司都在使用vue技術(shù)棧,或稱為vue全家桶。
使用過vue的程序員一般這樣評價它,“vue.js兼具angular.js和react.js的優(yōu)點”。Vue.js 是一個JavaScript MVVM(Model-View-ViewModel)庫,用于漸近式構(gòu)建用戶界面。它以數(shù)據(jù)驅(qū)動和組件化思想構(gòu)建,采用自底向上增量開發(fā)的設(shè)計思想。相比Angular.js,Vue.js API更加簡潔;相比 React + Redux 復雜的架構(gòu),Vue.js 上手更加容易。
目錄
一、vue全家桶包括什么
vue-router路由
vuex
vue-resource
構(gòu)建工具vue-cli
調(diào)度工具Devtools
關(guān)于UI組件庫
二、vue工程目錄結(jié)構(gòu)
編輯器
三、vue使用簡介
數(shù)據(jù)代理
vue實例生命周期圖解
四、vue的運行原理
雙向綁定圖解
模板是如何解析的
五、發(fā)布前優(yōu)化
UI組件按需加載
路由懶加載
使用異步組件(動態(tài)組件)
圖片壓縮與合并
使用CDN加速vue類庫
壓縮代碼
v-for和v-if不要同時使用
使用Object.freeze凍結(jié)大數(shù)據(jù)
使用Keep-alive標簽優(yōu)化組件創(chuàng)建
使用Set
在scope中少用元素選擇器
關(guān)于template的優(yōu)化
一、vue全家桶包括什么
vue-router路由
網(wǎng)站:http://router.vuejs.org。使用npm工具來安裝vue-router
npm install vue-router
通過import導入Vue模塊、vue-router模塊及其它組件。
import Vue from’vue’
importRouter from’vue-router’
在使用路由前,必須要通過 Vue.use() 明確地安裝路由功能。
Vue.use(Router)
通過const router= new VueRouter()定義路由,并傳入對應(yīng)的配置,包括路徑path和組件components等。
在使用newVue來創(chuàng)建和掛載vue根實例的時候,記得要通過 router配置參數(shù)注入路由。使用router-link:
有兩種模式:
hash 模式
history 模式
vuex
網(wǎng)站:http://vuex.vuejs.org
在vue開發(fā)實戰(zhàn)中,多個組件共享數(shù)據(jù)時,單向數(shù)據(jù)流的簡潔性很容易被破壞。為解決多個視圖使用同一數(shù)據(jù)及多個視圖驅(qū)動同一數(shù)據(jù)更新的問題,vuex應(yīng)運而生。
當網(wǎng)站足夠大時,一個狀態(tài)樹下,根的部分字段繁多,解決這個問題就要模塊化 vuex,官網(wǎng)提供了模塊化方案,允許我們在初始化 vuex 的時候配置 modules。每一個 module 里面又分別包含 state 、action 等,看似是多個狀態(tài)樹,其實還是基于 rootState 的子樹。細分后整個 state 結(jié)構(gòu)就清晰了,管理起來也方便許多。
Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。Vuex 的四個核心概念是:
The state tree:Vuex 使用單一狀態(tài)樹,用一個對象就包含了全部的應(yīng)用層級狀態(tài)。至此它便作為一個唯一數(shù)據(jù)源(SSOT)而存在。這也意味著,每個應(yīng)用將僅僅包含一個 store 實例。單狀態(tài)樹讓我們能夠直接地定位任一特定的狀態(tài)片段,在調(diào)試的過程中也能輕易地取得整個當前應(yīng)用狀態(tài)的快照。
Getters:用來從 store 獲取 Vue 組件數(shù)據(jù)。
Mutators:事件處理器用來驅(qū)動狀態(tài)的變化。
Actions:可以給組件使用的函數(shù),以此用來驅(qū)動事件處理器 mutations。(注:此許或許稱之為EventHandler更為恰當。)
Vuex和簡單的全局對象是不同的。當Vuex從store中讀取狀態(tài)值的時候,若狀態(tài)發(fā)生了變化,那么相應(yīng)的組件也會更新。并且改變store中狀態(tài)的唯一途徑就是提交commit mutations。只要發(fā)生了狀態(tài)的變化,一定伴隨著mutation的提交。 例如:
通過 store.state 來獲取狀態(tài)對象,以及通過 store.commit 方法觸發(fā)狀態(tài)變更:
由于 vuex 的靈活性,帶來了編碼不統(tǒng)一的情況,完整的閉環(huán)是 store.dispatch('action') -> action -> commit -> mutation -> getter -> computed,實際上中間的環(huán)節(jié)有的可以省略,因為 API 文檔提供了以下幾個方法 mapState、mapGetters、mapActions、mapMutations,然后在組件里可以直接調(diào)取任何一步,還是項目小想怎么調(diào)用都可以,項目大的時候,就要考慮 vuex 使用的統(tǒng)一性,有人建議是不論多簡單的流程都跑完整個閉環(huán),形成代碼的統(tǒng)一,方便后期管理,在組件里只允許出現(xiàn) dispatch 和 mapGetters,其余的流程都在名為 store 的 vuex 文件夾里進行。
注:mapGetters 工具函數(shù)會將 store 中的 getter 映射到局部計算屬性中。它的功能和 mapState 非常類似。
vue-resource
網(wǎng)站:https://github.com/pagekit/vue-resource
使用npm來安裝Vue-resource:
$ npm install vue-resource
在安裝并引入vue-resource后,可以基于全局的Vue對象使用http,也可以基于某個Vue實例使用http。
在發(fā)送請求后,使用then方法來處理響應(yīng)結(jié)果,then方法有兩個參數(shù),第一個參數(shù)是響應(yīng)成功時的回調(diào)函數(shù),第二個參數(shù)是響應(yīng)失敗時的回調(diào)函數(shù)。
vue-resource的請求API是按照REST風格設(shè)計的,它提供了7種請求API:
· get(url,[options])
· head(url,[options])
· delete(url,[options])
· jsonp(url,[options])
· post(url,[body], [options])
· put(url, [body],[options])
· patch(url,[body], [options])
構(gòu)建工具vue-cli
vue-cli是vue標準的開發(fā)工具。網(wǎng)站:https://cli.vuejs.org/
安裝
npm install -g @vue/cli
最新版本為3.4.0。
創(chuàng)建項目
vue create my-project
以上是命令行創(chuàng)建。也可以通過 vue ui 命令以圖形化界面創(chuàng)建和管理項目:
vue ui
運行
npm run serve
調(diào)度工具Devtools
vue在調(diào)試方面,可以選擇安裝chrome插件vue Devtools。打開vue項目,在調(diào)試vue應(yīng)用的時候,chrome開發(fā)者工具中會看一個vue的一欄,點擊之后就可以看見當前頁面vue對象的一些信息。
在Devtools工具中,可以選擇組件,查看對應(yīng)組件內(nèi)的數(shù)據(jù)信息。也可以選擇Vuex選項,查看該項目內(nèi)Vuex的狀態(tài)變量信息。
關(guān)于UI組件庫
可以自己寫,為提高開發(fā)效率也可以復用第三方組件庫。element(https://github.com/ElemeFE/element)是一個最好支持vue2.0的UI組件庫。
二、vue工程目錄結(jié)構(gòu)
這是一個簡單的vue項目的大概結(jié)構(gòu):
components/文件夾:用來存放Vue 組件。個人建議,把每一個組件中使用到的image圖片放置到對應(yīng)的組件子文件目錄下,便于統(tǒng)一的管理
Node_modules/:npm安裝的該項目的依賴庫
vuex/文件夾:存放的是和 Vuex store 相關(guān)的東西(state對象,actions,mutations)
router/文件夾:存放的是跟vue-router相關(guān)的路由配置項
build/文件:是 webpack 的打包編譯配置文件
static/文件夾:存放一些靜態(tài)的、較少變動的image或者css文件
config/文件夾:存放的是一些配置項,比如服務(wù)器訪問的端口配置等
dist/該文件夾:一開始是不存在,在我們的項目經(jīng)過 build 之后才會產(chǎn)出
App.vue根組件,所有的子組件都將在這里被引用
index.html整個項目的入口文件,將會引用我們的根組件 App.vue
main.js入口文件的 js 邏輯,在webpack 打包之后將被注入到 index.html 中
編輯器
VSCode with Vetur
三、vue使用簡介
數(shù)據(jù)代理
每個 Vue.js 應(yīng)用都是通過構(gòu)造函數(shù) Vue 創(chuàng)建一個 Vue 的根實例 啟動的。每個 Vue 實例都會代理其 data 對象里所有的屬性:
var data = { a: 1 }
var vm = new Vue({
data: data
})
vm.a === data.a // -> true
設(shè)置新值也會同步影響:
vm.a = 2
data.a // -> 2
// ... 反之亦然
data.a = 3
vm.a // -> 3
實現(xiàn)數(shù)據(jù)代理的偽代碼如下:
var self = this; // this為vue實例, 即vm
Object.keys(this.data).forEach(function(key) {
Object.defineProperty(this, key, { // this.title, 即vm.title enumerable: false, configurable: true, get: function getter () { return self.data[key]; //觸發(fā)對應(yīng)data[key]的getter }, set: function setter (newVal) { self.data[key] = newVal; //觸發(fā)對應(yīng)data[key]的setter } });}
Vue 實例暴露了一些有用的實例屬性與方法。這些屬性與方法都有前綴 $,以便與代理的 data 屬性區(qū)分。例如:
vm.$data === data // -> true
vm.$el === document.getElementById('example') // -> true
vue實例生命周期圖解
四、vue的運行原理
Vue采用簡潔的模板語法,以聲明的方式將數(shù)據(jù)渲染進 DOM。vue代碼是沒有辦法直接被瀏覽器解析的,必須經(jīng)過“編譯”,變?yōu)闉g覽器可以識別為html、js與css代碼。這種聲明式開發(fā)方式把方便留給了程序員,轉(zhuǎn)換工作交給了自動化工具。
注:el是element的縮寫,指Vue實例掛載的元素節(jié)點。
雙向綁定圖解
一般說的雙向綁定,指:
數(shù)據(jù)變動 --> 視圖更新
視圖更新 --> 數(shù)據(jù)變動
視圖更新 --> 數(shù)據(jù)變動,這個方向的綁定比較簡單。主要通過事件監(jiān)聽來改變數(shù)據(jù),比如input控件可以監(jiān)聽input事件,一旦事件觸發(fā),調(diào)用JS改變data。
模型層(model)只是普通 JavaScript 對象,修改它,DOM本是不能更新的。當程序員把一個普通 JavaScript 對象傳給 Vue 實例的 data 選項,Vue 將遍歷此對象所有的屬性,并使用 Object.defineProperty 把這些屬性全部轉(zhuǎn)為 getter/setter。在每個setter中,可以做許多事件,使表面看起來數(shù)據(jù)變了,視圖就更新了。并且這種數(shù)據(jù)更新,和原來一樣,只是 vm.a=123 這樣的簡單更新。
如上所求,每個vue組件實例都有相應(yīng)的 watcher 實例對象,它會在vue組件渲染的過程中把需要用到的屬性(getter)記錄為依賴。之后,當依賴項的 setter 被(其它JS代碼)調(diào)用時,setter 會通知 watcher 重新計算,從而致使它關(guān)聯(lián)的組件得以更新。
此處實現(xiàn)的是一個觀察者模式。
通過object.defineProperty遍歷設(shè)置this.data里面所有屬性,在每個屬性的setter里面去通知對應(yīng)的回調(diào)函數(shù),這里的回調(diào)函數(shù)包括dom視圖重新渲染的函數(shù)、使用$watch添加的回調(diào)函數(shù)等,這樣我們就通過object.defineProperty劫持了數(shù)據(jù),當我們對數(shù)據(jù)重新賦值時,如this.title = 'hello vue',就會觸發(fā)setter函數(shù),從而觸發(fā)dom視圖重新渲染的函數(shù),實現(xiàn)數(shù)據(jù)變動,對應(yīng)視圖更新。
那么,如何在setter里面觸發(fā)所有綁定該數(shù)據(jù)的回調(diào)函數(shù)呢?
既然綁定該數(shù)據(jù)的回調(diào)函數(shù)不止一個,我們就把所有的回調(diào)函數(shù)放在一個數(shù)組里面,一旦觸發(fā)該數(shù)據(jù)的setter,就遍歷數(shù)組觸發(fā)里面所有的回調(diào)函數(shù),我們把這些回調(diào)函數(shù)稱為訂閱者。數(shù)組最好就定義在setter函數(shù)的最近的上級作用域中,如下面實例代碼所示。
> Object.keys(this.data).forEach(function(key) {
>
> var subs = []; // 在這里放置添加所有訂閱者的數(shù)組
>
> Object.defineProperty(this.data, key, { // this.data.title
>
> enumerable: false,
>
> configurable: true,
>
> get: function getter () {
>
> console.log('訪問數(shù)據(jù)啦啦啦')
>
> return this.data[key]; //返回對應(yīng)數(shù)據(jù)的值
>
> },
>
> set: function setter (newVal) {
>
> if (newVal === this.data[key]) {
>
> return; // 如果數(shù)據(jù)沒有變動,函數(shù)結(jié)束,不執(zhí)行下面的代碼
>
> }
>
> this.data[key] = newVal; //數(shù)據(jù)重新賦值
>
> subs.forEach(function () {
>
> // 通知subs里面的所有的訂閱者
>
> })
>
> }
>
> });
>
> }
那么,怎么把綁定數(shù)據(jù)的所有回調(diào)函數(shù)放到一個數(shù)組里面呢?這是通過gettter內(nèi)部的代碼完成的。
我們知道只要訪問數(shù)據(jù)就會觸發(fā)對應(yīng)數(shù)據(jù)的getter,那我們可以先設(shè)置一個全局變量target,如果我們要在data里面title屬性添加一個訂閱者(changeTitle函數(shù)),我們可以先設(shè)置target = changeTitle,把changeTitle函數(shù)緩存在target中,然后訪問this.title去觸發(fā)title的getter,在getter里面把target這個全局變量的值添加到subs數(shù)組里面,添加完成后再把全局變量target設(shè)置為null,以便添加其他訂閱者。
偽代碼如下:
> target = changeTitle
>
> ...
>
> Object.keys(this.data).forEach(function(key) {
>
> var subs = []; // 在這里放置添加所有訂閱者的數(shù)組
>
> Object.defineProperty(this.data, key, { // this.data.title
>
> enumerable: false,
>
> configurable: true,
>
> get: function getter () {
>
> console.log('訪問數(shù)據(jù)啦啦啦')
>
> if (target) {
>
> subs.push(target);
>
> }
>
> return this.data[key]; //返回對應(yīng)數(shù)據(jù)的值
>
> },
>
> set: function setter (newVal) {
>
> if (newVal === this.data[key]) {
>
> return; // 如果數(shù)據(jù)沒有變動,函數(shù)結(jié)束,不執(zhí)行下面的代碼
>
> }
>
> this.data[key] = newVal; //數(shù)據(jù)重新賦值
>
> subs.forEach(function () {
>
> // 通知subs里面的所有的訂閱者
>
> })
>
> }
>
> });
>
> }
上面代碼中提到的changeTitle,即是上面最近一張圖解中的watcher。vue通過getter收集watcher集合。因為vue充許在運行時添加代碼,所以該收集行為不能僅限制于模板“編譯”之前。(注:vue中是不存在嚴格的編譯的,js是解析執(zhí)行型語言,像C、Go等語言將源碼編譯為目標平臺的二進制文件,才是真的編譯。)
模板是如何解析的
假如說有下面這一段代碼,我們怎么把它解析成對應(yīng)的html呢?
> <input v-model="title">
>
> <h1>{{title}}</h1>
>
> <button v-on:click="changeTitle">change title<button>
注:該示例實現(xiàn)的效果是,在input輸入框內(nèi)輸入任何內(nèi)容,下方h1文本同步更新。
先簡單介紹視圖更新函數(shù)的用途,比如解析指令v-model="title",v-on:click="changeTitle",還有把{{title}}替換為對應(yīng)的數(shù)據(jù)等。
回到上面那個問題,如何解析模板?我們只要去遍歷所有dom節(jié)點包括其子節(jié)點:
如果節(jié)點屬性含有v-model,視圖更新函數(shù)就為把input的value設(shè)置為title的值
如果節(jié)點為文本節(jié)點,視圖更新函數(shù)就為先用正則表達式取出大括號里面的值'title',再設(shè)置文本節(jié)點的值為data['title']
如果節(jié)點屬性含有v-on:xxxx,視圖更新函數(shù)就為先用正則獲取事件類型為click,然后獲取該屬性的值為changeTitle,則事件的回調(diào)函數(shù)為this.methods['changeTitle'],接著用addEventListener監(jiān)聽節(jié)點click事件。
五、發(fā)布前優(yōu)化
使用vue-cli部署生產(chǎn)包時,發(fā)現(xiàn)資源包很大,打包后的vendor.js達到了1M+。
UI組件按需加載
如果使用了第三方組件/UI庫,如element-ui, mint-ui,echarts等,如果全部引入,項目體積非常大,這時可以按需引入組件。
安裝 babel-plugin-component
npm install babel-plugin-component -D
然后,將.babelrc 修改為:
> {
>
> "presets": [["es2015", { "modules": false }]],
> "plugins": [
> [
> "component",
> {
> "libraryName": "element-ui",
> "styleLibraryName": "theme-chalk"
> }
> ]
> ]
> }
然后引入部分組件,這樣一來,就不需要引入樣式了,插件會幫我們處理。
> // main.js
> import Vue from 'vue'
> import { Dialog, Loading } from 'element-ui'
> Vue.use(Dialog)
> Vue.use(Loading.directive)
> Vue.prototype.$loading = Loading.service
> // 然后正常使用組件
注:Babel是一個廣泛使用的轉(zhuǎn)碼器,可以將ES6代碼轉(zhuǎn)為ES5代碼。讓不支持ES6的宿主環(huán)境,支持使用一套源碼開發(fā)。
mint-ui是element-ui的移動端組件,所以它的使用和引入幾乎和element-ui一樣。
路由懶加載
vue-router官方推薦syntax-dynamic-import插件,不過它要求同時安裝@bable/core^7.0.0,如果你安裝了babel-core6,可能有版本沖突的,解決方法如下:
npm install babel-plugin-syntax-dynamic-import --save-dev(^6.18.0)
當打包構(gòu)建應(yīng)用時,Javascript 包會變得非常大,影響頁面加載。如果我們能把不同路由對應(yīng)的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應(yīng)組件,這樣就更加高效了。結(jié)合 Vue 的異步組件和 Webpack 的代碼分割功能,輕松實現(xiàn)路由組件的懶加載。
> // router.js
> const login = () => import('@/components/login')
> const router = new VueRouter({
> routes: [
> { path: '/login', component: login }
> ]
> })
還有一種魔法注釋用法,不推薦使用。
使用異步組件(動態(tài)組件)
app bundle 文件過大,可以嘗試通過組件懶加載優(yōu)化。
動態(tài)組件主頁面加載是不會加載,等到觸發(fā)條件時才加載該組件,并且加載一次后就有緩存。如果組件在頁面加載時不需要,只在調(diào)用時用到,這時可以使用異步組件的寫法。僅僅是引入和組件注冊寫法不同:
> // template
> <test v-if="showTest"></test>
>
> // script
>
> components: {
> test: () => import('./test') // 將組件異步引入,告訴webpack,將該部分代碼分割打包
> },
>
> methods:{
> clickTest () {
> this.showTest = !this.showTest
> }
> }
圖片壓縮與合并
無損壓縮圖片:https://tinypng.com/??梢詫D片制成雪碧精靈圖。
使用CDN加速vue類庫
一般項目里用到的第三方j(luò)s庫主要有:vue、vue-router、vuex、vue-resource、axio、qiniu等。這些依賴庫的js文件被一起打包到vender那個js文件里面,導致vender這個文件很大,那首屏加載速度肯定會被拖慢。
類庫文件使用cdn加速
> <!-- built files will be auto injected -->
>
> <script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
>
> <script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
>
> <script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
>
> <script src="https://cdn.bootcss.com/vue-resource/1.5.1/vue-resource.min.js"></script>
修改 build/webpack.base.conf.js
> module.exports = {
>
> context: path.resolve(__dirname, '../'),
>
> entry: {
>
> app: './src/main.js'
>
> },
>
> externals:{
>
> 'vue': 'Vue',
>
> 'vue-router': 'VueRouter',
>
> 'vuex':'Vuex',
>
> 'vue-resource': 'VueResource'
>
> }
排除已經(jīng)手動收入的js文件
利用webpack的externals。具體做法就是在 build/webpack.base.conf.js文件的module里面與rules同層加入externals。具體做法,修改src/main.js src/router/index.js 注釋掉import引入的vue,vue-resource等:
> // import Vue from 'vue'
>
> // import VueResource from 'vue-resource'
>
> // Vue.use(VueResource)
上面已經(jīng)引用過。
壓縮代碼
vue-cli已經(jīng)使用UglifyJsPlugin 插件來壓縮代碼,可以設(shè)置成如下配置:
> new webpack.optimize.UglifyJsPlugin({
>
> compress: {
>
> warnings: false,
>
> drop_console: true,
>
> pure_funcs: ['console.log']
>
> },
>
> sourceMap: false
>
> })
其中sourceMap: false是禁用除錯功能。如果設(shè)為true,在部署包中會生成.map結(jié)尾的js文件。它用于在代碼混淆壓縮的情況下仍可進行調(diào)試。這個功能雖好,但會大大增加整體資源包的體積,所以將其禁用。
v-for和v-if不要同時使用
在vue中v-for和v-if不要放在同一個元素上使用。由于 v-for 和 v-if 放在同一個元素上使用會帶來一些性能上的影響,在計算屬性上過濾之后再進行遍歷。反例:
使用Object.freeze凍結(jié)大數(shù)據(jù)
對于前端純大數(shù)據(jù)展示(純大數(shù)據(jù)指:拿到數(shù)據(jù)就是直接用于展示的,不需要做修改其中字段等處理的,而且數(shù)據(jù)量比較大)的情況下,使用Object.freeze方法來包裹變量,那邊vue內(nèi)部不會使用defineproperty去監(jiān)聽數(shù)據(jù)內(nèi)部的變化,只有本身變化時才會觸發(fā),在大量數(shù)據(jù)的情況下,vue內(nèi)部不在去監(jiān)聽數(shù)據(jù)的變化會提高性能。使用demo如下:
使用Keep-alive標簽優(yōu)化組件創(chuàng)建
vue提供了keep-alive標簽來存儲緩存,對于一些視頻控件object或圖表類的使用,我們經(jīng)常會使用v-if指令,而v-if是會創(chuàng)建和銷毀的,如果頻繁操作在ie下的內(nèi)存會持續(xù)上升,而keep-alive可以有效的緩存,抑制內(nèi)存的持續(xù)上升。
見:https://cn.vuejs.org/v2/api/#keep-alive
使用Set
Es6集合Set()可優(yōu)化遍歷速度,set集合是可用于查找該集合內(nèi)是否存在某個元素。但如果使用了Bable自動轉(zhuǎn)化,該優(yōu)化無效。
在scope中少用元素選擇器
scope中元素選擇器盡量少用。在 scoped 樣式中,類選擇器比元素選擇器更好,因為大量使用元素選擇器是很慢的。
為了給樣式設(shè)置作用域,Vue 會為元素添加一個獨一無二的特性,例如 data-v-f3f3eg9。然后修改選擇器,使得在匹配選擇器的元素中,只有帶這個特性才會真正生效 (比如 button[data-v-f3f3eg9])。問題在于大量的元素和特性組合的選擇器 (比如 button[data-v-f3f3eg9]) 會比類和特性組合的選擇器 慢,所以應(yīng)該盡可能選用類選擇器。
關(guān)于template的優(yōu)化
v-show,v-if 用哪個?在我來看要分兩個維度去思考問題,第一個維度是權(quán)限問題,只要涉及到權(quán)限相關(guān)的展示無疑要用 v-if,第二個維度在沒有權(quán)限限制下根據(jù)用戶點擊的頻次選擇,頻繁切換的使用 v-show,不頻繁切換的使用 v-if,這里要說的優(yōu)化點在于減少頁面中 dom 總數(shù),我比較傾向于使用 v-if,因為減少了 dom 數(shù)量,加快首屏渲染,至于性能方面我感覺肉眼看不出來切換的渲染過程,也不會影響用戶的體驗。
不要在模板里面寫過多的表達式與判斷 v-if="isShow && isAdmin && (a || b)",這種表達式雖說可以識別,但是不是長久之計,當看著不舒服時,適當?shù)膶懙?methods 和 computed 里面封裝成一個方法,這樣的好處是方便我們在多處判斷相同的表達式,其他權(quán)限相同的元素再判斷展示的時候調(diào)用同一個方法即可。
循環(huán)調(diào)用子組件時添加 key,key 可以唯一標識一個循環(huán)個體,可以使用例如 item.id 作為 key,假如數(shù)組數(shù)據(jù)是這樣的 ['a' , 'b', 'c', 'a'],使用 :key="item" 顯然沒有意義,更好的辦法就是在循環(huán)的時候 (item, index) in arr,然后 :key="index"來確保 key 的唯一性。
2019年2月14日
寫在最后:通篇文章完整讀下來可以學到蠻多知識點的 值得學習以下
此外 對于最后一段對于v-for的循環(huán)來說 :key的值最好不要為index 作為唯一性的key值如果變動以后 框架會認為替換了內(nèi)容而對改變的index項之后的循環(huán)都重新渲染了. 正確的做法應(yīng)該是數(shù)據(jù)中包含唯一的key來作為值來綁定. (推薦這么做 因為這時插入一條數(shù)據(jù) 只是在index添加一條數(shù)據(jù) 之后的數(shù)據(jù)不會重新渲染 實際情況應(yīng)項目而異)
參考資料: