iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0
Vue.js

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

Day9-試試Vue3-主頁歡迎訊息顯示會員名(Pinia)

  • 分享至 

  • xImage
  •  

這裡要將會員登入頁面(LoginView.vue 檔)中 axios.get() 取得的會員 name 儲存到 Pinia 裡的 store 。再透過該 store 取出 name 給會員主頁(MainView.vue 檔),如此就能在主頁裡顯示會員 name 。

使用 Pinia store 好處是可以存放資料狀態與方法,支持專案內跨元件的資料傳遞,且元件也可以被統一管理。此篇 Pinia 的 store 採用 Option store 寫法。

(1)安裝 Pinia 套件
(windows系統)命令提示字元執行以下指令。執行完檔案 package.json 清單內會出現 Pinia 套件,表示安裝完成。

npm install pinia

路徑 src / main.js 進入點檔案也要引入 Pinia 套件。

import { createPinia } from 'pinia'
...
const app = createApp(App)
..
// 建立 Pinia 實例
const pinia = createPinia();

// 使用 createApp 方法而創立的 app 實例
app.use(pinia);
...
app.mount('#app')

(2)建立登入會員的 Pinia store
路徑 src / components 底下新增 LoginStore.js 檔案作為登入會員的 Pinia store。

  • 導出的資料建立屬性 name 並定義字串型態。這邊先以空字串為默認值。
  • 方法中建立 updateName() 函式。當函式被調用時,如 updateName() 會將接收到的變數 newName 值賦給 this.name ,進而修改 Pinia store 中的資料狀態(即更新 name 的值)。
// 取出 Pinia 裡的 defineStore 方法
import { defineStore } from 'pinia'

// useLoginStore 是自行定義 Pinia store 的函數,之後可以通過調用它來取得 store 實例
export const useLoginStore = defineStore({
    id: 'myStore',
    state: () => ({
        name: ''
    }),
    // actions 概念同 Vue 的 methods
    // 透過呼叫將 response 存到 state 中,所以 actions 可以用來更新 state 資料的方法
    actions: {
        updateName(newName) {
            this.name = newName;},
    },
})

(3)會員登入頁面訪問 Pinia store
路徑 src / views / front / LoginView.vue 檔案裡的 <script></script> 調整以下內容。

  • data() return 增加屬性 name: "" 來接收 store 的 name。
  • 表單送出按鈕檢查表單驗通過時,在 axios.get() 取得資料集後,新增一個新變數 newName 去接收資料集裡的第一個物件值。定義 newName.name 屬性值為資料集的 name 。接下來就能用前一步驟建立好的 Pinia 的 updateName() action 去更新 store 裡的 state 資料(即將取得資料集的 name 回傳到 store 裡的 name)。
<script>
...
// 在元件中引入並呼叫 useLoginStore() 來訪問 store
import { useLoginStore } from "../../components/LoginStore.js";

export default {
  data() {
    return {
      name: "",
      email: "",
      password: "",
    };
  },
  methods: {
    ...
    // 表單送出按鈕
    submitOrder() {
      // 使用 Vee Validate 的 validate 函式來驗證表單
      this.$refs.form.validate().then((valid) => {
        if (valid) {
          // 驗證通過,可以提交表單
          axios
            .get(
              `http://localhost:3000/user?email=${this.email}&password=${this.password}`
            )
            .then((res) => {
              ...

              // 假設網路請求成功取得資料集
              // 變數 newName 指資料集裡的第一個物件值
              const newName = res.data[0]; 
              // 令 data() 裡的 name 為資料集的 name
              this.name = newName.name; 

              // 使用 Pinia 中的 updateUser action 更新 store 裡的 state 資料
              // (1)訪問 store 中的狀態和執行。這寫法是直接在方法中取得 store 實例(userStore)
              const userStore = useLoginStore(); 
              // (2)操作這實例(userStore)去調用 updateName ,將 axios.get 取得的 newName.name 更新到 store 的 name 狀態中
              userStore.updateName(newName.name); 

              // 印出來看 newName.name 值
              // console.log("User data updated:", newName.name);
              ...
            })
            .catch((error) => {
              ...
            });
        } else {
          ...
        }
      });
    },
  },
};
</script>

(4)會員主頁顯示會員名
調整路徑 src / components / MainView.vue 檔案達到取用 Pinia store 資料目的。

STEP1:<script></script> 將 LoginStore.js 檔裡的 useLoginStore 方法取出。透過 computed 監控資料更動時就重新渲染畫面的特性,把 Pinia store 剛更新的會員 name 給顯示。再運用 mapState 取用 Pinia store 資料。

<script>
import { mapState } from 'pinia';

// 在元件中引入並呼叫 useLoginStore() 來訪問 store
import { useLoginStore } from "../../components/LoginStore.js";

export default {
  computed: {
    ...mapState(useLoginStore, {
      // 'name' 是 store 中的狀態名,'userName' 是在組件中的名稱
      userName: (state) => state.name,
    }),
  }
};
</script>

STEP2:html 架構增加顯示會員名的標籤
會員註冊的表單驗證沒有規定會員名稱若是英文第一個字母要大寫。這邊可以用 bootstrap5 文字變換 功能(class 屬性加上 text-primary)把英文會員名的第一個字母轉為大寫。

<template>
  <div class="container">
    <ul class="nav main-nav mb-5">
    ...
    </ul>
    <p class="fs-4 fw-bold text-capitalize text-primary">歡迎華特會員 {{ userName }}</p>
    ...
</template>

畫面執行結果。
畫面執行結果


上一篇
Day8-試試Vue3-會員登入後轉跳主頁
下一篇
Day10-試試Vue3-歡迎訊息顯示會員名(Pinia)下
系列文
試試用Vue建立網站吧30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言