做完了側選單就要進入到第二區塊 — 燈箱
首先,在src/components下新增lightbox.vue(內容取自此連結)
<template>
<transition name="modal">
<div class="modal-mask" v-show="showModal">
<!-- 為了可以關閉燈箱,加上@click.self="close" -->
<div class="modal-wrapper" @click.self="close">
<div class="modal-container">
<div class="modal-body">
<!-- 內容放這裡 -->
<div>Hello</div>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: 'Lightbox',
computed: {
showModal: {
get() {
return this.$store.state.showModal;
},
set(value) {
this.$store.commit('setshowModal', value);
},
},
},
methods: {
close() {
this.showModal = false;
},
},
};
</script>
<style scoped lang="scss">
.modal-mask {
position: fixed;
z-index: 100;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .65);
display: table;
transition: opacity .3s ease;
}
.modal-wrapper {
display: table-cell;
vertical-align: middle;
}
.modal-container {
width: 520px;
margin: 0px auto;
padding: 10px 30px;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 8px rgba(0, 0, 0, .3);
transition: all .3s ease;
font-family: Helvetica, Arial, sans-serif;
}
.modal-body {
color: #42b983;
margin: 20px 0;
}
</style>
<style>
.modal-enter {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
transform: scale(1.1);
}
</style>
<style lang="scss" scoped>
.store-name {
font-size: 1.6rem;
font-weight: bold;
line-height: 1.5;
}
.title{
font-weight: 500;
margin-bottom: .5rem;
line-height: 1.7;
}
table {
border-spacing: 0;
border-radius: 3px;
width: 100%;
margin-bottom: 1rem;
}
th{
background-color: #42b983;
color: #fff;
}
td, th{
padding: .3em;
text-align: center;
line-height: 1.5rem;
}
</style>
並在store/index.js中新增showModal
state: {
currCity: '臺北市',
currDistrict: '北投區',
location: [],
stores: [],
keywords: '',
showModal: false
},
及相對應的mutations
setshowModal(state, payload) {
state.showModal = payload
}
接著修改App.vue,加入lightBox.vue
import { mapActions } from "vuex";
import asideMenu from "./components/asideMenu.vue";
import lightBox from "./components/lightBox.vue";
export default {
name: "App",
components: {
asideMenu,
lightBox,
},
methods: {
...mapActions(["fetchLocations", "fetchPharmacies"]),
},
mounted() {
this.fetchLocations();
this.fetchPharmacies();
},
};
側選單處可以控制modal的開關,所以要回到asideMenu.vue加入對應的showModal控制屬性
computed: {
currCity: {...},
currDistrict: {...},
keywords: {...},
...mapGetters(["cityList", "districtList", "filteredStores"]),
showModal: {
get() {
return this.$store.state.showModal;
},
set(value) {
this.$store.commit("setshowModal", value);
},
},
},
以及相關的methods
openInfoBox() {
this.showModal = true;
},
還有要去模板那增加click事件
<button class="btn-store-detail" @click="openInfoBox()">
<i class="fas fa-info-circle"></i>
看詳細資訊
</button>
到這個步驟已經可以看到一個簡易的畫面,如下圖
再來就是要修改一下燈箱裡面的內容
<div class="modal-body">
<h1 class="store-name">藥局名稱</h1>
<hr>
<h2 class="title">營業時間</h2>
<table>
<thead>
<tr>
<th></th>
<th>ㄧ</th>
<th>二</th>
<th>三</th>
<th>四</th>
<th>五</th>
<th>六</th>
<th>日</th>
</tr>
</thead>
<tbody>
<tr>
<th>早上</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>中午</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>晚上</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<h2 class="title">地址 XXXXXXX</h2>
<h2 class="title">電話 XXXXXXX</h2>
<h2 class="title">備註 XXXXXXX</h2>
</div>
修改後可以看到以下畫面
有了畫面但沒有資料,所以下一步就是要想辦法讓資料生出來。從列表中要取得藥局的資訊,我們可以利用藥局的id來渲染資料,先在state中新增一個infoBoxSid
state: {
currCity: '臺北市',
currDistrict: '北投區',
location: [],
stores: [],
keywords: '',
showModal: false,
infoBoxSid: null
},
以及mutations
setInfoBoxSid(state, payload) {
state.infoBoxSid = payload
}
接下來就是在asideMenu.vue和lightBox.vue加上computed屬性
infoBoxSid: {
get() {
return this.$store.state.infoBoxSid;
},
set(value) {
this.$store.commit("setinfoBoxSid", value);
},
},
改寫asideMenu.vue的openInfoBox,讓他可以帶入藥局的id
openInfoBox(sid) {
this.showModal = true;
this.infoBoxSid = sid;
},
當然模板也要改一下
<button class="btn-store-detail" @click="openInfoBox(s.id)">
<i class="fas fa-info-circle"></i>
看詳細資訊
</button>
同時,在lightBox.vue的computed新增以下內容,就可以找到對應的藥局資訊
currStore() {
return this.$store.state.stores.filter(
(d) => d.id === this.infoBoxSid
)[0];
},
營業的時間內容放在service_periods這個欄位,我們要把NNNNNNYNNNNNNYNNNNNNY
拆解成我們需要的內容,所以在lightBox.vue中computed加上servicePeriod
servicePeriods() {
let servicePeriods = this?.currStore?.["service_periods"] || "";
servicePeriods = servicePeriods.replace(/N/g, "O").replace(/Y/g, "X");
return servicePeriods
? [
servicePeriods.slice(0, 7).split(""),
servicePeriods.slice(7, 14).split(""),
servicePeriods.slice(14, 21).split(""),
]
: servicePeriods;
},
可以看到內容被我們變成這樣了
再來就是修改燈箱模版
<div class="modal-body">
<h1 class="store-name">{{ currStore.name }}</h1>
<hr />
<h2 class="title">營業時間</h2>
<table>
<thead>
<tr>
<th></th>
<th>ㄧ</th>
<th>二</th>
<th>三</th>
<th>四</th>
<th>五</th>
<th>六</th>
<th>日</th>
</tr>
</thead>
<tbody>
<tr>
<th>早上</th>
<td v-for="(s, idx) in servicePeriods[0]" :key="idx">
{{ s }}
</td>
</tr>
<tr>
<th>中午</th>
<td v-for="(s, idx) in servicePeriods[1]" :key="idx">
{{ s }}
</td>
</tr>
<tr>
<th>晚上</th>
<td v-for="(s, idx) in servicePeriods[2]" :key="idx">
{{ s }}
</td>
</tr>
</tbody>
</table>
<h2 class="title">地址 {{ currStore.address }}</h2>
<h2 class="title">電話 {{ currStore.phone }}</h2>
<h2 class="title" v-if="currStore.custom_note">
備註 {{ currStore.custom_note }}
</h2>
</div>
若一開始沒有currStore的情況下找不到currStore.name會跳錯,此時可以在modal加上v-if解決錯誤。
<div class="modal-body" v-if="currStore"></div>