Nuxt.js打造旅遊網站第3篇_登陸頁面的編寫

 主要知識點:

1.使用vuex/store管理數據vue

2.登陸註冊邏輯ios

3.Nuxt的本地存儲git

 

1.登陸頁面

1.1登陸頁面佈局

替換pages/user/login.vue的代碼以下github

<template>
    <div class="container">
        <!-- 主要內容 -->
        <el-row 
        type="flex" 
        justify="center" 
        align="middle" 
        class="main">

            <div class="form-wrapper">
                <!-- 表單頭部tab -->
                <el-row type="flex" justify="center" class="tabs">
                    <span :class="{active: currentTab === index}" 
                    v-for="(item, index) in [`登陸`, `註冊`]"
                    :key="index" 
                    @click="handleChangeTab(index)">
                        {{item}}
                    </span>
                </el-row>

                <!-- 登陸功能組件 -->
                <LoginForm v-if="currentTab == 0"/>

                <!-- 註冊功能組件 -->
                <!-- <RegisterForm v-if="currentTab == 1"/> -->
            </div>
        </el-row>
    </div>
</template>

<script>
import LoginForm from '@/components/user/loginForm'
export default {
    components: {
      LoginForm
    },
    data(){
        return {
            currentTab: 0
        }
    },
    methods: {
        handleChangeTab(index){
            this.currentTab = index;
        },
    }
}
</script>

<style scoped lang="less">
.container{
    background:url(http://157.122.54.189:9095/assets/images/th03.jfif) center 0;
    height: 700px;
    min-width:1000px;

    .main{
        width:1000px;
        height: 100%;
        margin:0 auto;
        position: relative;
        
        .form-wrapper{
            width:400px;
            margin:0 auto;
            background:#fff;
            box-shadow: 2px 2px 0 rgba(0,0,0,0.1);
            overflow:hidden;
            
            .tabs{
                span{
                    display: block;
                    width:50%;
                    height: 50px;
                    box-sizing: border-box;
                    border-top:2px #eee solid;
                    background:#eee;
                    line-height: 48px;
                    text-align: center;
                    cursor: pointer;
                    color:#666;

                    &.active{
                        color:orange;
                        border-top-color: orange;
                        background:#fff;
                        font-weight: bold;
                    }
                }
            }
        }
    }
}
</style>
pages/user/login.vue

 

1.2 登陸功能

 

思路:vuex

1.在components/user中新建loginForm.vue表單組件axios

2.使用Element-ui的表單組件服務器

3.表單數據綁定app

4.表單驗證less

5.登陸接口異步

 

實現步驟:

1.新建loginForm.vue表單組建

components/user中新建loginForm.vue組件,新增內容以下

<template>
    <el-form 
        :model="form" 
        ref="form"
        :rules="rules" 
        class="form">

        <el-form-item class="form-item">
            <el-input 
            placeholder="用戶名/手機">
            </el-input>
        </el-form-item>

        <el-form-item class="form-item">
            <el-input 
            placeholder="密碼" 
            type="password">
            </el-input>
        </el-form-item>

        <p class="form-text">
            <nuxt-link to="#">忘記密碼</nuxt-link>
        </p>

        <el-button 
        class="submit"
        type="primary"
        @click="handleLoginSubmit">
            登陸
        </el-button>
    </el-form>

</template>

<script>
export default {
    data(){
        return {
            // 表單數據
            form: {},
            // 表單規則
            rules: {},
        }
    },
    methods: {
        // 提交登陸
        handleLoginSubmit(){
           console.log(this.form)
        }
    }
}
</script>

<style scoped lang="less">
    .form{
        padding:25px;
    }

    .form-item{
        margin-bottom:20px;
    }

    .form-text{
        font-size:12px;
        color:#409EFF;
        text-align: right;
        line-height: 1;
    }

    .submit{
        width:100%;
        margin-top:10px;
    }
</style>
components/user/loginForm.vue

注意:新增了組件後在pages/user/login.vue中導入便可,導入位置,去除下面部分的組件的註釋

<!-- 登陸功能組件 -->
<!-- <LoginForm v-if="currentTab == 0"/> -->

 

2.表單數據綁定

修改dataform數據,而後使用v-model綁定到對應的表單字段。

編輯components/user/loginForm.vue

// 其餘代碼...

data(){
    return {
        // 表單數據
        form: {
            username: "",   // 登陸用戶名/手機
            password: ""    // 登陸密碼
        },
        // 其餘代碼...
    }
},
    
// 其餘代碼...

 

使用v-model綁定到對應的表單字段

<!-- 其餘代碼... -->

<el-form-item class="form-item">
    <!-- 新增了v-model -->
    <el-input 
              placeholder="用戶名/手機"
              v-model="form.username">
    </el-input>
</el-form-item>

<el-form-item class="form-item">
    <!-- 新增了v-model -->
    <el-input 
              placeholder="密碼" 
              type="password"
              v-model="form.password">
    </el-input>
</el-form-item>

<!-- 其餘代碼... -->

 

3.表單驗證

雙向數據綁定到form字段後,咱們如今能夠來提交表單了,可是提交以前還須要驗證下表單字段是否合法,好比不能爲空。

繼續編輯components/user/loginForm.vue

// 其餘代碼...

data(){
    return {
        // 其餘代碼...

        // 表單規則
        rules: {
            username: [
                { 
                    required: true, 
                    message: '請輸入用戶名', 
                    trigger: 'blur' 
                },
            ],
            password: [
                { 
                    required: true, 
                    message: '請輸入密碼', 
                    trigger: 'blur' 
                },
            ],
        },
    }
},
    
// 其餘代碼...

 

el-form-item添加prop屬性

<!-- 其餘代碼... -->

<!-- 新增了prop屬性 -->
<el-form-item class="form-item" prop="username">
    <el-input 
              placeholder="用戶名/手機"
              v-model="form.username">
    </el-input>
</el-form-item>

<!-- 新增了prop屬性 -->
<el-form-item class="form-item" prop="password">
    <el-input 
              placeholder="密碼" 
              type="password"
              v-model="form.password">
    </el-input>
</el-form-item>

<!-- 其餘代碼... -->

如今能夠嘗試在把input輸入框的值清空,會出如今rules中的定義的提示內容

 

4.登陸接口

接下來要調用登陸的接口進行登陸了,若是一切正常的話,咱們能夠看到後臺返回的用戶信息,若是登陸失敗,咱們須要對統一對錯誤的返回進行處理,這個咱們在最後再統一實現。

修改components/user/loginForm.vue的提交登陸事件:

// 其餘代碼...

// 提交登陸
methods: {
    handleLoginSubmit(){
        // 驗證表單
        this.$refs['form'].validate((valid) => {
            // 爲true表示沒有錯誤
            if (valid) {
                this.$axios({
                    url: "/accounts/login",
                    method: "POST",
                    data: this.form
                }).then(res => {
                    console.log(res.data);
                })
            }
        })
    }
}

// 其餘代碼...

 

如今登陸接口能夠開始訪問了,服務器給咱們提供了測試帳號密碼

帳號:13800138000

密碼:123456

 

若是正常登陸應該能夠在控制看到打印出來的用戶信息,則表示登陸成功了。

 

5.總結

  1. components/user中新建loginForm.vue表單組件

  2. 使用Element-ui的表單組件綁定數據和驗證表單

  3. 調用登陸接口

 

2.使用store管理數據

思路:

使用vuex統一管理用戶登陸註冊行爲和用戶信息。

1.在store文件夾下新建user.js

2.在store/user.js中實現登陸,並保存數據到store的state中

3.在頭部組建中顯示用戶信息

 

實現步驟:

新建狀態文件

// 每一個小倉庫都必須暴露出 state, mutations

export const state = {
userInfo: {
// 用戶驗證的token
token: "",
// 用戶信息
user: {

}

}
}

export const mutations = {
// 設置用戶信息
setUserInfo(state, data){
state.userInfo = data;
}
}

 

在登陸請求發送成功後存儲用戶輸入的數據到vuex的store倉庫中。

        // 提交登陸
        handleLoginSubmit(){
          // 驗證表單
          this.$refs['form'].validate((valid)=>{
            // 爲true表示沒有錯誤
            if(valid){
              this.$axios({
                url: '/accounts/login',
                method: 'POST',
                data: this.form
              }).then(res=>{
                // 1.保存到vuex, 注意調用方法時加上命名空間,也就是方法所在的模塊user
                this.$store.commit('user/setUserInfo', res.data)
              })
            }
          })
        }
loginForm.vue

 

在頁面中顯示用戶登陸的手機號,在header.vue組件中替換下面代碼。

<span class="el-dropdown-link">
              <img src="http://157.122.54.189:9095/assets/images/avatar.jpg" alt="">
              {{this.$store.state.user.userInfo.user.username}}
              <i class="el-icon-arrow-down el-icon--right"></i>
</span>

 

nuxt下的store的使用

1.先新建數據的模塊,一個模塊就是一個文件,文件名字就是模塊的名字,好比新建一個user模塊,每一個模塊裏面能夠暴露出3個經常使用的屬性

  • state
  • mutations
  • actions
// 每一個小倉庫都必須暴露出 state, mutations

export const state = {
  userInfo: {
    // 用戶驗證的token
    token: "",
    // 用戶信息
    user: {

    }
    
  }
}

export const mutations = {
  // 設置用戶信息
  setUserInfo(state, data){
    state.userInfo = data;
  }
}
store/user.js

 

2.讀取user下面的用戶

{{ $store.state.user.userInfo.user.username }} 
components/header.vue

 

3.調用mutations下的方法時候必需要帶有模塊名稱

// 1.保存到vuex
this.$store.commit("user/setUserInfo", res.data);
components/user/loginForm.vue

 

把store數據保存到本地

由於這個項目是Node.js項目,因此不能使用使用localStorage方法來存儲,這裏須要安裝一個插件解決這個本地存儲問題。

插件地址:https://github.com/robinvdvleuten/vuex-persistedstate

安裝依賴

安裝:yarn add vuex-persistedstate

 

配置nuxt.config.js,在plugins中添加下面配置。

{ src: '~/plugins/localStorage.js', ssr: false }

 

在plugins目錄中新建localStorage.js並添加以下代碼。

// ~/plugins/localStorage.js

import createPersistedState from 'vuex-persistedstate'

export default ({store}) => {
  window.onNuxtReady(() => {
    createPersistedState({
        key: 'store'
    })(store)
  })
}

使用一個第三方的插件vuex-persistedstate, 經過這個插件會自動把store的數據保存到本地,而且在應用加載完後會自動把本地的數據從新賦值給store。

 

3.判斷顯示頁面信息

當本地保存的數據被清除後,頁面中仍會顯示頭像,應該顯示的是"登陸/註冊"按鈕,修改爲下面的代碼便可。

<div>
        <div v-if="!$store.state.user.userInfo.token">
          <nuxt-link to="/user/login">登陸 / 註冊</nuxt-link>
        </div>
        <div v-else>
          <el-dropdown>
            <span class="el-dropdown-link">
              <img
                :src="$axios.defaults.baseURL + $store.state.user.userInfo.user.defaultAvatar"
                alt
              />
              {{this.$store.state.user.userInfo.user.username}}
              <i
                class="el-icon-arrow-down el-icon--right"
              ></i>
            </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item>我的中心</el-dropdown-item>
              <el-dropdown-item>退出</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
      </div>
header.vue

 

4.退出登陸

給header.vue組件中的退出按鈕添加一個退出事件

<!-- 給經過native給elementUI組件綁定原生事件 -->
<el-dropdown-item @click.native="handleLogout">退出</el-dropdown-item>

 

  methods: {
    // 退出登陸,清空本地用戶數據
    handleLogout(){
      this.$store.commit('user/clearUserInfo');
    }
  }

 

在store/user.js模塊的mutations中添加一個清空數據的方法。

  // 設置用戶數據爲空
  clearUserInfo(state){
    state.userInfo = {};
  }

登陸成功以後跳轉到首頁,在loginForm.vue中添加下面代碼。

// 跳轉到首頁
this.$router.push("/");

 

5.actions的使用

actions是異步的修改倉庫的數據,而且依賴mutations。

mutations:用於同步修改倉庫的數據。

actions:用於異步修改倉庫的數據,例如登陸。

 

將發送登陸請求的代碼寫到actions的方法裏面,方便之後維護和調用。

在store/user.js中新增actions。

// 異步修改倉庫的數據
export const actions = {
  // login(store, data){
  login({commit}, data){
    return this.$axios({
      url: "/accounts/login",
      method: "POST",
      data:data
    }).then(res => {
      // store.commit("setUserInfo", res.data)
      commit("setUserInfo", res.data)
      // 1.保存到vuex, 注意調用方法時加上命名空間,也就是方法所在的模塊user

      // 登陸後的行爲應該由調用的頁面去執行,不能寫死,由於每一個頁面登陸成功執行的操做可能不同
      // this.$router.push("/");
      
    });
  }
}

 

loginForm.vue組件中的發送登陸請求方法的代碼改成:

  methods: {
    // 提交登陸
    handleLoginSubmit() {
      // 驗證表單
      this.$refs["form"].validate(valid => {
        // 爲true表示沒有錯誤
        if (valid) {
          this.$store.dispatch('user/login', this.form).then(res=>{
            this.$router.push('/');
          })
        }
      });
    }
  }

 

actions總結

什麼狀況下把方法封裝到actions?

  異步的方法須要複用的時候,能夠考慮把方法封裝到actions,好比登陸這些方法。

 

actions要怎麼聲明?

  actions裏面的方法第一個參數是store對象,這個對象下面能夠訪問到全部store的屬性(commit, dispatch, state...)用commit修改state數據;

  第二個是可選的,是傳遞進來的參數。

 

怎麼調用actions的方法?

this.$store.dispatch('user/login', this.form).then(res=>{ this.$router.push('/'); })

 

store總結

 何時使用Vuex?

  項目數據比較多,須要多個組件去共享數據的時候能夠使用vuex

 

怎麼使用?

  state: 存儲數據

  mutations: 設置修改state的數據

  actions: 異步修改state的數據,把能夠複用的請求放到actions裏面(actions須要調用mutations的方法修改數據)

 

使用時候注意的問題

  單詞別寫錯

  注意調用mutations和actions的方法記得加上模塊名字(命名空間)

相關文章
相關標籤/搜索