本篇資料來於官方文檔:vue
http://cn.vuejs.org/guide/components.html
java
本文是在官方文檔的基礎上,更加細緻的說明,代碼更多更全。app
簡單來講,更適合新手閱讀ide
(二十五)組件的定義函數
①組件的做用:
【1】擴展HTML元素,封裝可重用的代碼;ui
【2】組件是自定義元素,Vuejs的編譯器能夠爲其添加特殊的功能;this
【3】某些狀況下,組件能夠是原生HTML元素的形式,以is的方式擴展。spa
②寫一個標準的組件:
分爲如下幾步:
【1】掛載組件的地方,須要是Vue實例所渲染的html元素,具體來講,好比上面的<div id=」app」></div>這樣的html元素及他的子節點;
【2】定義一個組件,用
var 變量名 = Vue.extend({template:」這裏是html的模板內容」})
這樣的形式建立,例如:
- var btn = Vue.extend({
- template: "<button>這是一個按鈕</button>"
- })
【3】將定義的組件註冊到Vue實例上,這會讓指定標籤,被組件的內容所替代。
如代碼:
- Vue.component("add-button", btn);
具體而言,每個如下這樣的標籤(在Vue的根實例範圍內的)
- <add-button></add-button>
會被
所替代。
【4】以上方法是全局註冊(每一個Vue實例的add-button標籤都會被咱們定義的所替代);
解決辦法是局部註冊。
如代碼:(這是是設置了template屬性,也能夠在沒有這個屬性的時候,在<div id=」app」></div>標籤內放置<add-button></add-button>標籤
- <div id="app">
- </div>
- <script>
- //定義一個組件
- var btn = Vue.extend({
- template: "<button>這是一個按鈕</button>"
- })
-
- Vue.component("add-button", btn);
-
- //建立根實例,也就是說讓Vue對這個根生效
- var vm = new Vue({
- el: '#app',
- template: "<add-button></add-button>"
- });
- </script>
③局部註冊組件:
簡單來講,只對這一個Vue實例生效,具體作法是,在註冊那一步,跳過;
而後在聲明Vue實例的時候,將添加到components這個屬性中(他是一個對象,以KV形式放置)(注意,這個單詞多一個s)
如代碼:
- <div id="app">
- </div>
- <script>
- //定義一個組件
- var btn = Vue.extend({
- template: "<button>這是一個按鈕</button>"
- })
-
- //建立根實例,也就是說讓Vue對這個根生效
- var vm = new Vue({
- el: '#app',
- template: "<add-button></add-button>",
- components: {
- "add-button": btn
- }
- });
- </script>
注:
根據官方教程,這種方法(指局部註冊),也適用於其餘資源,好比指令、過濾器和過渡。
④步驟簡化:
【1】定義組件和註冊組件結合起來一步完成:
- Vue.component("add-button", {
- template: "<button>這是一個按鈕</button>"
- });
【2】局部註冊時,定義和註冊一步完成:
- var vm = new Vue({
- el: '#app',
- template: "<add-button></add-button>",
- components: {
- "add-button": {
- template: "<button>這是一個按鈕</button>"
- }
- }
- });
⑤data屬性
直接給組件添加data屬性是不能夠的(無效);
緣由在於,假如這麼幹,那麼組件的data屬性有多是一個對象,而這個對象也有多是外部傳入的(例如先聲明一個對象,而後這個對象做爲data的值),可能致使這個組件的全部副本,都共享一個對象(那個外部傳入的),這顯然是不對的。
所以,data屬性應該是一個函數,而後有一個返回值,這個返回值做爲data屬性的值。
且這個返回值應該是一個全新的對象(即深度複製的,避免多個組件共享一個對象);
如代碼:
- var vm = new Vue({
- el: '#app',
- template: "<add-button></add-button>",
- components: {
- "add-button": {
- template: "<button>這是一個按鈕{{btn}}</button>",
- data: function () {
- return {btn: "123"};
- }
- }
- }
- });
另外,假如這樣的話,btn的值是同樣的(由於他們實際上仍是共享了一個對象)
- <div id="app">
- </div>
- <div id="app2">
- </div>
- <script>
- var obj = {btn: "123"};
- var vm = new Vue({
- el: '#app',
- template: "<add-button></add-button>",
- components: {
- "add-button": {
- template: "<button>這是一個按鈕{{btn}}</button>",
- data: function () {
- return obj;
- }
- }
- }
- });
-
- obj.btn = "456";
- var vm2 = new Vue({
- el: '#app2',
- template: "<add-button></add-button>",
- components: {
- "add-button": {
- template: "<button>這是一個按鈕{{btn}}</button>",
- data: function () {
- return obj;
- }
- }
- }
- });
- </script>
注:
el屬性用在Vue.extend()中時,也須是一個函數。
⑥is特性:
【1】按照官方教程,一些HTML元素對什麼元素能夠放在它之中是有限制的;
簡單來講,若是我要在table標籤內複用某個組件,這個組件展開後是tr標籤,可是展開前不是,那麼就沒法正常運行(被放置在table標籤內);
如代碼(錯誤寫法,會渲染錯誤):
- <div id="app">
- <table>
- <tr>
- <td>索引</td>
- <td>ID</td>
- <td>說明</td>
- </tr>
- <thetr v-for="i in items" v-bind:id="i" :index="$index"></thetr>
- </table>
- </div>
- <script>
- var vm = new Vue({
- el: '#app',
- data: {
- items: [1, 2, 3, 4]
- },
- methods: {
- toknowchildren: function () { //切換組件顯示
- console.log(this.$children);
- }
- },
- components: {
- thetr: { //第一個子組件
- template: "<tr>" +
- "<td>{{index}}</td>" +
- "<td>{{id}}</td>" +
- "<td>這裏是子組件</td>" +
- "</tr>",
- props: ['id', 'index']
- }
- }
- });
- </script>
渲染結果以下:
- <div id="app">
- <tr><td>0</td><td>1</td><td>這裏是子組件</td></tr>
- <tr><td>1</td><td>2</td><td>這裏是子組件</td></tr>
- <tr><td>2</td><td>3</td><td>這裏是子組件</td></tr>
- <tr><td>3</td><td>4</td><td>這裏是子組件</td></tr>
- <table>
- <tbody>
- <tr>
- <td>索引</td>
- <td>ID</td>
- <td>說明</td>
- </tr>
- </tbody>
- </table>
- </div>
能夠明顯發現,內容沒有被放在table之中。
正確寫法以下:
- <div id="app">
- <button @click="toknowchildren">點擊讓子組件顯示</button>
- <table>
- <tr>
- <td>索引</td>
- <td>ID</td>
- <td>說明</td>
- </tr>
- <tr is="thetr" v-for="i in items" v-bind:id="i" :index="$index"></tr>
- </table>
- </div>