摘要:事件總線事件總線首先創建了一個名為的空的實例然后全局定義了組件最后創建了實例。在父組件模板中,子組件標簽上使用指定一個名稱,并在父組件內通過來訪問指定名稱的子組件。
學習筆記:組件詳解組件詳解 組件與復用
Vue組件需要注冊后才可以使用。注冊有全局注冊和局部注冊兩種方式。
全局注冊
Vue.component("my-component", {});
要在父實例中使用這個組件,必須要在實例創建前注冊,之后就可以用
Vue.component("my-component", { template: `這是一個組件` });
template的DOM結構必須被一個元素包含,缺少會無法渲染并報錯。
在Vue實例中,使用components選項可以局部注冊組件,注冊后的組件只在該實例作用域下有效。
組件中也可以使用components選項來注冊組件,使組件可以嵌套。
var Child = { template: `局部注冊組件的內容` }; new Vue({ el: "#app", components: { "my-component": Child }, });
Vue組件的模板在某些情況下會受到HTML的限制,比如 常見的限制元素還有 除了template選項外,組件中還可以像Vue實例那樣使用其他的選項,比如data、computed、methods等。 但是在使用data時,data必須是函數,然后將數據return出去。 JavaScript對象是引用關系,如果return的對象引用了外部的一個對象,那這個對象就是共享的,任何一方修改都會同步。 組件不僅要把模板的內容進行復用,更重要的是組件間進行通信。 通常父組件的模板中包含子組件,父組件要正向地向子組件傳遞數據或參數,子組件接收后根據參數的不同渲染不同的內容或者執行操作。這個正向傳遞數據的過程通過props來實現。 在組件中,使用選項props聲明需要從父級接收的數據,props的值可以是兩種,一種是字符串數組,一種是對象。 props中聲明的數據與組件data函數中return的數據主要區別就是props的數據來自父級,而data中的是組件自己的數據,作用域是組件本身,這兩種數據都可以在模板template及計算屬性computed和方法methods中使用。 由于HTML特性不區分大小寫,當使用DOM模板時,駝峰命名的props名稱要轉為短橫線分割命名。 有時候,傳遞的數據并不是直接寫死,而是來自父級的動態數據,這時可以使用指令v-bind動態綁定props的值,當父組件的數據變化時,也會傳遞子組件。 這里用v-model綁定了父級的數據parentMessage,當通過輸入框任意輸入時,子組件接收到的props["message"]也會實時響應,并更新組件模板。 業務中會經常遇到兩種需要改變prop的情況,一種是父組件傳遞初始值進來,子組件將它作為初始值保存起來,在自己的作用域下可以隨意使用和修改。這種情況可以在組件data內再聲明一個數據,引用父組件的prop。 組件中聲明了數據count,它在組件初始化時會獲取來自父組件的initCount,之后就與之無關了,只用維護count,這樣就可以避免直接操作initCount。 另一種情況就是prop作為需要被轉變的原始值傳入,這種情況用計算屬性就可以。 因為用CSS傳遞寬度要帶單位(px),數值計算一般不帶單位,所以統一在組件內使用計算屬性。 當prop需要驗證時,需要對象寫法。 一般當組件需要提供給別人使用時,推薦都進行數據驗證。比如某個數據必須是數字類型,如果傳入字符串,就會在控制臺彈出警告。 See the Pen prop by whjin (@whjin) on CodePen. 在改變組件的data "counter"后,通過$emit()再把它傳遞給父組件,父組件用@increase和@reduce。$emit()方法的第一個參數是自定義事件的名稱。 除了用v-on在組件上監聽自定義事件外,也可以監聽DOM事件,這時可以用.native修飾符表示監聽時一個原生事件,監聽的是該組件的根元素。 Vue可以在自定義組件上使用v-model指令。 組件$emit()的事件名時特殊的input,在使用組件的父級,并沒有在 v-model還可以用來創建自定義的表單輸入組件,進行數據雙向綁定。 See the Pen v-model雙向綁定 by whjin (@whjin) on CodePen. $broadcast()是由上級向下級廣播事件,用法完全一致,方向相反。 這兩種方法一旦發出事件后,任何組件都可以接收到,就近原則,而且會在第一次接收到后停止冒泡,除非返回true。 這些方法在Vue 2.x版本中已廢棄。 在Vue 2.x中,推薦任何一個空的Vue實例作為中央事件總線(bus),也就是一個中介。 See the Pen Vue-bus事件總線 by whjin (@whjin) on CodePen. 在父組件模板中,子組件標簽上使用ref指定一個名稱,并在父組件內通過this.$refs來訪問指定名稱的子組件。 Vue 2.x將v-el和v-ref合并成ref,Vue會自動去判斷是普通標簽還是組件。 當需要讓組件組合使用,混合父組件的內容與子組件的模板時,就會用到slot,這個過程叫做內容分發。
props傳遞數據、events觸發事件和slot內容分發就構成了Vue組件的3個API來源,再復雜的組件也是由這3部分構成。 父組件中的模板: 這里的message就是一個slot,但是它綁定的是父組件的數據,而不是組件 父組件模板的內容是在父組件作用域內編譯,子組件模板的內容是在子組件作用域內編譯。 這里的狀態showChild綁定的是父組件的數據。 在子組件上綁定數據: 因此,slot分發的內容,作用域是在父組件上。 在子組件內使用特殊的 分發的內容 更多分發的內容 如果沒有父組件插入內容,我將作為默認出現。 子組件child-component的模板內定義了一個 作為默認的內容,在父組件沒有使用slot時,會渲染這段默認的文本;如果寫入了slot,就會替換整個 給 See the Pen Vue-slot by whjin (@whjin) on CodePen. 通過$slots可以訪問某個具名slot,this.$slots.default包括了所有沒有被包含在具名slot中的節點。 給組件設置name選項,組件在它的模板內可以遞歸地調用自己。 組件遞歸使用可以用來開發一些具有未知層級關機的獨立組件,比如級聯選擇器和樹形控件等。 組件的模板一般都是在template選項內定義的,Vue提供了一個內聯模板的功能,在使用組件時,給組件標簽使用inline-template特性,組件就會把它的內容當做模板,而不是把它當內容分發,這讓模板更靈活。 See the Pen Vue-inline-template by whjin (@whjin) on CodePen. 可以直接綁定在組件對象上: Welcome home! Vue.js允許將組件定義為一個工廠函數,動態地解析組件。 Vue.js只在組件需要渲染時觸發工廠函數,并且把結果緩存起來,用于后面的再次渲染。 工廠函數接收一個resolve回調,在收到從服務器下載的組件定義時調用。也可以調用reject(reason)指示加載失敗。 異步更新隊列 Vue在觀察到數據變化時并不是直接更新DOM,而是開啟一個隊列,并緩沖在同一個事件循環中發生的所有數據變化。在緩沖時會去除重復數據,從而避免不必要的計算和DOM操作。然后,在一下個事件循環tick中,Vue刷新隊列并執行實際(已去重的)工作。 Vue會根據當前瀏覽器環境優先使用原生的Promise.then和MutationObserver,如果都不支持,就會采用setTimeout代替。 $nextTick就是用來確定什么時候DOM更新已經完成。 See the Pen Vue-$nextTick by whjin (@whjin) on CodePen. 在一些非常特殊的情況下,需要動態地創建Vue實例,Vue提供了Vue.extend和$mount兩個方法來手動掛載一個實例。 Vue.extend是基礎Vue構造器,創建一個“子類”,參數是一個包含組件選項的對象。 如果Vue實例在實例化時沒有收到el選項,它就處于“未掛載”狀態,沒有關聯的DOM元素。可以使用$mount手動地掛載一個未掛載的實例。這個方法返回實例自身,因而可以鏈式調用其他實例方法。 See the Pen Vue-$mount by whjin (@whjin) on CodePen.內規定只允許是
、 、 等這些表格元素,所以在 內直接使用組件時無效的。這種情況下,可以使用特殊的is屬性來掛載組件。
、
、。
在JavaScript中對象和數組時引用類型,指向同一個內存空間,所以props是對象和數組時,在子組件內改變是會影響父組件。
數組驗證
使用v-model
$refs只在組件渲染完成后才填充,并且它是非響應式的。它僅僅作為一個直接訪問子組件的應急方案,應當避免在模板或計算屬性中使用$refs。
子組件
具名Slot
異步組件
Vue.component("my-component", {
template: `#my-component`,
});
var app = new Vue({
el: "#app",
});
手動掛載實例