Day26-实作(列表区) (part1)

要对个别的元件做更多的指令之前,需要先把他们个别的拆出来,第一个拆解的是列表的部分,先在components/下建立一个asideMenu.vue档案,把刚刚App.vue中的<div class="aside-menu">...</div>搬过去

//asideMenu.vue

<template>
  <div class="aside-menu">
    ...
  </div>
</template>

<script>
	export default {
	  name: "asideMenu",
	};
</script>

在App.vue被搬走的位置改由取代,并import新建立的

//App.vue

<template>
  <div id="app">
    <!-- aside-menu 左侧栏 -->
    <asideMenu />

    <!-- 地图区块 -->
    <div class="mask-map" id="mask-map"></div>
  </div>
</template>

<script>
import asideMenu from "./components/asideMenu.vue";

export default {
  name: "App",
  components: {
    asideMenu,
  },
};
</script>

<style lang="scss" src="./style.scss"></style>

取得县市及行政区资料

在store/index.js中先定义好几个状态

state: {
  //目前所选县市,预设城市
  currCity: '台北市',
  //目前所选行政区,预设北投区
  currDistrict: '北投区',
  //存放API回传的县市/行政区列表资讯
  location: [],
  //存放API回传的所有药局
  stores: []
}

先建立对应的mutations,透过他操作state的资料

mutations: {
  setcurrCity(state, payload) {
    state.currCity = payload
  },
  setcurrDistrict(state, payload) {
    state.currDistrict = payload
  },
  setAreaLocation(state, payload) {
    state.location = payload
  },
  setStores(state, payload) {
    state.stores= payload
  }
}

接着透过actions从json档案抓取资料,存到state里面

actions: {
  // 取得行政区资料
  async fetchLocations({ commit }) {
    const json = await fetch('https://raw.githubusercontent.com/kurotanshi/mask-map/master/raw/area-location.json')
      .then((res) => res.json())
	//commit操作mutaions
    commit('setAreaLocation', json)
  },
  // 取得药局资料
  async fetchPharmacies({ commit }) {
    const json = await fetch('https://raw.githubusercontent.com/kiang/pharmacies/master/json/points.json')
      .then((res) => res.json())
		//整理资料格式,拆出经纬度
    const data = json.features.map((d) => ({
      ...d.properties,
      latitude: d.geometry.coordinates[0],
      longitude: d.geometry.coordinates[1]
    }))
		//commit操作mutaions
    commit('setStores', data)
  }
}

最後回到App.vue新增mountedhook

import { mapActions } from "vuex";
import asideMenu from "./components/asideMenu.vue";

export default {
  name: "App",
  components: {
    asideMenu,
  },
  methods: {
    ...mapActions(["fetchLocations", "fetchPharmacies"]),
  },
  mounted() {
    this.fetchLocations();
    this.fetchPharmacies();
  },
};

可以从开发者工具看看是否有发送远端请求

Untitled

将行政区套用至左侧选单

得到资料後就要把它放到左侧两个下拉选单之中,在asideMenu.vue下新增computed来存取state的资料,将currCity和currDistrict透过v-model双向绑定。

computed: {
  currCity: {
    get() {
      return this.$store.state.currCity;
    },
    set(value) {
      this.$store.commit("setcurrCity", value);
    },
  },
  currDistrict: {
    get() {
      return this.$store.state.currDistrict;
    },
    set(value) {
      this.$store.commit("setcurrDistrict", value);
    },
  },
},

并改写模板

<div class="aside-menu">
  <div class="wraps">
    <label>
      县市:<select v-model="currCity">
        <option>台北市</option>
      </select>
    </label>
    <label>
      行政区:<select v-model="currDistrict">
        <option>北投区</option>
      </select>
    </label>
  </div>

接下来要处理option中的资料,从state回传的资料如下,并不适合用v-for渲染,所以需要回到getters处理

▼ location:Array[21]
	▼ 0:
		▶ districts: Array[12]
			 id: "0000"
			 name: "台北市"
			 sort: 1
	▼ 1:
	▶ districts: Array[29]
		 id: "0001"
		 name: "新北市"
		 sort: 2

行政区的部分有使用到optional chaining处理预设问题,关於此用法可以参考此连结

getters: {
  cityList(state) {
    //城市
    return state.location.map((d) => d.name)
  },
  districtList(state) {
    //行政区
    return state.location.find((d) => d.name === state.currCity)?.districts || []
  }
}

处理好资料後回到asideMenu.vue在computed新增mapGetters

computed: {
  currCity: {...},
  currDistrict: {...},
  ...mapGetters(["cityList", "districtList"]),
},

并再次改写option模板的部分

<div class="aside-menu">
  <div class="wraps">
    <label>
      县市:<select v-model="currCity">
        <option v-for="c in cityList" :key="c">{{ c }}</option>
      </select>
    </label>
    <label>
      行政区:<select v-model="currDistrict">
        <option v-for="d in districtList" :key="d.id">{{ d.name }}</option>
      </select>
    </label>
  </div>

这样大致就完成罗!!! 最後,可以加入一个watch功能,让使用者在选择新的城市时,行政区会自动切换第一个行政区。districtList 一更新,this.currDistrict也会马上切换成第一笔资料。

watch: {
  districtList(v) {
    const [arr] = v;
    this.currDistrict = arr.name;
  },
},

明天继续完成剩下的部分...


<<:  那些被忽略但很好用的 Web API / 拖拉式待办清单

>>:  {DAY 29} Seaborn

作业系统的修课经验

今天要来分享的是我最喜欢的一门学科 - 作业系统! 进入正题 作业系统是资讯学系中的一门进阶课程,内...

计算机概论 - 程序语言 Programming Languages

如果程序都必须以机械语言撰写,那麽现在复杂的程序系统发展,如作业系统、网路软件和市面上各种应用软件都...

[Day 27] 阿嬷都看得懂的 JavaScript 怎麽写

阿嬷都看得懂的 JavaScript 怎麽写 昨天我们提及程序语言的 4 个重要特徵: 变数 型别 ...

Day24:终於要进去新手村了-Javascript-函式-物件建立练习

这一篇我会使用彭彭教学中的例子加上自己理解的方式做解释以及纪录。 在彭彭课程之中的程序码如下: va...

[Day17] - 在 Vue 中引入现成的 Web Component

当我们拿到一个现有的 Web Component 时 , 如果直接在 Vue 专案中使用会抱错 今天...