Day28-实作(灯箱)

做完了侧选单就要进入到第二区块 — 灯箱

首先,在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>

到这个步骤已经可以看到一个简易的画面,如下图

Untitled

再来就是要修改一下灯箱里面的内容

<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>

修改後可以看到以下画面

Untitled

有了画面但没有资料,所以下一步就是要想办法让资料生出来。从列表中要取得药局的资讯,我们可以利用药局的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];
},

Untitled

营业的时间内容放在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;
},

可以看到内容被我们变成这样了

Untitled

再来就是修改灯箱模版

<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>

<<:  响应式网站注意细节-30天学会HTML+CSS,制作精美网站

>>:  建立第一个RESTful api server(重构篇)-1 (Day16)

【没钱买ps,PyQt自己写】Day 21 - 透过 PyQt 实现滑鼠监听总整理,完全掌握滑鼠控制 (listen mouse)

看完这篇文章你会得到的成果图 前言 这一篇我们会拿现有的 day 17 成品来改, 我们这篇主要要学...

用科学化除错方法替你的 zk 程序除错之二

b. 分析找到的资料并给出一个对根因的假设 在取得资料之後,就要针对这些资料提出一个假设。如果对 Z...

集中心力在你能力所及之事,而非不舍於无法改变的事实。

集中心力在你能力所及之事,而非不舍於无法改变的事实。 Fix your eyes forward o...

用一半的时间做两倍的事

听说,这个书名引发了一些争议。老板角色的人看这本书都认为RD团队读完後就是吃了大补丸,以後做专案只需...

D23. 学习基础C、C++语言

D23. C++介绍 C++是一种被广泛使用的电脑程序设计语言。它是一种通用程序设计语言,支援多重程...