iT邦幫忙

2023 iThome 鐵人賽

DAY 26
0
Vue.js

試試用Vue建立網站吧系列 第 26

Day26-試試Vue3-餐廳實評頁面(1)

  • 分享至 

  • xImage
  •  

因開發過程細節較多會分成兩篇來說明。

(1)新增餐廳實評頁面檔案
路徑 src / views / front 底下新增 CommentView.vue 檔案。 html 架構先建立同「Day8-試試Vue3-會員登入後轉跳主頁」的導覽(nav)。

(2)新增路由
路徑 src / router / index.js 寫入以下語法將餐廳實評頁面建為新路由。登入後才可到會員功能頁所以路徑是 login / CommentView 。

const router = createRouter({
  ...
  routes: [
  ...
    {
      path: '/login/comment',
      component: () => import('../views/front/CommentView.vue')
    },
  ]
})

(3)編輯餐廳實評檔案
本小節說明檔案 CommentView.vue 的開發內容。

(3-1)前置作業
1.調用 Pinia store 資料
<script></script> 將 LoginStore.js 檔裡的 useLoginStore 方法取出。透過 computed 監控資料更動時就重新渲染畫面的特性,把 Pinia store 剛更新的會員 name 、 email 、 id 給顯示。再運用 mapState 取用 Pinia store 資料。

2.取得網路請求 axios 的路徑
created 裡的 apiUserResUrl 與 apiUserResIdUrl 是網路請求的路徑。路徑在頁面載入時被使用,為使方法中所有函式能取用該變數(全域變數),將之定義於此。created 是 Vue 生命週期中實例創建完成階段,可訪問 data 、 computed 、 watch、 methods 上的方法和數據。此時可把 apiUserResUrl 與 apiUserResIdUrl 在 data 裡的初始值給重新賦值。

(3-2)導出的資料
<script></script> 中資料實體建立以下屬性。

  • 屬性 userResList:從會員餐廳 API 取得的資料。屬性有 name、email、userRestaurants(底下有 brandName 、 address 、 type 屬性)。
  • 屬性 selectCardList: 存放要寫回會員餐廳 API 的資料(品牌受眾、品牌名稱、地址)。屬性有 cardBrandName 、 cardType 、 cardAddress 、 cardComment 。
  • 屬性 commentDisabled:控制「餐廳評論」欄位是否可以操作。
  • 屬性 apiUserResUrl 、 apiUserResIdUrl 是網路請求 axios 的路徑。先設定初始值為空字符串,稍後在 created() 會定義其值。

(3-3)頁面下面區塊(卡片區塊)
參考 bootstrap5「卡片」來寫 html 結構。該區塊的操作情境請參考上一篇「Day25-試試Vue3-規劃餐廳實評的頁面」。

  • 頁面載入時執行 userPocket() 函式,取得該會員的會員餐廳 API 資料,並使用 v-for="(item, index) in userResList" 將口袋餐廳頁面所選的清單進行多筆資料渲染。此處需取得該筆資料的索引值(index)才能在點選每張卡片裡的「查看實評」鈕時展開下方被折疊的評論區塊,否則按了任一張卡片的「查看實評」鈕會開啟所有卡片被折疊的區塊。參數設定請參考 bootstrap5「折疊」說明。

    • 使用 bootstrap 折疊功能前需在路徑 src / main.js 這個進入點檔案內引入 bootstrap 的 JavaScript 。寫法為 import 'bootstrap/dist/js/bootstrap.bundle.min.js';
  • 點選任一張卡片時會觸發方法裡的 selectCard(item) 函式

    • 點擊卡片時其 @click 事件處理程序會自動傳遞這張卡片的數據(即 item )給方法, item 資訊包含 type 、 brandName 、 address 、 comment 。取得的 item 資料會依序賦值給 selectCardList 裡的相應屬性。此時頁面表單的「品牌受眾」、「品牌名稱」、「地址」、「餐廳評論」就能顯示其資料內容。並且「餐廳評論」欄位也會因為觸發 selectCard(item) 函式而被允許會員操作。
    • 如果所選的卡片已有評論,當會員點選卡片,「餐廳評論」欄位會顯示其評論,作為編輯功能使用。若否則顯示預設值空字串。
      • 判斷 item.comment 是否有值。若有就把內容賦值給 selectCardList.cardComment 。若否則定義 selectCardList.cardComment = ""
<template>
  <div class="container">
    ...
    <section class="row">
      <div class="col-3" v-for="(item, index) in userResList" v-bind:key="item">
        <a @click="selectCard(item)">
          <div class="card">
            <h2 class="card-header">{{ item.type }}</h2>
            <div class="card-body">
              <h3 class="card-title">{{ item.brandName }}</h3>
              <p class="card-text">{{ item.address }}</p>
              <p>
                <button
                  class="btn btn-warning"
                  type="button"
                  data-bs-toggle="collapse"
                  :data-bs-target="'#collapseExample' + index"
                  aria-expanded="false"
                  :aria-controls="'collapseExample' + index">
                  查看實評
                </button>
              </p>
              <div class="collapse" :id="'collapseExample' + index">
                <div class="card card-body">
                  {{ item.comment }}
                </div>
              </div>
            </div>
          </div>
        </a>
      </div>
    </section>
  </div>
</template>
<script>
import axios from "axios";
import { mapState } from "pinia";

// 定義好的 store 賦值給變數 useLoginStore
// 在元件中引入並呼叫 useLoginStore() 來訪問 store
import { useLoginStore } from "../../components/LoginStore.js";

export default {
  data() {
    return {
      userResList: [],
      selectCardList: {
        cardBrandName: "",
        cardType: "",
        cardAddress: "",
        cardComment: "",
      },
      commentDisabled: true,

      apiUserResUrl: "",
      apiUserResIdUrl: "",
    };
  },
  methods: {
    userPocket() {
      axios
        .get(this.apiUserResUrl)
        .then((res) => {
          console.log(res);
          this.userResList = res.data[0].userRestaurants;
        })
        .catch((error) => {
          console.log(error);
        });
    },
    selectCard(item) {
      // 允許對餐廳評論操作
      this.commentDisabled = false;
      console.log(item);
      this.selectCardList.cardBrandName = item.brandName;
      this.selectCardList.cardType = item.type;
      this.selectCardList.cardAddress = item.address;

      if (item.comment) {
        this.selectCardList.cardComment = item.comment;
      } else {
        // 將上一次選擇的卡片評論給重置
        this.selectCardList.cardComment = "";
      }
    },
  },
  created() {
    this.apiUserResUrl = `http://localhost:3002/userRes?email=${this.userEmail}`;
    this.apiUserResIdUrl = `http://localhost:3002/userRes/${this.userId}`;
  },
  mounted() {
    this.userPocket();
  },
  // 監聽data
  computed: {
    ...mapState(useLoginStore, {
      // 'name' 是 store 中的狀態名,'userName' 是在組件中的名稱
      userName: (state) => state.name,
      userEmail: (state) => state.email,
      userId: (state) => state.id,
    }),
  },
};
</script>

上一篇
Day25-試試Vue3-規劃餐廳實評的頁面
下一篇
Day27-試試Vue3-餐廳實評頁面(2)
系列文
試試用Vue建立網站吧30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言