1. 程式人生 > >VUE2中文文檔:組件基礎篇

VUE2中文文檔:組件基礎篇

fonts 無效 發生 RR err cti 解決 場景 賦值

組件基礎

組件(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中文文檔:組件基礎篇