iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0
SideProject30

從零開始的firebase與Vue框架ーSNS專案系列 第 28

Day28—開發日記(九)自訂新增firebase文件名稱、建立讓使用者更改資料頁面

  • 分享至 

  • xImage
  •  

前言

今天回歸實作,主要處理:

  1. 將存入firestore的文件名稱自訂為user的uid:為了在userSetting頁面拿取到登入使用者的資料
  2. 讓使用者可以變更資料(先以變更名字為首)

實現內容

問題思考與解決:

  1. 需要自訂firestore集合的文件名:
  • addDoc改為setDoc
  • collection改成doc
export class FbService {
  registerAccount = async (userInfo) => {
    let isRegisterSuccessful = false;
    
    try {
      const data = await createUserWithEmailAndPassword(auth, userInfo.value.email, userInfo.value.pwd);
      console.log("successfully registered", data);

      const userRef = doc(db, "users", data.user.uid); //將collection改成doc
      const userDoc = {
        UID: data.user.uid,
        name: userInfo.value.name,
        email: userInfo.value.email
      };

      await setDoc(userRef, userDoc); // 使用 setDoc 函數將文檔添加到集合中
      isRegisterSuccessful = true;
      console.log("User added to Firestore");
    } catch (error) {
      console.error("Register Fail: ", error.code);
    }

    return isRegisterSuccessful;
  };

在註冊一筆新資料後,印出使用者資料確認uid以及email。

回到網頁的firestore確認,可以看到名稱為uid的使用者資料已經被加進去資料庫了。

  1. 在UserSetting頁面拿取使用者資料
  • 用模板語法綁定email與name
   <div>
        <label for="email" class="text-white">User Email: {{ userRef.email }}</label>
      </div>
      <div>
        <label for="displayName" class="text-white">User Name: </label>
        <span v-if="!editing" class="text-white">{{ userRef.name }}</span>
  </div>

//<script setup>的部分
const userRef = ref({ email: "", name: "" })

onMounted(() => {
  const auth = getAuth()
  const db = getFirestore()

  onAuthStateChanged(auth, async (user) => {
    if (user) {
      userRef.value = user
      console.log("User UID:", user.uid) //確認拿取的的UID正確與否
      const userDocRef = doc(db, "users", user.uid)
      console.log(userDocRef) //拿取到的物件
      const userDoc = await getDoc(userDocRef) 
      console.log(userDoc.data()) //物件裡面的值們
      userRef.value = { 
        ...userRef.value, // 保留 userRef.value 對象的原有属性
        ...userDoc.data() // 將userDoc.data() 對象的属性合併到 userRef.value對象中
      }
    }
  })
    

可以看見畫面上首先印出目前登入使用者的詳細資訊。

  1. 讓使用者可以編輯資料
  • 點擊編輯按鈕可以進入編輯模式:按鈕必須是切換可見狀態的
  • 在確定後能夠實時更新網頁上的資訊,以及資料庫內的資料

按下Edit Profile後,讓使用者進入編輯模式

按下完成後,可以看見無論是網站以及資料庫內資料已經被更新完畢。


https://ithelp.ithome.com.tw/upload/images/20231013/20162319gUxSNj8XoU.png

//在Edit Profile加上startEditing,掌控editing監控按鈕的顯示與否
// 再用v-model雙向綁定資料
// 在完成按鈕與取消按鈕上,
// 創建completeEditing跟canceling Editing 兩個事件,
//分別掌管修改資料以及取消
 <div>
        <label for="displayName" class="text-white">User Name: </label>
        <span v-if="!editing" class="text-white">{{ userRef.name }}</span>
        <input v-if="editing" v-model="editedDisplayName" />
        <button
          v-if="editing"
          class="text-white"
          @click="completeEditing"
        >
          Complete
        </button>
        <button
          v-if="editing"
          class="text-white"
          @click="cancelEditing"
        >
          Cancel
        </button>
      </div>
    </div>
    <button
      class="text-white"
      @click="startEditing"
    >
      Edit Profile
    </button>

由於需要實時監聽editedDisplayName的變化,並確保在取消編輯時退回原始值,使用了watch參數

  watch(editedDisplayName, (newValue, oldValue) => {
    console.log(oldValue)
    if (!editing.value && newValue !== userRef.value.name) {
      editedDisplayName.value = userRef.value.name
    }
  })

各按鈕的事件:未來是否可以模組化?

/**
 * 開始編輯,故一開始為true
 */
const startEditing = () => {
  editing.value = true
  editedDisplayName.value = userRef.value.name
}

/**
 * 完成編輯
 */
const completeEditing = () => {
  editing.value = false
  updateUserProfile()
}
/**
 * 取消編輯
 */
const cancelEditing = () => {
  editing.value = false
  editedDisplayName.value = userRef.value.name
}

將更新後的資料加入資料庫:

/**
 * 更新userprofile
 */
const updateUserProfile = async () => {
  try {
    const user = userRef.value
    const db = getFirestore()
    const userDocRef = doc(db, "users", user.uid)

    await updateDoc(userDocRef, {
      name: editedDisplayName.value
    })

    userRef.value = {
      ...userRef.value,
      name: editedDisplayName.value
    }
    console.log("User profile updated successfully!", editedDisplayName.value)
  } catch (error) {
    console.error("Error updating user profile:", error)
  }
}

總結與未來目標

  • 更改了新增資料的方式,能拿到使用者的資料
  • 編輯模式的寫法應該更加模組化,減少code的雜亂程度

上一篇
Day27—Vue(十三) Vuex 狀態管理模式
下一篇
Day29—開發日記(十)專案進度小結、JsDoc、私有類別
系列文
從零開始的firebase與Vue框架ーSNS專案31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言