VUE2中文文檔:組件基礎篇
組件基礎
組件(component),是具有 name 名稱的可復用 Vue 實例:當前示例中是 <button-counter>
。我們可以使用 new Vue
創建出一個 Vue 根實例,然後將這個組件作為其中的一個自定義元素(custom element)。
由於組件是可復用的 Vue 實例,它們接收的選項,和在 new Vue
時候的選項相同,例如 data
, computed
, watch
, methods
和生命周期鉤子。唯一的例外是,類似 el
這樣,根實例上特有(root-specific)的選項。
data
必須是一個函數
組件的 data
選項必須是一個函數,以便每個實例都可以維護「函數返回的數據對象」的彼此獨立的數據副本,
如果 Vue 沒有遵循這個規定,點擊其中一個按鈕,會影響其他所有用到此 data 的組件實例,
組件註冊有兩種方式:全局註冊和局部註冊。
全局方式註冊的組件,可以用於之後創建的所有(通過 new Vue
創建的)Vue 根實例,以及 Vue 實例組件樹中所有子組件的內部。
使用 props 向子組件傳遞數據
new Vue({ el: ‘#blog-post-demo‘, data: { posts: [ { id: 1, title: ‘我的 Vue 旅程‘ }, { id: 2, title: ‘用 Vue 寫博客‘ }, { id: 3, title: ‘Vue 如此有趣‘ }, ] } })<blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title" ></blog-post>
Vue.component(‘blog-post‘, { props: [‘title‘], template: ‘<h3>{{ title }}</h3>‘ })
使用 events 向父組件發送消息
new Vue({ el: ‘#blog-posts-events-demo‘, data: { posts: [/* ... */], postFontSize: 1 //定義一個對象用作字體大小} }) <div id="blog-posts-events-demo"> <div :style="{ fontSize: postFontSize + ‘em‘ }"> //將style屬性動態的綁定起來,一旦數據傳入可以及時更新 <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:post="post" v-on:enlarge-text="postFontSize += 0.1" //監聽enlarge-text事件,觸發則執行。 ></blog-post> </div> </div>
Vue.component(‘blog-post‘, { props: [‘post‘], template: ` <div class="blog-post"> <h3>{{ post.title }}</h3> <button v-on:click="$emit(‘enlarge-text‘)> //添加點擊事件,並且將此事件返回給父組件的enlarge-text事件 放大文本 </button> <div v-html="post.content"></div> </div> ` })
在 event 事件中發送一個值
有時,想在 event 事件中發送一個特定的值。例如,我們可能想要在 <blog-post>
組件自身內部,去控制放大文本字號的間隔。在這種情況下,我們可以使用 $emit
的第二個參數來提供字號間隔值:
<button v-on:click="$emit(‘enlarge-text‘, 0.1)"> 放大文本 </button> <blog-post ... v-on:enlarge-text="postFontSize += $event" //此時$event就是傳入的值0.1 ></blog-post>
或者,如果事件處理函數是一個方法:
<blog-post ... v-on:enlarge-text="onEnlargeText" ></blog-post> methods: { onEnlargeText: function (enlargeAmount) { //此時$event傳入的值會作為方法的第一個參數,這裏是enlargeAmount this.postFontSize += enlargeAmount } }
在組件中使用 v-model
自定義事件(custom event),還可以用來創建出「實現 v-model
機制的自定義輸入框(custom input)」
<input v-model="searchText">
等同於如下: //完全意義上的等同 <input v-bind:value="searchText" //綁定value和searchText的值(即隨著searchText實時更新value) v-on:input="searchText = $event.target.value" //將value值賦值給searchText > //以上便實現了searchText和value的雙向綁定
而用於一個組件時,也是如此。
為了組件內部能夠有效運行,組件內的 <input>
必須:
- 將
value
屬性綁定到value
prop - 在
input
輸入框中,在自定義的input
事件中,發送一個新的值
這裏就是上面所描述的:
Vue.component(‘custom-input‘, { props: [‘value‘], //2.接受父組件傳遞的value值 template: ` <input v-bind:value="value" //3.將收到的value賦值給input框的value v-on:input="$emit(‘input‘, $event.target.value) //4.監聽input,並向父組件返回名為input的事件以及當前DOM的value > ` })
<custom-input v-bind:value="searchText" //1.將searchText綁定到value v-on:input="searchText = $event" //5.接受子組件觸發input,將子組件傳遞的value賦值給searchText ></custom-input>
//以上五點即有效實現了子組件和父組件完全復刻,也就是說v-modle在父組件也可以用了
所以,父組件用更簡潔的形式替代如下。
<custom-input v-model="searchText"></custom-input>
使用 slots 進行內容分發
通過 Vue 的 <slot>
自定義元素,可以非常簡單的實現這個任務:
Vue.component(‘alert-box‘, { template: ` <div class="demo-alert-box"> <strong>Error!</strong> <slot></slot> </div> ` }) <alert-box> 發生一些錯誤。 </alert-box>
會被渲染為如下結果:
動態組件
通過向 Vue 的 <component>
元素傳入 is
特性,
<!-- Component changes when currentTabComponent changes --> <component v-bind:is="currentTabComponent"></component>
通過改變:is的值就可以改變組件的選擇。 //話說這難道不是vue-router?
DOM 模板解析註意事項
有些 HTML 元素,例如 <ul>
, <ol>
, <table>
和 <select>
這些元素,會對於出現在其內部的元素有所限制;而另一些 HTML 元素,例如 <li>
, <tr>
和 <option>
這些元素,只可以出現在前面那些元素的內部。
由於這種 HTML 運行機制,在這些受限制的元素內部使用組件,會導致一些問題。
自定義組件 <blog-post-row>
會被當作無效內容,提升到 table 元素之外,從而導致最終渲染輸出後的錯誤。幸運的是,is
特性提供了一種解決方案:
<table> <tr is="blog-post-row"></tr> </table>
應當註意,在使用以下字符串模板之一的場景中,這些限制將不再適用:
- 字符串模板(例如
template: ‘...‘
) - 單文件 (
.vue
) 組件 <script type="text/x-template">
VUE2中文文檔:組件基礎篇