Vue.js 實現使用者登入退出和 e2e 測試

狼族小狽發表於2017-06-12

前言

本來只是想寫個Vuet實現登入退出的例子的,但是又覺得這樣乾貨太少。一個好的開源專案,少不了單元測試和e2e測試,為了保證Vuet教程的豐富性和程式的穩定性,所以我選擇了寫的例子即能當教程使用,也可以用於測試,豐富的應用場景和測試,能保證日後的版本迭代不會因為修復了一個bug而引發了一大堆bug的尷尬。

原始碼地址

例子原始碼
測試原始碼

執行Vuet專案

git clone https://github.com/medevicex/vuet.git
npm install
npm run dev
npm run dev:test # 執行測試,需要電腦本地安裝firefox和chrome瀏覽器複製程式碼

開始

哈哈,上面直接拋原始碼地址,感覺也是挺尷尬的,我們先分析一下我們這個登入退出所需要所的功能

  • 登入頁面,使用者資訊頁面,是兩個不同的頁面,就涉及到了多元件狀態共享
  • 我期望使用者在已登入的情況下,每次到使用者資訊頁面時,先渲染本地的使用者資訊,然後再去請求伺服器更新本地的使用者資訊
  • 將登入退出的方法,集中起來管理,方面在在各個元件中呼叫

多元件共享狀態和方法

Vuet提供了全域性的mapModules方法,可以讓我們連線到掛載在Vue例項上的Vuet例項

  • ages/Home.vue
  import { mapRules, mapModules } from 'vuet'

  export default {
    mixins: [
      // manual:規則,可以將通用的更新模組狀態的方法集中起來,
      //        可以理解成vuex中的action,只不過他是可以允許在裡面更改模組狀態的
      // need 規則,會在元件每一次的beforeCreate鉤子中,傳送請求更新一次使用者的資訊
      mapRules({ manual: 'user', need: 'user' }),
      // 連線使用者模組
      mapModules({ user: 'user' })
    ]
  }複製程式碼

定義一個user模組

  • vuet/user.js
export default {
  data () {
    // 一個Object物件中,是否有data方法,是構成Vuet.js一個模組的依據
    // 當你呼叫reset方法時,將會重置整個模組的狀態
    // 例如在元件中:this.$vuet.reset('模組名稱')
    return {
      name: null,
      age: null,
      sex: null,
      count: 0
    }
  },
  async fetch ({ state }) {
    // 當need規則觸發更新時,出呼叫一次fetch方法更新
    // 我們可以在這裡直接更改state,也可以return一個Object物件來更新狀態

    // 在實際專案中,使用者未登入時,我們並不需要向伺服器傳送真正的請求
    // 所以我們可以判斷一下使用者的名稱是否存在,否則的話不向伺服器進行真正的請求
    if (state.name === null) return

    // 下面資料因為是模擬的,所以就直接return好了
    return {
      name: 'Vuet',
      age: 18,
      sex: 'male',
      count: ++state.count
    }
  },
  // 注:你要在元件中使用manual規則才能向元件注入這些方法
  // 例如:mapRules({ manual: '模組名稱' }) 
  // 呼叫:this.$模組名稱.xxx()
  manuals: {
    async signin ({ state }, from) { // 定義了一個登入的方法
      if (from.name === 'Vuet' && from.pass === '2017') {
        return {
          success: true,
          msg: 'Login was successful',
          data: {
            name: 'Vuet',
            age: 18,
            sex: 'male',
            count: ++state.count
          }
        }
      }
      return {
        success: false,
        msg: 'Logon failure',
        data: null
      }
    },
    async sigout () {
      // 使用者選擇退出後,直接呼叫reset的方法即可重置使用者資訊
      this.reset()
    }
  }
}複製程式碼

實現使用者登入

  • pages/Signin.vue

<template>
  <div class="inner">
    <b class="msg" style="color:red" v-if="msg">{{ msg }}</b>
    <form @submit.prevent="submit">
      <div>
        <label>User name:<input class="name" type="text" v-model="form.name"></label>
      </div>
      <div>
        <label>Password:<input class="pass" type="password" v-model="form.pass"></label>
      </div>
      <button>Signin</button>
    </form>
  </div>
</template>
<script>
  import { mapRules, mapModules } from 'vuet'

  export default {
    mixins: [
      // 使用manual規則取得user模組裡面manuals的方法
      mapRules({ manual: 'user' }),
      // 連線使用者的模組資訊
      mapModules({ user: 'user' })
    ],
    data () {
      return {
        msg: null,
        form: {
          name: null,
          pass: null
        }
      }
    },
    methods: {
      async submit () {
        const res = await this.$user.signin(this.form)
        this.msg = res.msg
        if (res.success) {
          // 登入成功後,直接賦值更新使用者資訊
          this.user = res.data
          setTimeout(() => {
            this.$router.replace({ name: 'home' })
          }, 500)
        }
      }
    }
  }
</script>
<style scoped>
</style>複製程式碼

總結

其實教程並沒有寫得特別詳細的過程,主要是為了體現出Vuet一種開放的姿態,它可以在任意元件直接對模組的狀態進行直接的賦值更新,也可以使用類似action的方法進行更新,它可以讓你為所欲為,用得好的人可以讓你開發的效率飆升,用得不好,也會導致你程式中的狀態難以追蹤變化的記錄。哈哈,不小心被嚇到了吧,其實這些都是有辦法可以解決的,下次有機會,我們可以再討論一下使用Vuet的正確姿勢。

相關文章