iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 2
1

平時比較少用的生命週期

  • 這是一段HTML
<div id="app">{{ name }}</div>
  • 通常我們都這樣用
let vm = new Vue({
	el: '#app',
	data: {
		name: 'aka allen'
	}
})
  • 但我們看著官網的組件生命週期的這段,其實我們可以不提供 el ,當我們不提供的時候,就必須呼叫 vm.$mount(el) 讓生命週期繼續往下走判斷是否有 templateel 的部分就是 '#app' 或者自己下的其他名稱。

https://ithelp.ithome.com.tw/upload/images/20200907/20129819khk26P4tLT.jpg

  • 所以我們可以寫成這樣
let vm = new Vue({
  template: `
    <div id="replace"> 
      <span> {{ name }} </span>
    </div>
  `,
  data: {
    name: 'aka allen'
  }
})

再往下看生命週期,有 template 就會將他丟進 render 函式編譯,沒有 template ,就會抓元素的 outerHTML 來做為 template 編譯並渲染掛載,隨後回到我們平常使用 Vue 的方式。

https://ithelp.ithome.com.tw/upload/images/20200908/20129819gIhtfZWJv8.jpg

  • 所以接下來呼叫 vm.$mount(el) ( el 選擇器的部分自行替換成可辨識的 id or class 啥的 ) 就會看見內容被渲染了,並且可以發現若你有提供 template,裡面的內容是直接被替換掉的。以下是小範例,請自行琢磨。

https://codepen.io/fiftybillionHuang/pen/NWNvJKV

開始解說組件 ( Component )

全域組件 ( 我都叫他大組件 )

  • 隨便準備一份 HTML 來引入 Vue,或者隨便編輯器,其實我都直接 CodePen 啦。

  • 引入 Vue 後,使用 Vue.component 物件來對組件做全域註冊,注意註冊的動作必須在new Vue 之前完成,沒這麼做,如果是使用開發版 Vue,會顯示 unknown custom element: <name-generator> - did you register the component correctly? 的錯誤訊息。

  • 以下是全域組件的註冊方法,直接寫 Vue.component('',{}) 就是在註冊了,必須傳入組件命名及 {}形式的設定。

  • template 的部分使用了字符串模板,便於直接撰寫 HTML,而內容則是需要一個 div.class='rootDiv' 來做為根元素包覆,class 的名字是我隨便取的,只是用來表達根而已,什麼都不寫也可以,如果沒有最外層的 div ( 或其他標籤名稱也可 ) 而只有單單的 {{ name }} 將會顯示不出內容。若使用開發版 Vue,會有 Component template requires a root element 的錯誤訊息,切記,根元素只能有一個。

  • 這邊我習慣可以在加上個 name 屬性

Vue.component('name-generator', {
  name: 'NameGenerator',
  template: `
	<div class='rootDiv'>
		{{ name }}
	</div> 
  `,
  data () {
    return {
      name: 'aka allen'
    }
  }
});

// 全域組件註冊完接著才是 Vue 實例
new Vue ...

請注意,new Vue() 實例的 data 可以直接指定為一個物件,或函式返回的物件(沒有強制規定),但組件的部分則被明確規定為需要指定為 函式返回物件 的方式,請參考官網詳解 — #組件數據(必要) ,或者可參考這裡 ,經我自己實測, 如果把組件內的 data 直接寫成物件,貌似是過不了的樣子。另外,我們的 30 天組件命名將使用官網風格指南

  • 註冊完一個全域組件,就可以像這樣直接使用:
<name-generator></name-generator>
  • 接著可成功看到如此的資料顯示:

https://ithelp.ithome.com.tw/upload/images/20200908/201298192naUT8ZFbS.jpg

局部組件 ( 小組件 )

  • 有點不同的是,在註冊全域組件時,定義好其內容的同時也註冊完畢了,而小組件的註冊,則是要先定義內容,然後再將其丟進 components,若是沒正確地將其丟進,也會出現類似 did you register the component correctly? 的錯誤訊息 ...
  • 以下為局部組件註冊
let nameGeneratorHeHe = {
  name: 'NameGeneratorHeHe',
  template: `
	<div>
      {{ name }}
	</div>
  `,
  data () {
	return {
	  name: 'hehe'
	}
  }
}

new Vue({
  el: '#app',
  data: {
    title: '鐵人賽第一天 - 組件'
  },
  components: {
	nameGeneratorHeHe
  }
});
  • 如此就可以像這樣直接使用 ( 烤肉串寫法 ):
<name-generator-he-he></name-generator-he-he>
  • 現在 script 部分完整的程式碼長這樣:
<script>
    Vue.component('name-generator', {
      name: 'NameGenerator',
      template: `
        <div class='rootDiv'>
          {{ name }}
        </div> 
      `,
      data() {
        return {
          name: 'aka allen'
        }
      }
    });

    let nameGeneratorHeHe = {
      name: 'NameGeneratorHeHe',
      template: `
        <div>
          {{ name }}
        </div>
      `,
      data() {
        return {
          name: 'hehe'
        }
      }
    };

    new Vue({
      el: '#app',
      data: {
        title: '鐵人賽第一天 - 組件'
      },
      components: {
        nameGeneratorHeHe
      }
    });
</script>
  • 這是HTML部分:
<div id="app">
  <header>{{ title }}</header>
  <name-generator></name-generator>
  <name-generator-he-he></name-generator-he-he>
</div>
  • 會得到像這樣的結果:

https://ithelp.ithome.com.tw/upload/images/20200908/20129819yvLhRSU4Wk.jpg

重要 : 全域註冊的組件,仔細觀察他寫法是 Vue.component ... ,我們不去推敲源碼,但是邊依照我們對原生 JS 物件的認識,這可能是代表整個 Vue 類別被添加了這個組件的內容,因此在往後創造的所有 Vue 實例以及單文件組件 ( .vue 檔案 ) 都可以存取到這個組件,而相對的查看局部組件的寫法,是寫在某個 Vue 實例的 components 屬性中,因此在這個 Vue 實例以外範圍,是沒有辦法存取到此局部組件的,這點有機會的話在實作一個原生 JS 的例子給大家參考這個概念。

照這樣的概念我們可以知道,若是不常用的組件,通常就是作成局部的,而常用的再做成全域,比如每個頁面可能都需要某種相同的客製化按鈕,那這時你就可以使用全域註冊,就像我們的公用 CSS Class 一樣概念。

結尾補充

let a = 5;
let obj = {
	a
};

console.log(obj.a) // 印出 5

// 因為ES2015定義物件成員的名稱和值若都是相同的,就可以只寫變數名稱,所以組件的寫法也可以學上面

let nameGeneratorHeHe = ......

new Vue({
  el: '#app',
  data: {
    title: '鐵人賽第一天 - 組件'
  },
  components: {
    // nameGeneratorHeHe: nameGeneratorHeHe
	nameGeneratorHeHe
  }
});

  • 你也可以利用物件特性像這樣更換使用於HTML上的名稱
components: {
  'get-a-name': nameGeneratorHeHe
}
  • HTML
<get-a-name></get-a-name>

https://codepen.io/fiftybillionHuang/pen/RwagEqp

這裡跟大家報告一下我目前的感受,目前為止覺得怪怪的,不知道到底是要程式碼多一些,還是中文敘述多一些,感覺怎麼做都怪怪的哈哈。預計是希望用大約 3~4 篇 ( 包含今天這篇,應該吧,搞不好越講越多 XD ) 的篇幅, 可以把 Prop + Slot + Event 的特性過一遍,外加帶大家逛一下 BootstrapVue 的部分並完成一些小功能,下一篇寫組件 Prop,感謝今日收看。

沒事也可以逛逛我們其他團隊成員的文章啦 ~~

eien_zheng: 前端小嘍嘍的Golang學習旅程_The journey of learning Golang 系列

PollyPO技術: 前端設計轉前端工程師-JS踩坑雜記 30 天 系列

阿電: 忍住不打牌位,只要30天VueJS帶你上A牌 系列

喬依司: 實作經典 JavaScript 30 系列


上一篇
Day 01: 奇怪的理論 + 有點廢的入門
下一篇
Day 03: 組件 Prop + Slot + 仿造 BootstrapVue <b-button>
系列文
Vue CLI + Firebase 雲端資料庫 30天打造簡易部落格及後臺管理30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
文斯先生
iT邦新手 4 級 ‧ 2020-09-10 09:48:01

這也太多了吧

我要留言

立即登入留言