// 定義一個名爲 button-counter 的新組件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' })
(1)組件是可複用的 Vue 實例,且帶有一個名字:在這個例子中是 <button-counter>。咱們能夠在一個經過 new Vue 建立的 Vue 根實例中,把這個組件做爲自定義元素來使用javascript
<div id="components-demo"> <button-counter></button-counter> </div>
new Vue({ el: '#components-demo' })
(2)由於組件是可複用的 Vue 實例,因此它們與 new Vue 接收相同的選項,例如 data、computed、watch、methods 以及生命週期鉤子等。僅有的例外是像 el 這樣根實例特有的選項。html
(1)你能夠將組件進行任意次數的複用。java
<div id="components-demo"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> </div>
(2)注意當點擊按鈕時,每一個組件都會各自獨立維護它的 count。由於你每用一次組件,就會有一個它的新實例被建立。git
(1)當咱們定義這個 <button-counter> 組件時,你可能會發現它的 data 並非像這樣直接提供一個對象。github
data: { count: 0 }
(2)取而代之的是,一個組件的 data 選項必須是一個函數,所以每一個實例能夠維護一份被返回對象的獨立的拷貝。web
data: function () { return { count: 0 } }
(3)若是 Vue 沒有這條規則,點擊一個按鈕就可能會像以下代碼同樣影響到其它全部實例。segmentfault
(1)在 Vue 項目中使用組件,目的通常就是 提升代碼複用率,加強模塊化,從而下降開發成本。app
(2)咱們在 Vue 中使用組合組件,也就是A組件中包含了B組件。而組件與組件之間的相互使用避免不了數據之間的傳遞。那麼 Vue 中組件的數據是如何傳遞的呢?模塊化
(1)首先要說明,組件數據傳遞不一樣於Vue全局的數據傳遞,組件實例的數據做用域是孤立的。函數
(2)這裏的孤立並不只僅在組件內獨立,並且是指上下層之間的數據隔離,即不能在子組件的模板內直接引用父組件的數據。若是要把數據從父組件傳遞到子組件,就須要使用props屬性。這是父組件用來傳遞數據的一個自定義屬性。
(1)在Vue的官方文檔中提到,在Vue中,父子組件的關係 【prop向下傳遞,事件向上傳遞】。父組件經過prop給子組件下發數據,子組件經過事件給父組件發送消息。
(1)常把這種數據流稱之爲單向數據流。prop是單向綁定的,當父組件的屬性變化時,將傳給子組件,可是反過來不會。這是爲了防止子組件無心間修改了父組件的狀態,來避免應用的數據流變得難以理解。
(2)另外,每次父組件更新時,子組件的全部prop都會更新爲最新值。這意味着你不該該在子組件內部改變prop。若是你這麼作了,Vue會在控制檯給出警告。
(1)首先來建立一個子組件child,而且在Vue的實例中定義了data選項。
let parent = new Vue ({ el:"#app", data () { return { name: 'WEBING', job: 'front-end-development' } }, components: { 'child': { template: '#child', props: ['myName','myJob'] } } });
(2)這裏直接把Vue實例 parent 看成組件child的父組件。若是咱們想要使用父組件的數據,則必須先在子組件中定義props,即:props:['myName', 'myJob']。
(3)接下來定義child組件的模板。
<template id="child"> <div class="child"> <h3>子組件child數據</h3> <ul> <li> <label>姓名</label> <span>{{ myName }}</span> </li> <li> <label>工做</label> <span>{{ myJob }}</span> </li> </ul> </div> </template>
(4)將父組件parent的data經過已定義好的props屬性傳遞給子組件。
<div id="app"> <child :my-name="name" :my-job="job"></child> </div>
(5)給上面的示例,添加CSS樣式,最終看到的效果以下。
(1)因爲HTML特性不區分大小寫,在子組件定義prop時,使用了駝峯式大小寫(camelCase)命名法。
(2)駝峯式大小寫的prop用於特性時,須要轉爲短橫線隔開(kebab-case)。例如,在prop中定義的myName,在用做特性時須要轉換爲my-name。
let parent = new Vue ({ // ... components: { 'child': { props: ['myName','myJob'] // 在 JavaScript 中是 camelCase 的 // ... } } });
<!-- 在 HTML 中是 kebab-case 的 --> <div id="app"> <child :my-name="name" :my-job="job"></child> </div>
(3)【注意】若是你使用字符串模板,那麼這個限制就不存在了。
(1)在父組件使用子組件時,經過如下語法將數據傳遞給子組件。
<child :子組件的prop="父組件數據屬性"></child>
(2)【注意】:其實至關於v-bind,也就是Vue中的v-bind指令。這是屬於動態綁定,讓它的值被看成JavaScript表達式計算。
在Vue中的prop綁定主要有① 單向綁定和② 雙向綁定(見後續文章)。
(1)咱們知道在 Vue 2.0 中組件的props的數據流動改成了單向流動;
(2)即只能由組件外(調用組件方)經過組件的DOM屬性attribute傳遞props給組件內,組件內只能被動接受組件外傳遞過來的數據,而且在組件內,不能修改由外層傳來的props數據。
<div id="app"> <div class="parent"> <h3>父組件Parent數據</h3> <ul> <li> <label>姓名</label> <span>{{ name }}</span> <input type="text" v-model="name" /> </li> <li> <label>工做</label> <span>{{ job }}</span> <input type="text" v-model="job" /> </li> </ul> </div> <child :my-name="name" :my-job="job"></child> </div> <template id="child"> <div class="child"> <h3>子組件Child數據</h3> <ul> <li> <label>姓名</label> <span>{{ myName }}</span> <input type="text" v-model="myName" /> </li> <li> <label>工做</label> <span>{{ myJob }}</span> <input type="text" v-model="myJob" /> </li> </ul> </div> </template>
let parent = new Vue({ el: '#app', data () { return { name: 'WEBING', job: 'FE' } }, components: { 'child': { template: '#child', props: ['myName', 'myJob'] } } })
(1)如下示例修改父組件中的數據。
(2)從上面修改父組件數據獲得的效果能夠告訴咱們 【修改父組件的數據將會影響子組件,子組件的數據也會對應的修改】
(3)如下示例修改子組件的數據。
(4)從效果中能夠看出 【修改子組件數據並不會影響父組件的數據】(警告信息的處理見後續文章。)
prop默認是 單向綁定 【當父組件的屬性變化時,將傳給子組件,但反過來不會。這是爲了防止子組件無心修改了父組件的狀態】