大家還記得元件系列第一篇筆記中,提到的 Demo 嗎? 本篇筆記要帶領大家回顧元件系列中所有的觀念,一步一步拆解這個 Demo 該如何製作!
首先先把成品放在最前面供參:
功能一:用 <select>
篩選特定縣市的測站 HTML
<select>
用 v-model
綁定根實例的 filter
特性
<option>
用 v-for="county in location"
+ :value="county"
渲染
元件模板:寫在 .app
外面,用 <script type="text/x-template">
製作
元件置入的地方:這次是用 Bootstrap 卡片元件來製作,所以元件模板置入的地方就在 .card-columns
裡面
元件:用 v-for
渲染所有城市,並且在這裡進行內外層資料傳遞 (外傳內 -> 所有城市資料) (內傳外 -> 關注的城市)
Vue 根實例
AJAX 取得資料,篩選出所有縣市並存到 data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 var app = new Vue({ el: "#app" , data: { data: [], location: [], stared: [], filter: "" }, created: function ( ) { this .getData(); }, methods: { getData() { const vm = this ; const api = "https://cors-anywhere.herokuapp.com/http://opendata2.epa.gov.tw/AQI.json" ; $.get (api).then(function(response) { vm.data = response; const siteCounty = []; vm.data.forEach(item => siteCounty.push(item.County)); vm.location = siteCounty.filter( (element, index, array) => array.indexOf(element) === index ); }); } }, });
<select>
選出縣市後,顯示符合條件的測站 在 computed
中,用 if
判斷 <select>
是否有選擇特定縣市,沒選的話就呈現所有測站資料。以及用 filter()
過濾根實例的 data
,篩選出符合條件(縣市)的測站
1 2 3 4 5 6 7 8 9 10 11 12 13 computed: { filterData: function () { if (this .filter == '' ) { return this .data ; } let filtered = this .data .filter((item) => { return item.County == this .filter; }); return filtered; }, }
Vue 元件 1 2 3 4 Vue .component ('card-component' , { props : ['cardData' ], template : '#cardTemplate' , });
功能二:點擊星星設為關注城市,且設定 localStorage 星星按鈕是位於元件中的元素,所以就要用到 $emit
把內層資料傳到外層。
HTML
元件模板:星星按鈕為用 <a>
包住的 fontawesome icon,在 <a>
加上 click
事件且綁定至元件的 methods
(用 emit
傳遞資料);在 <i>
上用 v-bind
綁定 className
切換(切換星星點擊後的樣式)。
1 2 3 4 <a href="#" class ="float-right" @click.prevent="clickStar" > <i :class ="starStyle" ></i > </a> <!--clickStar 是元件的 method, 用 $emit 傳到外層-->
元件:加入 :star="stared"
跟 @change-stared="setStar"
。前者是用於 localStorage 紀錄已關注的測站,後者是要配合 emit
從元件傳資料到根實例。
元件 2:在「關注城市」的欄位下,貼上同一個元件,只需要把 v-for
的來源陣列改成 staredData
就好。
Vue 元件
在 props
中加入 star
,接收根實例的 localStorage 資料。
在 methods
中寫一個 function,把星星被點擊的測站送進根實例的 methods
。
1 2 3 4 5 methods : { clickStar : function (){ this.$emit ('change-stared' , this.cardData.SiteName); } },
在 computed
中新增 starStyle()
,點選的城市不存在關注中時,星星為實心;已存在時,空心。
Vue 根實例
在 data.stared
中取出 localStorage 紀錄
1 2 stared: JSON . parse(localStorage.getItem('staredSites ') ) || [] ,
在 methods
中新增 setStar()
,接收 $emit
傳遞被點擊的城市名稱,並判斷是否存在 stared
陣列中
在 computed
中新增 staredData()
,從 data
中找出已存在於 this.stared
的測站
功能三:依據汙染程度呈現不同顏色 在 CSS 中事先寫好不同汙染程度對應的 class
,每個 class
都設定不同的背景顏色,等一下要把這些 class
套用到卡片上。
HTML
元件模板:在 .card
上用 v-bind
切換 className
,:class="airColor"
。
Vue 元件 在 computed
新增 airColor()
,用 switch
判斷汙染等級的顏色。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 airColor: function(){ let status = this .cardData.Status; switch (status) { case '普通' : return 'status-aqi2' ; break ; case '對敏感族群不健康' : return 'status-aqi3' ; break ; case '對所有族群不健康' : return 'status-aqi4' ; break ; case '非常不健康' : return 'status-aqi5' ; break ; case '危害' : return 'status-aqi6' ; break ; } }