1.註冊組件就是利用Vue.component()方法
2.能夠理解爲一個vue文件就是一個組件html
組件的模板中只能有一個根元素vue
var app = new Vue({ data () { return { message: 'hello world' } } })
例,一個父組件:數組
<my-component v-bind:foo="baz" v-on:event-a="doThis(arg1,...arg2)"></my-component>
上面代碼app
foo
是<my-component>
組件內部定義的一個prop
屬性,baz
是父組件的一個data屬性,event-a
是子組件定義的一個事件,doThis
是父組件的一個方法執行過程應該是這樣的:函數
baz
數據經過prop
傳遞給子組件的foo
;foo
的值,就能夠進行相應的操做;event-a
事件,把一些數據發送出去doThis
方法,子組件發送的數據,就做爲doThis
方法的參數被傳進來Vue組件經過props
屬性來聲明一個本身的屬性,而後父組件就能夠往裏面傳遞數據。ui
Vue.component('mycomponent',{ template: '<div>這是一個自定義組件,父組件傳給個人內容是:{{myMessage}}</div>', props: ['myMessage'], data () { return { message: 'hello world' } } })
而後調用該組件this
<div id="app"> <mycomponent my-message="hello"></mycomponent> </div>
注意,因爲HTML特性是不區分大小寫的,因此傳遞屬性值時,myMessage
應該轉換成 kebab-case (短橫線隔開式)my-message="hello"
。spa
<div attr="message">hello</div>
上面這樣,div
元素的attr
特性值就是message
。而這樣雙向綁定
<div v-bind:attr="message">hello</div>
這裏的message
應該是Vue實例的data的一個屬性,這樣div
元素的attr
特性值就是message
這個屬性的值。
之因此說是通常狀況,是由於class
和style
特性並非這樣。用v-bind:class
和class
傳入正常的類名,效果是同樣的,由於對於這兩個特性,Vue採用了合併而不是替換的原則。code
根據上面,想要把父組件的屬性綁定到子組件,應該使用v-bind
,這樣,父組件中數據改變時能反映到子組件。
注意 在子組件中最好不要更改父組件傳入的值,若是非要更改的話,加上.sync
修飾符
例父組件
<my-component :child-array.sync="parentArray"></my-component>
子組件
methods: { changeArray () { this.counter++ this.$emit('update:childArray', this.counter) } }
一樣是上面的緣由,靜態的給子組件的特性傳遞值,它都會把他當作一個字符串。
<!-- 傳遞了一個字符串 "1" --> <comp some-prop="1"></comp>
子組件中,特性的值是字符串 "1" 而不是 number 1。若是想傳遞正確的數值,應該使用v-bind傳遞,這樣就能把傳遞的值當作一個表達式來處理,而不是字符串。
<!-- 傳遞實際的 number 1 --> <comp v-bind:some-prop="1"></comp>
咱們能夠給組件的props
屬性添加驗證,當傳入的數據不符合要求時,Vue會發出警告。
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 } } } })
type
能夠是下面原生構造器:
type
也能夠是一個自定義構造器函數
經過prop屬性,父組件能夠向子組件傳遞數據,而自定義事件就是用來將子組件的內部數據報告給父組件的。
例
<div id="app3"> <my-component2 v-on:myclick="onClick"></my-component2> </div> <script> Vue.component('my-component2', { template: `<div> <button type="button" @click="childClick">點擊我觸發自定義事件</button> </div>`, methods: { childClick () { this.$emit('myclick', '這是我暴露出去的數據', '這是我暴露出去的數據2') } } }) new Vue({ el: '#app3', methods: { onClick () { console.log(arguments) } } }) </script>
如上所示,共分爲如下步驟:
子組件在本身的方法中將自定義事件以及須要發出的數據經過如下代碼發送出去
this.$emit('myclick', '這是我暴露出去的數據', '這是我暴露出去的數據2')
第一個參數是自定義事件的名字 後面的參數是依次想要發送出去的數據
父組件利用v-on
爲事件綁定處理器
<my-component2 v-on:myclick="onClick"></my-component2>
這樣,在Vue實例的methods
方法中就能夠調用傳進來的參數了
注意: 在使用v-on
綁定事件處理方法時,不該該傳進任何參數,而是直接寫v-on:myclick="onClick"
,否則,子組件暴露出來的數據就沒法獲取到了
若是想在某個組件的根元素上監聽一個原生事件。可使用 .native
修飾 v-on
v-model
v-model
能夠對錶單控件實現數據的雙向綁定,它的原理就是利用了綁定屬性和事件來實現的。好比input
控件。不使用v-model
,能夠這樣實現數據的雙向綁定:
<div id="app4"> <input type="text" v-bind:value="text" v-on:input="changeValue($event.target.value)"> {{text}} </div> <script> new Vue({ el: '#app4', data: { text: '444' }, methods: { changeValue (value) { this.text = value } } }) </script>
上面的代碼一樣實現了數據的雙向綁定。其本質就是:
input
的value
特性綁定到Vue實例的屬性text
上,text
改變,input
中的內容也會改變input
事件處理函數設置爲Vue實例的一個方法,這個方法會根據輸入參數改變Vue中text
的值input
中輸入內容時,觸發了input
事件,把event.target.value
傳給這個方法,最後就實現了改變綁定的數據的效果。而v-model
就是上面這種方式的語法糖,也就是把上面的寫法封裝了一下,方便咱們使用。
上面用到的不少組件的使用方式是這樣的:
<component></component>
也就是說組件中是空的,沒有放置任何文本或元素。可是原生的html元素都是能夠進行嵌套的,div
裏面放table
什麼的。自定義組件開閉標籤之間也能夠放置內容,不過須要在定義組件時使用slot
。
slot
至關於子組件設置了一個地方,若是在調用它的時候,往它的開閉標籤之間放了東西,那麼它就把這些東西放到slot
中。
子組件的模板:
<div> <h2>我是子組件的標題</h2> <slot> 只有在沒有要分發的內容時纔會顯示。 </slot> </div>
父組件模板:
<div> <h1>我是父組件的標題</h1> <my-component> <p>這是一些初始內容</p> </my-component> </div>
渲染結果:
<div> <h1>我是父組件的標題</h1> <div> <h2>我是子組件的標題</h2> <p>這是一些初始內容</p> </div> </div>
slot
能夠有不少個。那麼子組件對於父組件放置的多餘的內容如何放到各個slot
中呢?方法就是子組件給每一個slot
起一個名字name
,父組件放置多餘的元素時,給每一個元素的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-layout>
渲染結果爲:
<div class="container"> <header> <h1>這裏多是一個頁面標題</h1> </header> <main> <p>主要內容的一個段落。</p> <p>另外一個主要段落。</p> </main> <footer> <p>這裏有一些聯繫信息</p> </footer> </div>
做用域插槽也是一個插槽slot
,可是他能夠把數據傳遞給到父組件的特定元素內,而後有父組件決定如何渲染這些數據。
首先,子組件的slot
須要有一些特性(prop)
Vue.component('my-component4', { template: `<div> <slot :text="hello" message="world"></slot> </div>`, data () { return { hello: [1,'2'] } } })
父組件在調用子組件時,須要在裏面添加一個template
元素,而且這個template
元素具備scope
特性
<div id="app7"> <my-component4> <template scope="props"> </template> </my-component4> </div>
scope
特性的值,就表明了全部子組件傳過來的數據組成的對象。至關於
props = { text: '', message: '' }
最後,父組件就能夠在template
中渲染子組件傳過來的數據了
<div id="app7"> <my-component4> <template slot-scope="props"> <span>{{props.text}}</span> <span>{{props.message}}</span> </template> </my-component4> </div>
做用域插槽也是插槽,只不過是多加了些特性,而後父組件多進行了些處理。