Vue3+Vant开发:登录功能

🙈作者简介:练习时长两年半的Java up主

🙉个人主页:程序员老茶

🙊 ps:点赞👍是免费的,却可以让写博客的作者开心好久好久😎

📚系列专栏:Java全栈,计算机系列(火速更新中)

💭 格言:种一棵树最好的时间是十年前,其次是现在

🏡动动小手,点个关注不迷路,感谢宝子们一键三连

目录

课程名:Vue 3

内容/作用:知识点/设计/实验/作业/练习

学习:Vue3+Vant开发:登录功能

1、创建登录路由

复制代码
npm install vue-router@4

以上安装了最新版本的vue-router.

下面在src目录下面创建router目录,在该目录下面创建index.js文件,在该文件中完成路由的配置。

index.js文件中代码如下所示:()

在下面的代码中,首先从vue-router中导入createRouter以及createWebHashHistory.

createRouter用来创建路由实例

createWebHashHistory创建hash路由

Layout组件用来完成整个后台管理页面的布局。

在routes数组中,定义了相应的路由规则

js 复制代码
import { createRouter, createWebHashHistory } from "vue-router";
const routes = [
  {
    path: "/login",
    name: "login",
    component: () => import("../views/login/index.vue"),
  },
];
//创建路由实例
const router = createRouter({
  //history模式:createWebHistory
  history: createWebHashHistory(), //使用hash模式
  routes,
});
export default router;

下面在src目录下面创建views目录,在该目录下面创建login目录,然后在创建index.vue.

该组件中的内容如下所示:

vue 复制代码
<template>
  <div>登录</div>
</template>

<script>
export default {};
</script>

<style></style>

下面,返回到main.js文件中使用创建好的路由对象

js 复制代码
import { createApp } from "vue";
import App from "./App.vue";
import Vant from "vant";
import "vant/lib/index.css";
import "amfe-flexible";
import router from "./router"; //导入路由对象
createApp(App).use(Vant).use(router).mount("#app"); //使用路由

同时在App.vue文件中,添加router-view,指定路由的出口。

vue 复制代码
<template>
  <router-view></router-view>
</template>

<script setup></script>

<style></style>

在浏览器中输入http://localhost:3000/#/login查看效果。

2、实现登录布局结构

vue 复制代码
<template>
  <div class="login-container">
    <!-- 导航栏 -->
    <van-nav-bar title="登录" />
    <!-- 导航栏结束 -->
    <!-- 登录表单 -->
    <van-form>
      <van-field name="userName" placeholder="请输入用户名" />
      <van-field name="userPwd" placeholder="请输入密码" />
      <div style="margin: 16px">
        <van-button block type="primary" native-type="submit">
          提交
        </van-button>
      </div>
    </van-form>
    <!-- 登录表单结束 -->
  </div>
</template>

<script>
export default {};
</script>

<style></style>

3、登录布局实现

这里我们首先设置一下,导航栏的样式。由于很多页面都会用到导航栏,所以可以将样式定义在全局的文件中,而不是单独的定义在登录组件中。

在src目录下面创建styles目录,在该目录下面创建index.css文件,该文件中的代码如下所示:

css 复制代码
.page-nav-bar {
  background-color: #3296fa;
}
.page-nav-bar .van-nav-bar__title {/* 这里的van-nav-bar__title,可以查看原有的导航栏的样式*/
  color: #fff;
}

在登录组件的导航栏中使用该样式。(在main.js文件中导入import "./styles/index.css";)

vue 复制代码
  <van-nav-bar title="登录" class="page-nav-bar" />

下面给登录表单的文本框与密码框添加对应的图标。

对应的官网:

复制代码
https://vant-contrib.gitee.io/vant/v3/#/zh-CN/field
vue 复制代码
 <van-form>
    <van-field name="userName" placeholder="请输入用户名" left-icon="manager" />
      <van-field name="userPwd" placeholder="请输入密码"   left-icon="lock"/>
      
      </van-field>
      <div style="margin: 16px">
        <van-button block type="primary" native-type="submit"> 
          提交
        </van-button>
      </div>
    </van-form>

这里给手机号与验证码添加了left-icon设置了图标。同时设置了"发送验证码"的按钮

4、实现基本登录功能

注意:这里只是实现基本登录效果,把服务端返回的内容打印出来,不涉及到登录状态的提示与登录状态的存储操作。

首先在src目录下面创建api目录,在该目录下面创建user.js文件,该文件中封装了用户请求的相关处理模块。

js 复制代码
// 封装用户相关的请求模块
import request from "../utils/request";
export const login = (data) => {
  return request({
    method: "POST",
    url: "/user/login",
    data,
  });
};

下面修改login.vue组件中的内容

vue 复制代码
  <div class="login-container">
    <!-- 导航栏 -->
    <van-nav-bar title="登录" class="page-nav-bar" />
    <!-- 导航栏结束 -->

    <!-- 登录表单 -->

    <van-form @submit="onSubmit">
      <van-field
        name="userName"
        placeholder="请输入用户名"
        v-model="userName"
        left-icon="manager"
        :rules="userFormRules.userName"
      />
     <van-field
        name="userPwd"
        placeholder="请输入密码"
        v-model="userPwd"
        left-icon="lock"
        :rules="userFormRules.userPwd"
      >
      </van-field>
      <div style="margin: 16px">
        <van-button block type="primary" native-type="submit">
          登录
        </van-button>
      </div>
    </van-form>
    <!-- 登录表单结束 -->
  </div>

给每个van-field绑定了v-model,同时给van-form添加了@submit事件。

js 复制代码
<script>
import { reactive, toRefs } from "vue";
import { login } from "../../api/user"; //导入login方法,进行请求的发送

function useSubmit(user) {
const onSubmit = async () => {
    //1、获取表单数据
    //2、表单验证
    //3、提交表单请求
    Toast.loading({
      message: "登录中...",
      forbidClick: true, //禁用背景点击
      duration: 0, //持续时间,默认是2000毫秒,如果为0则持续展示
    });
    const res = await login(user);
    if (res.data.code === 0) {
      store.commit("setUser", res.data);
      Toast.success("用户登录成功");
    } else {
      Toast.fail("用户名或密码错误");
    }

    //4、根据请求响应结果处理后续操作。
  };
  return {
    onSubmit,
  };
}
export default {
  setup() {
   const user = reactive({
      userName: "", //用户名
      userPwd: "", //用户密码
    });
  
    return {
      ...toRefs(user),
      ...useSubmit(user),
  
    };
  },
};
</script>

在setup方法中,定义user响应式对象,最后返回。同时将外部定义的useSubmit方法进行调用。

5、登录状态提示

js 复制代码
const onSubmit = async () => {
    //1、获取表单数据
    //2、表单验证
    //3、提交表单请求
    Toast.loading({
      message: "登录中...",
      forbidClick: true, //禁用背景点击
      duration: 0, //持续时间,默认是2000毫秒,如果为0则持续展示
    });
    const res = await login(user);
    if (res.data.code === 0) {
      store.commit("setUser", res.data);
      Toast.success("用户登录成功");
    } else {
      Toast.fail("用户名或密码错误");
    }

    //4、根据请求响应结果处理后续操作。
  };
  return {
    onSubmit,
  };
}

这里使用了Toast组件,同时需要进行导入:

js 复制代码
import { Toast } from "vant";

由于网络比较快,可能看不到登录中...这个提示,所以可以把网络设置慢一些。

可以修改NetWork中的No throttling中的Slow 3G

6、表单验证功能

在setup函数中定义校验规则,并且将其返回。

js 复制代码
setup() {
    const user = reactive({
      userName: "", //用户名
      userPwd: "", //用户密码
    });
    //定义校验规则
   const userFormRules = {
      userName: [{ required: true, message: "请填写用户名" }],
      userPwd: [
        {
          required: true,
          message: "请填写密码",
        },
           {
          pattern: /^\d{6}$/,
          message: "密码格式错误",
        },
      ],
    };
    return {
      ...toRefs(user),
      ...useSubmit(user),
      userFormRules, //返回校验规则
    };
  },

在表单中使用校验规则:

vue 复制代码
     <van-field
        name="userName"
        placeholder="请输入用户名"
        v-model="userName"
        left-icon="manager"
        :rules="userFormRules.userName"
      />
     <van-field
        name="userPwd"
        placeholder="请输入密码"
        v-model="userPwd"
        left-icon="lock"
        :rules="userFormRules.userPwd"
      >
      </van-field>

7、处理用户Token

用户登录成功以后,会返回token数据。

Token是用户登录成功之后服务端返回的一个身份令牌,在项目中经常要使用。

例如:访问需要授权的API接口。

校验页面的访问权限等。

同时,这里我们还需要将token数据进行存储,这样在访问其它的页面组件的时候,就可以获取token数据来进行校验。

关于token数据存储在哪儿呢?

可以存储到本地:

存储到本地的问题是,数据不是响应式的。

存储到Vuex中,获取方便,并且是响应式的。但是存储到Vuex中也是有一定的问题的,就是当我们刷新浏览器的时候,数据就会丢失,所以还是需要把token数据存放到本地,存储到本地的目的就是为了进行持久化。

所以这里我们需要在登录成功以后,把token数据存储到vuex中,这样可以实现响应式,在本地存储就是为了解决持久化的问题。

安装最新版本的Vuex

复制代码
npm install vuex@next --save

下面在src目录下面创建store目录,在store目录中index.js文件,该文件中的代码如下所示:

js 复制代码
import { createStore } from "vuex";
const store = createStore({
  state: {
    //存储当前登录用户信息,包含token等数据
    user: null,
  },
  mutations: {
    setUser(state, data) {
      state.user = data;
    },
  },
});
export default store;

在上面的代码中,创建了store容器,同时指定了state对象,在该对象中定义user属性存储登录用户信息。

在mutations中定义setUser方法,完成用户信息的更新。

下面,要实现的就是,当登录成功以后,更新user这个状态属性。

当然,这里首先要做的就是把store注入到Vue的实例中。

js 复制代码
import { createApp } from "vue";
import App from "./App.vue";
import Vant from "vant";
import "vant/lib/index.css";
import "amfe-flexible";
import "./styles/index.css";
import router from "./router";
import store from "./store"; //导入store
createApp(App).use(Vant).use(router).use(store).mount("#app"); //完成store的注册操作

在main.js文件中,我们导入了store,并且注册到了Vue实例中。

下面返回到views/login/index.vue页面中,把登录的信息存储到store容器中。

js 复制代码
import { reactive, toRefs, ref } from "vue";
import { login, sendSms } from "../../api/user";
import { Toast } from "vant";
import { useStore } from "vuex"; //导入useStore

在上面的代码中导入useStore.

js 复制代码
export default {
  setup() {
    const loginForm = ref();
    //获取store
    const store = useStore();

在setup函数中,调用useStore方法,获取store容器。

js 复制代码
 return {
      ...toRefs(user),
      ...useSubmit(user, store),//在调用useSubmit方法的时候传递store容器
      userFormRules,
      loginForm,
    };
js 复制代码
//用户登录
function useSubmit(user, store) {
  const onSubmit = async () => {
    //1、获取表单数据
    //2、表单验证
    //3、提交表单请求
    Toast.loading({
      message: "登录中...",
      forbidClick: true, //禁用背景点击
      duration: 0, //持续时间,默认是2000毫秒,如果为0则持续展示
    });
    const res = await login(user);
    if (res.data.code === 0) {
      store.commit("setUser", res.data);
      Toast.success("用户登录成功");
    } else {
      Toast.fail("用户名或密码错误");
    }

    //4、根据请求响应结果处理后续操作。
  };
  return {
    onSubmit,
  };
}

登录成功以后,获取到返回的数据,同时调用store中的commit方法完成数据的保存

现在,我们虽然把登录成功的数据,存储到Vuex中,但是当我们刷新浏览器的时候,Vuex中的数据还是会丢失的。所以这里,我们还需要将其存储到本地中。

下面修改一下store/index.js文件中的代码:

js 复制代码
import { createStore } from "vuex";
const TOKEN_KEY = "TOUTIAO_USER";
const store = createStore({
  state: {
    //存储当前登录用户信息,包含token等数据
    // user: null,
    user: JSON.parse(window.localStorage.getItem(TOKEN_KEY)),
  },
  mutations: {
    setUser(state, data) {
      state.user = data;
      window.localStorage.setItem(TOKEN_KEY, JSON.stringify(state.user));
    },
  },
});
export default store;

在mutations中的setUser方法中,将登录成功的用户数据存储到了localStorage中,在存储的时候,将数据转成了字符串。

同时在state中获取数据的时候,就从localStorage中获取,当然获取的时候,再将其转换成对象的形式。

下面,我们可以在App.vue中做一下测试:

vue 复制代码
<template>
  <div>
    <router-view></router-view>
  </div>
</template>

<script>
import { useStore } from "vuex";
export default {
  setup() {
    const store = useStore();
    console.log(store.state.user);
  },
};
</script>

<style></style>

通过查看浏览器的控制台,可以查看到对应的登录用户的token数据

8、封装本地存储操作

在我们的项目中,有很多的地方都需要获取本地存储的数据,如果每次都写:

复制代码
JSON.parse(window.localStorage.getItem(TOKEN_KEY)),
window.localStorage.setItem(TOKEN_KEY, JSON.stringify(state.user));

就比较麻烦了。所以这里我们建议把操作本地数据单独的封装到一个模块中。

在utils目录下面创建storage.js文件,该文件中的代码如下所示:

js 复制代码
// 存储数据
export const setItem = (key, value) => {
  //将数组,对象类型的数据转换为JSON格式的字符串进行存储
  if (typeof value === "object") {
    value = JSON.stringify(value);
  }
  window.localStorage.setItem(key, value);
};
//获取数据
export const getItem = (key) => {
  const data = window.localStorage.getItem(key);
  //这里使用try..catch的,而不是通过if判断一下是否为json格式的字符串,然后在通过parse进行转换呢,目的就是是为了方便处理,因为对字符串进行判断看一下是否为json格式的字符串,比较麻烦一些。还需要通过正则表达式来完成。而通过try..catch比较方便
  // 如果data不是一个有效的json格式字符串,JSON.parse就会出错。
  try {
    return JSON.parse(data);
  } catch (e) {
    return data;
  }
};
//删除数据
export const removeItem = (key) => {
  window.localStorage.removeItem(key);

下面返回到store/index.js文件中,修改对应的代码,这里使用我们上面封装好的代码。

js 复制代码
import { createStore } from "vuex";
import { getItem, setItem } from "../utils/storage";
const TOKEN_KEY = "TOUTIAO_USER";
const store = createStore({
  state: {
    //存储当前登录用户信息,包含token等数据
    // user: null,
    // user: JSON.parse(window.localStorage.getItem(TOKEN_KEY)),
    user: getItem(TOKEN_KEY),
  },
  mutations: {
    setUser(state, data) {
      state.user = data;
      setItem(TOKEN_KEY, state.user);
      // window.localStorage.setItem(TOKEN_KEY, JSON.stringify(state.user));
    },
  },
});
export default store;

在上面的代码中,我们导入getItem和setItem两个方法,然后在存储登录用户信息,和获取登录用户信息的时候,直接使用这两个方法,这样就非常简单了。

下面返回浏览器进行测试。

把以前localStorage中存储的内容删除掉。

然后重新输入用户名和密码,发现对应的localStorage中存储了对应的数据。

总结

感谢小伙伴们一键三连,咱们下期文章再见~

往期专栏
Java全栈开发
数据结构与算法
计算机组成原理
操作系统
数据库系统
物联网控制原理与技术
相关推荐
陈随易6 小时前
Postman 被曝自动往 Claude Code 和 Codex 装插件
前端·后端·程序员
Dream-Y.ocean8 小时前
鸿蒙PC平台宅匠 3D 室内设计适配实战:基于 Electron 壳方案的 Three.js 双渲染引擎与参数化户型编辑器开发
javascript·3d·harmonyos
Csvn9 小时前
性能监控
前端
Highcharts.js9 小时前
Highcharts Gantt使用符号的自定义数据标签开发甘特图示例
javascript·甘特图·highcharts·图表开发·实战代码·响应式图表
Csvn10 小时前
构建工具
前端
FRing0310 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
Java小卷11 小时前
JuanForm vs FormCreate!Vue3 表单引擎联动配置 PK!
vue.js·低代码
kyriewen12 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
IT_陈寒13 小时前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端
工控丫丫13 小时前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库