目录
本章涉及知识点:
- 使用vuex/store管理数据
- 登录注册逻辑
- Nuxt的本地存储
一 登录注册页布局
pages/user/login.vue 的布局代码如下:
<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>
export default {
data(){
return {
currentTab: 0
}
},
methods: {
//点击tab栏根据index切换状态
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>
在预留的位置导入登录组件和注册组件
二 登录功能
1.思路
- 在components/user 中新建 loginForm.vue 表单组件
- 使用 Element-ui 的表单组件
- 表单数据绑定
- 表单验证
- 登录接口
2.实现步骤
2.1 新建登录表单组件
在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>
注意:新增了组件后在pages/user/login.vue 中导入,注册即可使用。
导入位置:
<!-- 登录功能组件 -->
<loginForm v-if="currentTab == 0" />
<!-- 注册功能组件 -->
<registerForm v-if="currentTab == 1" />
2.2 表单数据绑定及验证
修改data 的 form 数据,然后使用v-model绑定到对应的表单字段。
表单验证:双向数据绑定到form字段后,我们现在可以来提交表单了,但是提交之前还需要验证下表单字段是否合法,比如不能为空。
编辑components/user/loginForm.vue
data() {
return {
// 表单数据
form: {
username: "13800138000",
password: "123456"
},
// 表单规则
rules: {
username: [
{ required: true, message: "请输入用户名", trriger: "blur" }
],
password: [
{
required: true,
message: "请输入密码",
trriger: "blur"
},
{
min: 6,
message: "密码不能小于六位",
trriger: "blur"
}
]
}
};
使用el-form-item
添加prop
属性
<el-form :model="form" ref="form" :rules="rules" class="form">
<el-form-item class="form-item" prop="username">
<el-input placeholder="用户名/手机" v-model="form.username" @focus="clearRules('username')"></el-input>
</el-form-item>
<el-form-item class="form-item" prop="password">
<el-input
placeholder="密码"
type="password"
v-model="form.password"
@focus="clearRules('password')"
></el-input>
</el-form-item>
现在可以尝试在把input
输入框的值清空,会出现在rules
中的定义的提示内容
2.3 登录接口
接下来要调用登录的接口进行登录了,如果一切正常的话,我们可以看到后台返回的用户信息,如果登录失败,我们需要对统一对错误的返回进行处理,这个我们在最后再统一实现。
改components/user/loginForm.vue
的提交登录事件:
// 提交登录
async handleLoginSubmit() {
// console.log(this.form);
// 对整个表单进行验证,如果输入合法再进行发送请求
this.$refs.form.validate(async v => {
// console.log(v);
if (v) {
// console.log(this.form);
let res = await userLogin(this.form);
console.log(res);
if (res.data.token) {
this.$message.success("登录成功");
}
} else {
this.$message.error("请输入合法内容");
}
});
},
3.总结
- 在
components/user
中新建loginForm.vue
表单组件 - 使用
Element-ui
的表单组件绑定数据和验证表单 - 调用登录接口
三 使用vuex/store管理数据
1.思路
使用vuex统一管理用户登录注册行为和用户信息
- 在 store文件夹新建user.js
- 在store/user.js中实现登录,并保存数据到store的state中
- 在头部组件中显示用户信息
2.实现步骤
2.1新建状态文件
在store
文件夹新建user.js
,并添加以下代码
// 用户管理
export const state = () => ({
// 采用接口返回的数据结构
userInfo: {
token: "",
user: {},
},
})
export const mutations = {};
export const actions = {};
2.2实现登录
登录成功将数据放到 store/user.js 中统一管理
2.3顶部组件,展示用户信息
在头部组件展示store中保存的用户数据
判断token是否存在,存在则将用户数据显示出来:头像路径需要进行处理拼接基准路径
<!-- 如果用户存在则展示用户信息,用户数据来自store -->
<el-dropdown v-if="userInfo.token">
<el-row type="flex" align="middle" class="el-dropdown-link">
<nuxt-link to="#">
<img :src="$axios.defaults.baseURL+ userInfo.user.defaultAvatar" />
{{userInfo.user.nickname}}
</nuxt-link>
<i class="el-icon-caret-bottom el-icon--right"></i>
</el-row>
<el-dropdown-menu slot="dropdown">
四 状态持久化
1. 保存store到本地localStorage
现在用户已经保存到store了,但是还有一个问题,数据是保存在变量缓存中的,如果页面一刷新,那么数据就会不见了,这样是不合理的。
所以我们需要使用localStorage
实现状态持久化,
-
概念就是每当 vuex 数据发生变化, 就存放到 localStorage 里面去
-
每当页面刷新的时候, localStorage 数据恢复到 vuex 里面
另外由于nuxtjs
是运行在服务器的,不能直接在store
中使用浏览器的localStorage方法,可以直接调用一个插件来实现以上的所有功能。
2.思路
- 监听数据变化, 每当登录完毕,
- vuex 数据发生变化,就要将数据保存到浏览器 本地 (指用户浏览器localStorage)
- 页面打开时, 会尝试将之前保存过的数据恢复到 vuex 当中即可
找个插件帮忙vuex-persistedstate
3.实现缓存信息到本地
nuxtjs
中store
不能直接使用浏览器的lcoalStorage
方法,
而且自己写数据同步功能比较麻烦,
所以我们需要依赖一个插件vuex-persistedstate
,该插件会把本地存储的数据存储到store
。
插件地址:https://github.com/robinvdvleuten/vuex-persistedstate
3.1 安装插件
npm install --save vuex-persistedstate
3.2 引入
需要创建一个 localStorage 自定义插件用来引入第三方包
以前我们引入第三方的插件时, 可以直接在 main.js 入口文件
的 new Vue 根实例创建之前, 添加代码,
nuxt 的机制是自定义插件,存放在 plugins 文件夹, 然后用配置进行引入
在根目录plugins
中新建文件localStorage.js
,加入以下代码 :
import createPersistedState from 'vuex-persistedstate'
export default ({store}) => {
window.onNuxtReady(() => {
createPersistedState({
key: "store", // 读取本地存储的数据到store
})(store)
})
}
3.3 导入插件
修改nuxt.config.js
配置文件,在plugins
配置项中新增一条数据 :
// 其他代码...
plugins: [
// 其他代码...
// 这里的引入,如果是普通字符串,就在服务端马上运行
// 如果是要等到浏览器再运行的代码,可以将配置改为对象,并且路径作为src传进去
// 如果只在浏览器加载的代码, 可以添加一个 属性 ssr: false
{ src: '@/plugins/localStorage', ssr: false }
],
// 其他代码...
如果只在浏览器加载的代码, 可以添加一个 属性 ssr: false
修改完后 重新启动项目 npm run dev 就可以了
3.4 如果不使用插件也可以实现vuex 的持久化
在default.vue页面进行store数据的管理:
mounted() {
// 不使用插件 实现vuex持久化
// 如果数据有变化,存放到localstorage
// 如果页面进入,将localStorage数据重新拿回来
// this.$store.subscribe 可以订阅 mutations
// 任意一个 mutations触发。都会在之后执行这个 subscribe 订阅的回调
this.$store.subscribe((mutation, state) => {
localStorage.setItem("vuex", JSON.stringify(state));
});
// 如果页面进入,将localStorage 数据重新拿回来
// 本来所有数据的改变通过mutations
// this.$store有一个函数例外,replaceState 传入一个数据对象即可覆盖原来的数据
const savedState = localStorage.getItem("vuex");
if (savedState) {
this.$store.replaceState(JSON.parse(savedState));
}
}
4.总结
使用vuex-persistedstate 保存vuex到本地存储
- 安装
- 创建插件文件plugins/文件夹下面
- 在nuxt.config.js的plugins配置里面引入插件,注意设置ssr为false
- 重启项目即可