大家還記得元件系列第一篇筆記中,提到的 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 ; } }