天天看點

VUE 入門基礎(8)

十,元件

 使用元件

  注冊

    可以通過以下這種方式建立一個Vue執行個體

      new Vue({

         el: '#some-element',

      })

    注冊一個全局元件,你可以使用Vue.component(tagName,options)

      Vue.component('my-component',{  })

     在父執行個體的子產品中以自定義元素 <my-component></my-component> 的形式使用

    <div id="example">
				      <my-component></my-component>
			    </div>
			   // 注冊
			    Vue.component('my-component', { 
				      template: '<div>A custom component!</div>'
			    })
			   // 建立根執行個體
			    new Vue({ 
				      el:'#example'
			    })
			 渲染為
			    <div id="example">
				      <div>A custom component!</div>
			    </div>           

複制

 局部注冊

  使用元件執行個體選項注冊,可以使元件僅在另一個執行個體/元件的作用域中可用

   var Child = { 
			     template:'<div>A custom component !</div>'
		  }
		  new Vue({ 
			    components: { 
				      'my-component':Child
			    }
		  })           

複制

  data 必須是函數

    使用元件時,大多數選項可以被傳入到Vue 構造器中,有一個列外,data 必須是函數。

      Vue.component('my-component', { 
			        template: '<span> {{ message}}</span>',
			        data: { 
				          message:  'hello'
			        }
		    })           

複制

  Vue 會在控制台發出警告,告訴你在元件中 data 必須是一個函數

    var data = { counter:0}
		    Vue.component('simple-counter', { 
			    template: '<button v-on:click="counter += 1">{{ counter }}</button>',
			      data: function () { 
				        return data
			        }
		    })
		    new Vue({ 
			      el: '#example-2'
		    })           

複制

    三個元件共享了同一個 data

      data: function() { 
			        retrun { 
				          counter: 0
			        }
		      }           

複制

  構成元件

    Prop

      使用Prop傳遞資料,元件的作用域是孤立的,意味着不能并且不應該再子元件的

      模闆内引用父元件的資料,可以使用props 把資料傳給子元件。

    prop 是父元件用來傳遞資料的一個自定義屬性,子元件需要顯示的用props

      Vue.component('child', { 
				          // 聲明 props
				        props: ['message'],
				          // 像 data 一樣 prop 可以用在模闆内
				          // 同樣也可以在 vm 執行個體中像 “this.message”這樣使用
				        templae: '<span>{{ message }}</span>'
			    })           

複制

    然後向它傳入一個普通字元串:

      <child message="hello!"></child>

    結果:

      hello!

  camelCase vs.kebab-case

    HTML 特性不區分大小寫 當使用非字元串模闆的時,prop 的名字形式會從camelCase 轉為

      kebab-case(短橫線隔開)

        Vue.component('child', { 
				          props:['myMessage'],
				            template: '<span>{{ myMessage}}</span>'
			        })
			      <child my-message="hello"></child>           

複制

  動态Prop

      類似用于v-bind 綁定 HTML 特性到一個表達式,也可以用v-bind 動态綁定props的值

      到父元件的資料中。沒當父元件的資料變化時,該變化也會傳導給子元件。

      <div>
				        <input v-model="paremtMsg">
				        <child v-bind:my-message="parentMsg"></child>
			      </div>           

複制

      使用 v-bind 的縮寫文法統稱更簡單。

        <child :my-message="parentMsg"></child>

      字面量文法 vs 動态文法

        // 實際傳遞參數

      <comp v-bind:some-prop="1"></comp>

 單向資料流

    1.prop 作為初始值傳入,子元件之後隻是将它的初始值作為本地資料的初始值使用;

    2.prop 作為需要被轉變的原始值傳入。

    定義一個局部的 data 屬性 ,并将prop 的初始值作為局部資料的初始值。

    props:['initialCounter'],

      data: function () {

        return { counter: this.initialCounter}

    }

    定義一個computed 屬性。此屬性從prop 的值計算出來。

    props:['size'],
			      computed: { 
				        normalizedSize: function() { 
					        return this.size.trim().toLowerCase()
				      }
			    }           

複制

  Prop 驗證

    元件也可以為props指定驗證請求,prop 是一個對象而不是字元串數組時,它包含驗證要求:

      Vue.component('example', { 
				        props: { 
					             // 基礎類型檢測 (`null` 意思是任何類型都可以)
					              propA: Number,
					                // 多種類型
					              propB: [String, Number],
					                // 必傳且是字元串
					              propC: {
					                  type: String,
					                  required: true
					            },
					          // 數字,有預設值
					         propD: {
       type: Number,
					            default: 100
					          },
					            propE: {
					            type: Object,
					            default: function () {
					              return { message: 'hello' }
					            }
					        },
					        // 自定義驗證函數
					        propF: {
					            validator: function (value) {
					                  return value > 10
					              }
					            }
				      }
			    })           

複制

 自定義事件

    子元件需要把資料傳回父元件,需要自定義事件。

    使用v-on 綁定自定義事件。

    使用 $on(eventName) 監聽事件

    使用 $emit(eventName) 觸發事件

    給元件綁定原生事件

    可以使用 .native 修飾 v-on

      <my-component v-on:click.native="doTheThing"></my-component>

    使用自定義元件的表單輸入元件

    自定義事件也可以用來建立自定義的表單輸入元件,使用 v-model 來進行資料雙向綁定。

      <input v-model="something">

  非父子元件通信

    有時候非父子關系的元件也需要通信,在簡單的場景下,使用個空的Vue 執行個體作為中央事件總線。

        var bus = new Vue()
		      // 觸發元件 A 中的事件
		        bus.$emit('id-selected', 1)
		      // 在元件 B 建立的鈎子中監聽事件
		        bus.$on('id-selected', function(id) { 
			      //...
		    })           

複制

  使用Slot 分發内容

    在使用元件的時候,我們常常遇到這樣組合。

    <app>
			      <app-header></app-header>
			      <app-footer></app-footer>
		    </app>           

複制

    注意兩點:

    1.<app> 元件不知道它的挂載點有什麼内容,挂載點的内容是由<app>的父元件決定的

    2.元件很有可能有它自己的模闆。

    分發内容是在父元件作用域内編譯。

  單個Slot

    除非子元件模闆至少包含一個<slot>插口, 否則父元件的内容将會被丢棄。當子模闆隻有

    一個沒有屬性的Slot 時,父元件整個内容片斷将插入到slot 所在的DOM位置,并沒替換掉

  slot 标簽本身。

      假定 my-component 元件有下面模闆:

    <div>
					      <h2>我是子元件的标題</h2>
					      <slot>
						        隻有在沒有要分發的内容時才會顯示。
					      </slot>
				    </div>	           

複制

    父元件模版:

   <div>
					      <h1>我是父元件的标題</h1>
					       <my-component>
    						        <p>這是一些初始内容</p>
    						        <p>這是更多的初始内容</p>
  					      </my-component>
				  </div>           

複制

  渲染結果:

    <div>
  					      <h1>我是父元件的标題</h1>
  					    <div>
    						      <h2>我是子元件的标題</h2>
    						      <p>這是一些初始内容</p>
    						      <p>這是更多的初始内容</p>
  					    </div>
				    </div>           

複制

   具名 Slot

    <slot> 元素可以用一個特殊的屬性 neme 來配置如何分發内容。多個slot 可以有不同的名字,具名solt 将比對的内容片段中有對應的slot 特殊的元素

    仍然可以有個匿名slot,它是預設slot, 作為找不到比對的内容片斷的備用插槽。如果沒有預設的slot 這個找不到比對的内容将會被丢棄。

    例如,假定我們有一個 app-layout 元件,它的模闆為:

    <div class="container">
				      <header>
					        <slot name="header"></slot>
				      </header>
				      <main>
					        <slot></slot>
				      </main>
				      <footer>
					        <slot name="footer"></slot>
				      </footer>
			    </div>           

複制

    父元件模版:

      <app-layout>
				        <h1 slot="header">這裡可能是一個頁面标題</h1>
				        <p>主要内容的一個段落。</p>
				        <p>另一個主要段落。</p>
  				        <p slot="footer">這裡有一些聯系資訊</p
			      </app>           

複制

    渲染結果為:

      <div class="container">
			  	        <header>
			   		           <h1>這裡可能是一個頁面标題</h1>
			  	        </header>
			  	        <main>
			    		          <p>主要内容的一個段落。</p>
			    		          <p>另一個主要段落。</p>
			  	        </main>
			  	        <footer>
			    		          <p>這裡有一些聯系資訊</p>
			  	        </footer>
			      </div>           

複制

 動态元件

    多個元件可以使用同一個挂載點,然後動态地在它們之間切換。使用保留的 <component> 元素,動态地綁定到它的 is 特性:

      var vm = new Vue({
  				        el: '#example',
				          data: {
    					            currentView: 'home'
  				          },
 				         components: {
  					              home: { /* ... */ },
    					              posts: { /* ... */ },
    					            archive: { /* ... */ }
 				       }
			    })
			    <component v-bind:is="currentView">
  				      <!-- 元件在 vm.currentview 變化時改變! -->
			    </component>
			        也可以直接綁定到元件對象上:
			    var Home = {
 				       template: '<p>Welcome home!</p>'
				    }
			    var vm = new Vue({
  				      el: '#example',
  				      data: {
    					        currentView: Home
  				        }
			    })           

複制

     #keep-alive

    如果把切換出來的的元件保留在記憶體中,可以保留它的狀态或避免重新渲染。

      <keep-alive>
					        <component  :is="currentView">
						          // 非活動元件将被緩存 
					        </component>
				      </keep-alive>           

複制

 雜項

  編寫可複用元件

  可複用元件應當定義一個清晰的公開接口。

    Vue 元件的 API 來自三部分 - props, events 和 slots :

    Props 允許外部環境傳遞資料額給元件。

    Events 允許元件觸發外部環境的副作用。

    Slots 允許外部環境将額外的内容組合在元件中。

    使用 v-bind 和 v-on 的簡寫文法,模闆的縮進清楚且簡潔:

        <my-component
			          :foo = "baz"
			          :bar = "qux"
			          @event-a ="doThis"
			          @event-b="doThat"
			        >
				        <img slot="icon" src="...">
				        <p slot="main-text"></p>
			       </my-component>           

複制

   #子元件索引

      可以使用ref 為子元件指定一個索引ID 例如:

      <div id="parent">
				        <user-profile ref="profile"></user-profile>
			      </div>	
			      var parent = new Vue({ 
				          el: '#parent'
			      })
			      // 通路子元件
			      var child = parent.$refs.profile           

複制

      當 ref 和 v-for 一起使用時, ref 是一個數組或對象,包含相應的子元件