『壹』 Vue - 組件和Vue.extend
在初學 Vue 的時候,都是利用 cdn 的方式在一個頁面中導入 vue.js 的庫文件.
接著,肯定就學到了組件開發.
當然,也是在單頁面中.
API文檔告訴我們
在後來,學到了使用 vue-cli 搭配 .vue 模板的方式開發組件.
好了,三種組件創建的方式說完了,且在各自的環境里都能夠正常的運作.
在 Vue 開發中,所有的組件本質上都是由一個繼承自 Vue 的構造函數創建的.
比如在注冊局部組件時.
從視覺上,我們看到 TodoListComp 只是一個普通的 Object 對象.
直接賦值給了其他組件的 components 屬性里.
然後,這個組件就成為了一個局部組件,並可以在注冊了當前組件的內部去使用了.
那它在內部做了什麼,導致這個普通的對象最後可以被當成是一個正常的組件來使用呢?
比如,普通對象上都沒有 $el 之類的屬性.丟給 components 之後,就啥都有了.
使用Vue.extend(options)會根據傳入的options創建一個VueComponent的組件構造函數並返回.
既然使用 Vue.extend 會返回一個組件的構造函數.
那麼我們就可以使用 new 這個返回的構造函數
並手動的 mount 並替換某個 dom 節點(就和 new App() 一樣)
前面,我么已經知道了,所有的 vue 組件,不管是全局的還是局部的.
都是利用 Vue.extend 方法構建並返回出一個繼承自 Vue 的組件構造函數.
這個函數接受一個滿足了 Vue 組件屬性項的普通的 Object 對象.
在.vue模板文件開發中,也不例外.
我們可以看看,在書寫 .vue 模板文件時,我們到底在寫什麼?
我們寫的是一個 .vue 文件.
並按照 <template></template> <script></script> ( 這里不關注 <style></style> 節點 ) 的格式編寫 .vue 文件.
把它整合起來來看.
等價於
好了,繼續回到 .vue 模板開發文件中.
在另外一個組件中,使用此組件時,我們會 import xxx from xxx.vue 並搭配 components:{ xxxx }
.vue 會被 webpack 中配置的 vue-loader 處理.這是我們已知的.
結合上述的判斷, vue-loader 僅僅只是把 .vue 文件編譯成了一個 vue.extend(options) 創建組件所需要的 options 普通對象而已.
既然 vue-loader 僅僅,只是把 .vue 模板文件編譯成了一個 options 普通對象.
那麼我們可以手動的使用 Vue.extends(options) 來獲得這個組件對象的構造函數.
拿到此組件的構造函數,我們就可以在 組件 mounted 的時候,通過 new 的方式,掛在到 html 上了. (而無需去注冊到 components,成為一個局部組件.直接把它當成一個自己熟悉的不能在熟悉的構造函數調用即可.)
既然我們已經知道:
我們完全可以直接使用 .js 文件的方式來創建 vue 組件,進而省略 .vue & vue-loader 這個執行的步驟.
此 .js 文件到處一個 vue 組件的構造函數.
在另外一個組件里
通過這樣的原理,我們完全可以在HTML頁面的任意地方,任意位置,任意的掛在我們自己的組件.並不一定必須使用.vue聲明式組件的語法.
[ 碼雲地址 ]
『貳』 Vue3基礎-模板語法
如果我們希望把數據顯示到模板(template)中,使用最多的語法是 「Mustache」語法 (雙大括弧) 的文本插值。
並且我們前端提到過,data返回的對象是有添加到Vue的響應式系統 中,當data中的數據發生改變時,對應的內容也會發生更新。
當然,Mustache中不僅僅可以是data中的屬性,也可以是一個JavaScript的表達式:
下面這種寫法是語句不是表達式,所以是錯誤的:
v-once用於指定元素或者組件只渲染一次,當數據發生變化時,元素或者組件以及其所有的子元素將視為靜態內容並且跳過,該指令可以用於性能優化。
如果添加到父節點,那麼所有的子節點也是只會渲染一次:
用於更新元素的 textContent,等價於"Mustache"語法,而且"Mustache"語法更靈活。
默認情況下,如果我們展示的內容本身是 html 的,那麼vue並不會對其進行特殊的解析。如果我們希望這個內容被Vue可以解析出來,那麼可以使用 v-html 來展示。
效果如下:
v-pre用於跳過元素和它的子元素的編譯過程,顯示原始的Mustache標簽。
跳過不需要編譯的節點,加快編譯的速度。
效果如下:
這個指令保持在元素上直到關聯組件實例結束編譯。
v-cloak 和 CSS 規則如 [v-cloak] { display: none } 一起用時,這個指令可以隱藏未編譯的 Mustache 標簽直到組件實例准備完畢,主要用於解決閃動問題,現在Vue3一般不會出現這個問題了。
<div> 不會顯示,直到編譯結束。
前面講的一系列指令,主要是將值插入到模板內容中。但是,除了內容需要動態來決定外,某些屬性我們也希望動態來綁定。比如動態綁定a元素的href屬性,動態綁定img元素的src屬性。
綁定屬性我們使用 v-bind: ,縮寫 : ,用於動態地綁定一個或多個 attribute,或一個組件 prop 到表達式。
v-bind用於綁定一個或多個屬性值,或者向另一個組件傳遞props值(這個學到組件時再介紹),在開發中,有哪些屬性需要動態進行綁定呢?還是有很多的,比如圖片的鏈接src、網站的鏈接href、動態綁定一些類、樣式等等。
v-bind有一個對應的語法糖,也就是簡寫方式,在開發中,我們通常會使用語法糖的形式,因為更簡潔。
注意 :Vue2 template模板中只能有一個根元素,Vue3 template模板中允許有多個根元素。
在開發中,有時候我們的元素class也是動態的,比如:當數據為某個狀態時,字體顯示紅色,當數據另一個狀態時,字體顯示黑色。
綁定class有兩種方式:對象語法,數組語法。
① 對象語法:我們可以傳給 :class (v-bind:class 的簡寫) 一個對象,以動態地切換 class。
② 數組語法:我們可以把一個數組傳給 :class,以應用一個 class 列表;
我們可以利用v-bind:style來綁定一些CSS內聯樣式,這是因為某些樣式我們需要根據數據動態來決定,比如某段文字的顏色,大小等等。
CSS屬性名可以用駝峰式 (camelCase) 或短橫線分隔 (kebab-case,記得用引號括起來) 來命名。
綁定style有兩種方式:對象語法,數組語法。
① 對象語法:
② 數組語法: :style 的數組語法可以將多個樣式對象應用到同一個元素上
在某些情況下,我們屬性的名稱可能也不是固定的。
前面我們無論綁定src、href、class、style,屬性名稱都是固定的,如果屬性名稱不是固定的,我們可以使用 :[屬性名]=「值」 的格式來定義,這種綁定的方式,我們稱之為動態綁定屬性。
如果我們希望將一個對象的所有屬性,綁定到元素上的所有屬性,應該怎麼做呢?非常簡單,我們可以直接使用 v-bind 綁定一個對象。
如下:info對象會被拆解成div的各個屬性。
前面我們綁定了元素的內容和屬性,在前端開發中另外一個非常重要的特性就是交互。
在前端開發中,我們需要經常和用戶進行各種各樣的交互,這個時候,我們就必須監聽用戶發生的事件,比如點擊、拖拽、鍵盤事件等等。
在Vue中如何監聽事件呢?使用v-on指令。接下來我們來看一下v-on的用法:
我們可以使用v-on來監聽一下點擊的事件:
v-on:click可以寫成@click,是它的語法糖寫法:
當然,我們也可以綁定其他的事件:
如果我們希望一個元素綁定多個事件,這個時候可以傳入一個對象:
當通過methods中定義方法,以供@click調用時,需要注意參數問題:
情況一:如果該方法不需要額外參數,那麼方法後的()可以不添加,並且方法的實現不用參數,直接就可以列印event。
情況二:如果需要同時傳入某個參數和event時,可以通過$event傳入事件,並且方法的實現必須按順序寫明參數。
@keyup.enter 代表enter鍵彈起的時候會調用onEnter方法,我們一般在方法裡面獲取輸入的值:
在某些情況下,我們需要根據當前的條件決定某些元素或組件是否渲染,這個時候我們就需要進行條件判斷了。
Vue提供了下面的指令來進行條件判斷:
下面我們來對它們進行學習。
v-if、v-else、v-else-if 用於根據條件來渲染某一塊的內容,這些內容只有在條件為true時,才會被渲染出來,這三個指令與JavaScript的條件語句 if、else、else if 類似。
v-if 的渲染原理:v-if是惰性的,當條件為false時,其判斷的內容完全不會被渲染或者會被銷毀掉,當條件為true時,才會真正渲染條件塊中的內容。
因為v-if是一個指令,所以必須將其添加到一個元素上,但是如果我們希望切換的是多個元素呢?
如果此時我們使用div包裹,div會被渲染到界面上來,但是我們並不希望div被渲染,這個時候,我們可以選擇使用template,template元素可以當做不可見的包裹元素,並且 v-if 可以添加到 template 上,但是最終template不會被渲染出來,類似於小程序中的block。
v-show和v-if的用法看起來是一致的,也是根據一個條件決定是否顯示元素或者組件。
首先,在用法上的區別:
其次,本質的區別:
開發中如何進行選擇呢?
在真實開發中,我們往往會從伺服器拿到一組數據,並且需要對其進行渲染。這個時候我們可以使用v-for來完成,v-for類似於JavaScript的for循環,可以用於遍歷一組數據。
v-for的基本格式是 "item in 數組" ,數組通常是來自data或者prop,也可以是其他方式,item是我們給每項元素起的一個別名,這個別名可以自定來定義。
我們知道,在遍歷一個數組的時候會經常需要拿到數組的索引,如果我們需要索引,可以使用格式 "(item, index) in 數組" ,注意順序,數組元素項item在前面,索引項index在後面。
類似於v-if,你可以使用 template 元素來循環渲染一段包含多個元素的內容。
我們使用template來對多個元素進行包裹,而不是使用div來完成,因為div會被渲染,template不會被渲染。而且如果有ul,ul裡面不推薦放div,只推薦放li。
Vue 將被偵聽的數組的變更方法進行了包裹,所以它們也將會觸發視圖更新,這些被包裹過的方法包括:
上面的方法會直接修改原來的數組,所以視圖會跟著更新。但是某些方法不會替換原來的數組,而是會生成新的數組,比如 filter()、concat() 和 slice(),這時候我們可以通過重新賦值的方式觸發視圖更新,如下:
在使用v-for進行列表渲染時,我們通常會給元素或者組件綁定一個key屬性。
這個key屬性有什麼作用呢?
我們先來看一下官方的解釋:key屬性主要用在Vue的虛擬DOM演算法,在新舊nodes對比時辨識VNodes。如果不使用key,Vue會使用一種最大限度減少動態元素並且盡可能的嘗試就地修改/復用相同類型元素的演算法,而使用key時,它會基於key的變化重新排列元素順序,並且會移除/銷毀key不存在的元素。
官方的解釋對於初學者來說並不好理解,比如下面的問題:
什麼是新舊nodes,什麼是VNode?
沒有key的時候,如何嘗試修改和復用的?
有key的時候,如何基於key重新排列的?
我們先來解釋一下VNode的概念:
VNode的全稱是Virtual Node,也就是虛擬節點。事實上,無論是組件還是元素,它們最終在Vue中表示出來的都是一個個VNode。VNode的本質是一個JavaScript的對象。
如果我們不只是一個簡單的div,而是有一大堆的元素,那麼它們應該會形成一個VNode Tree。
我們先來看一個案例:這個案例是當我們點擊按鈕時會在li中間插入一個f。
我們可以確定的是,這次更新對於ul和button是不需要進行更新,需要更新的是我們li的列表。在Vue中,對於相同父元素的子元素節點並不會重新渲染整個列表,因為對於列表中 a、b、c、d它們都是沒有變化的。在操作真實DOM的時候,我們只需要在中間插入一個f的li即可。
那麼Vue中對於列表的更新究竟是如何操作的呢?
Vue事實上會對於有key和沒有key會調用兩個不同的方法,有key,那麼就調用 patchKeyedChildren方法,沒有key,那麼就調用 patchUnkeyedChildren方法。
沒有key的diff演算法:
我們會發現上面的diff演算法效率並不高,c和d來說它們事實上並不需要有任何的改動,但是因為我們的c被f所使用了,所有後續所有的內容都要一次進行改動,並且最後進行新增。
有key的diff演算法:
所以我們可以發現,Vue在進行diff演算法的時候,會盡量利用我們的key來進行優化操作,在沒有key的時候我們的效率是非常低效的,在進行插入或者重置順序的時候,保持相同的key可以讓diff演算法更加的高效。
『叄』 什麼是vue
Vue.js是一個構建數據驅動的 web 界面的漸進式框架,是一個JavaScript MVVM庫。Vue.js 的目標是通過盡可能簡單的 API 實現響應的數據綁定和組合的視圖組件。
與其他重量級框架不同的是,Vue 採用自底向上增量開發的設計。Vue 的核心庫只關注視圖層,並且非常容易學習,非常容易與其它庫或已有項目整合。另一方面,Vue 完全有能力驅動採用單文件組件和Vue生態系統支持的庫開發的復雜單頁應用。