关键词搜索

源码搜索 ×
×

uniapp 用户登录

发布2022-01-03浏览5213次

详情内容

一、登录基础
1. 登录组件

对于 登录 功能来说提供了两个登录的入口。

那么大家想一下,现在我们已经在 我的 这个 tab页 中实现了 登录的 UI,难道我还需要在另外一个页面中再去实现一遍吗?

这个肯定是不需要的对不对。所以我们希望可以复用登录的 UI,而复用的方式则可以把 登录的 UI 封装称为一个 组件

创建登录组件 my-login
在这里插入图片描述
在这里插入图片描述

登录页面基本样式

<template>
  <view class="my-container">
    <!-- 用户未登录 -->
    <block>
      <image class="avatar avatar-img" src="/static/images/default-avatar.png" mode="scaleToFill" />
      <view class="login-desc">登录后可同步数据</view>
      <button class="login-btn" type="primary" @click="getUserInfo">微信用户一键登录</button>
    </block>
  </view>
</template>

<script>
export default {
  name: 'my-login',
  data() {
    return {};
  }
};
</script>

<style lang="scss" scoped>
.my-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 25%;
  .avatar-img {
    width: 78px;
    height: 78px;
  }
  .login-desc {
    color: $uni-text-color-grey;
    font-size: $uni-font-size-base;
    margin-top: $uni-spacing-col-big;
  }
  .login-btn {
    margin-top: $uni-spacing-col-big;
    width: 85%;
  }
}
</style>

    2. 页面引用组件

    me.vue

    <template>
      <my-login />
    </template>
    
    <script>
    export default {
      name: 'login'
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    3. 明确登录的实现思路

    微信小程序:

    1. 想要实现登录功能,那么我们需要调用登录接口来进行实现,而登录接口所需要的参数,我们可以直接通过 getUserProfile 方法进行获取。
    2. 调用登录接口成功,服务端会返回用户的 token,这个 token 为当前的用户身份令牌。(拥有 token) 则表示用户已经登录了。
    3. 而此处的 token,我们需要在多个组件中进行使用,所以 token 需要被保存到 全局状态管理工具 - vuex 中,同时需要保存的还有通过 getUserProfile 获取到的用户基本信息。
    4. 而当前的用户登录状态,我们希望可以一直保存(PS:不需要每次都进行登录)。所以在登录完成后,我们需要把 token && userinfo 保存到 本地存储中
    5. 最后,为了实现 数据与组件的分离,我们需要把与 与登录相关的逻辑 都封装在 vuex 中进行。

    这些业务是 前端用户登录的标准逻辑,大家在以后的前端登录业务处理中,也可以按照此逻辑进行。

    4. 封装 action 调用登录接口

    首先我们需要先获取到用户的信息,用作登录时的请求参数:
    my-login

    <script>
    import { mapActions } from 'vuex';
    export default {
      methods: {
        ...mapActions('user', ['login']),
        /**
         * 获取用户信息
         */
        getUserInfo() {
          // 展示加载框
          uni.showLoading({
            title: '加载中'
          });
          uni.getUserProfile({
            desc: '登录后可同步数据',
            success: async (obj) => {
              // 调用 action ,请求登录接口
              await this.login(obj);
            },
            fail: () => {
              uni.showToast({
                title: '授权已取消',
                icon: 'error',
                mask: true
              });
            },
            complete: () => {
              // 隐藏loading
              uni.hideLoading();
            }
          });
        }
      }
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    api/user.js

    import request from '../utils/request';
    
    /**
     * 获取用户基本信息
     */
    export function login(data) {
      return request({
        url: '/sys/login',
        method: 'POST',
        data,
      });
    }
    
    /**
     * 微信用户授权登录,携带appid和code参数,调用后端接口获取Openid
     */
    export function loginAuth(data) {
      return request({
        url: '/wx/user/' + data.appid + '/login/',
        data: {
          code: data.code,
        },
      });
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    store/user.js

    import { login } from 'api/user';
    export default {
      namespaced: true,
      state: () => {
        return {};
      },
      actions: {
        /**
         * 完成登录
         */
        async login(context, userProfile) {
          console.log(userProfile);
          // 用户数据
          const rawData = userProfile.userInfo;
          // 调用登录接口
          const { data: res } = await login({
            signature: userProfile.signature,
            iv: userProfile.iv,
            nickName: rawData.nickName,
            gender: rawData.gender,
            city: rawData.city,
            province: rawData.province,
            avatarUrl: rawData.avatarUrl
          });
          // TODO: 登录逻辑
          console.log(res);
        }
      }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    store/index.js

    import user from './modules/user';
    
    const store = new Vuex.Store({
      modules: {
        user
      }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    5. 保存用户登录状态

    用户的登录状态需要被保存到 vuex 中,同时需要进行 本地存储

    store/user.js

    import { login } from 'api/user';
    const STORAGE_KEY = 'user-info';
    const TOKEN_KEY = 'token';
    export default {
      namespaced: true,
      state: () => {
        return {
          // 用户 token
          token: uni.getStorageSync(TOKEN_KEY) || '',
          // 用户信息
          userInfo: uni.getStorageSync(STORAGE_KEY) || {}
        };
      },
      mutations: {
        /**
         * 保存 token 到 vuex
         */
        setToken(state, token) {
          state.token = token;
          this.commit('user/saveToken');
        },
        /**
         * 保存 token 到 本地存储
         */
        saveToken(state) {
          uni.setStorage({
            key: TOKEN_KEY,
            data: state.token
          });
        },
        /**
         * 保存 用户信息 到 vuex
         */
        setUserInfo(state, userInfo) {
          state.userInfo = userInfo;
          this.commit('user/saveUserInfo');
        },
        /**
         * 保存 用户信息 到 本地存储
         */
        saveUserInfo(state) {
          uni.setStorage({
            key: STORAGE_KEY,
            data: state.userInfo
          });
        }
      },
      actions: {
        /**
         * 完成登录
         */
        async login(context, userProfile) {
          ...
          // 登录逻辑
          this.commit('user/setToken', res.token);
          this.commit('user/setUserInfo', JSON.parse(userProfile.rawData));
        }
      }
    };
    
    
      43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    6. 成已登录的用户视图

    token 存在时,表示用户已经登录了,此时需要 展示用户登录完成的视图:

    my-login

    <template>
      <view class="my-container">
        <!-- 用户未登录 -->
        <block v-if="!token">
          ...
        </block>
        <!-- 已登录 -->
        <block v-else>
          <image class="avatar avatar-img" :src="userInfo.avatarUrl" mode="scaleToFill" />
          <view class="login-desc">{{ userInfo.nickName }}</view>
          <button class="login-btn" type="default" @click="onLogoutClick">退出登录</button>
        </block>
      </view>
    </template>
    
    <script>
    import { mapState, mapActions } from 'vuex';
    export default {
      name: 'my-login',
      data() {
        return {};
      },
      computed: {
        ...mapState('user', ['token', 'userInfo'])
      },
    };
    </script>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    6. 现退出登录功能

    store/user

    export default {
      ...
      mutations: {
        ...
        /**
         * 删除 token
         */
        removeToken(state) {
          state.token = '';
          this.commit('user/saveToken');
        },
        ...
        /**
         * 删除用户信息
         */
        removeUserInfo(state) {
          state.userInfo = {};
          this.commit('user/saveUserInfo');
        }
      },
      actions: {
        ...
        /**
         * 退出登录
         */
        logout(context) {
          this.commit('user/removeToken');
          this.commit('user/removeUserInfo');
        }
      }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    my-login

    <template>
      <view class="my-container">
        ...
        <!-- 已登录 -->
        <block v-else>
        	...
            <button class="login-btn" type="default" @click="onLogoutClick">退出登录</button>
        </block>
      </view>
    </template>
    
    <script>
    export default {
      ...
      methods: {
        ...mapActions('user', ['login', 'logout']),
        ...
        /**
         * 退出登录
         */
        onLogoutClick() {
          uni.showModal({
            title: '提示',
            content: '退出登录将无法同步数据哦~',
            success: ({ confirm, cancel }) => {
              if (confirm) {
                this.logout();
              }
            }
          });
        }
      }
    };
    </script>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    相关技术文章

    点击QQ咨询
    开通会员
    返回顶部
    ×
    微信扫码支付
    微信扫码支付
    确定支付下载
    请使用微信描二维码支付
    ×

    提示信息

    ×

    选择支付方式

    • 微信支付
    • 支付宝付款
    确定支付下载