思路:使用vuex对小程序进行登录状态管理,采用集中式存储管理应用的登录状态
Vuex 是什么? | Vuex
效果:
新建store文件夹,在文件夹中新建一个index.js文件和一个modules文件夹,modules文件夹中新建一个stormoduls.js文件
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import storemoduls from './modules/storemoduls'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
'storemoduls': storemoduls,
}
})
export default store
store/modules/stormoduls.js
uni.setStorageSync(key, data)设置缓存数据
uni.getStorageSync(key)获取缓存数据
export default {
namespaced: true, //命名空间
state: () => ({
token: uni.getStorageSync('token') || '',//存储的登录之后获取到的头像昵称
userinfo: uni.getStorageSync('userinfo') || '{}',//存储的登录之后获取到的头像昵称
clcl: uni.getStorageSync('clcl') || '',
}),
//提交 mutation,更改state的状态
mutations: {
updateUserInfo(state, userinfo) {
state.userinfo = userinfo
this.commit('storemoduls/saveUserInfoToStorage')
},
saveUserInfoToStorage(state) {
uni.setStorageSync('userinfo', state.userinfo)
},
updateToken(state, token) {
state.token = token
this.commit('storemoduls/saveTokenToStorage')
},
saveTokenToStorage(state) {
uni.setStorageSync('token', state.token)
},
updateclcl(state, clcl) {
state.clcl = clcl
this.commit('storemoduls/saveclclToStorage')
},
saveclclToStorage(state) {
uni.setStorageSync('clcl', state.clcl)
},
}
}
在main.js中引入
import store from './store'
Vue.prototype.$store = store
const app = new Vue({
...App,
store
})
pages.json中的tabBar里我的页面:pages/login/login
...mapState('模块的名称', ['要映射的数据名称1', '要映射的数据名称2'])
<template>
<view>
<Login v-if="!token && !clcl"></Login>
<barberucell v-else-if="token"></barberucell>
<clientucell v-if="clcl"></clientucell>
</view>
</template>
<script>
import Login from '@/components/login/login.vue'
import barberucell from '@/components/cellgroup/barberucell.vue'
import clientucell from '@/components/cellgroup/clientucell.vue'
import { mapState } from 'vuex'
export default {
data() {
return {
}
},
components: {
Login,
barberucell,
clientucell
},
computed: {
//将storemoduls模块下的token,clcl内容映射到当前页面
...mapState('storemoduls', ['token', 'clcl'])
},
}
</script>
components/login/login.vue
<template>
<view>
<view class="bg-box">
<view v-if="login" class="bg-sing">
<view class="sing-cen">
<view class="sing-ing">
<u--image radius="50px" :src="userinfo.avatarUrl" height="100px" width="100px"></u--image>
<text class="sing-tex">{{userinfo.nickName}}</text>
</view>
</view>
</view>
<view v-else class="sing-out">
<view class="sing-ing">
<u--image radius="50px"
src="https://img1.baidu.com/it/u=2673751307,2157785445&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500"
height="100px" width="100px"></u--image>
</view>
<view>
<button type="warn" size="mini" @click="Signin">客户端</button>
<button type="warn" style="margin-left: 20px;" size="mini" @click="barberSignin">用户端</button>
</view>
</view>
</view>
<u-cell-group v-for="(g,index) in grouplist" :key="index">
<u-cell icon="map" :title="g.title" :name="g.name" :value="g.value" :isLink="true" @click="cellrow()">
</u-cell>
</u-cell-group>
<u-modal :show="showcellrow" :showConfirmButton="false" width="260px">
<view class="modal-slot">
<view class="modal-img">
<u--image radius="50px"
src="https://img1.baidu.com/it/u=2673751307,2157785445&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500"
height="60px" width="60px"></u--image>
</view>
<view>欢迎使用</view>
<view class="model-p">为了您良好的体验小程序,我们需要您授权信息进行登录</view>
<view class="model-btn">
<u-button type="error" shape="circle" text="关闭" @click="closemodal"></u-button>
</view>
</view>
</u-modal>
</view>
</template>
<script>
import { mapMutations } from 'vuex'//导入mutations的辅助方法mapMutations
import { mapState } from 'vuex'//引入state的辅助函数mapState
export default {
data() {
return {
login: false,
grouplist: [{
title: "优惠劵",
name: "coupon",
value: "优惠福利"
},
{
title: "消费积分",
name: "integral",
value: "积分换礼品"
}, {
title: "我的订单",
name: "orderform",
value: ""
}
],
clientuser: {},
showcellrow: false,
}
},
computed: {
//将storemoduls模块下的userinfo的内容映射到当前页面作为计算属性来使用
...mapState('storemoduls', ['userinfo']),
},
methods: {
//将storemoduls模块下的updateUserInfo,updateclcl方法映射到当前页面
...mapMutations('storemoduls', ['updateUserInfo', 'updateclcl']),
Signin() {
wx.getUserProfile({
desc: '必须授权才能继续使用',
success: (res) => {
this.clientuser = res.userInfo
//更新updateUserInfo方法中的数据
this.updateUserInfo(this.clientuser)
//更新updateclcl方法中的数据
this.updateclcl("storemoduls")
this.login = true
this.showcellrow = false
},
fail: (err) => {
console.log('授权失败', err);
}
})
},
barberSignin() {
uni.navigateTo({
url: '/pages/login/barberlogin'
})
},
cellrow() {
this.showcellrow = true
},
closemodal() {
this.showcellrow = false
},
},
}
</script>
<style lang="scss" scoped>
.bg-box {
background-image: linear-gradient(#e66465, #8081e5);
height: 480rpx;
.sing-out {
padding-top: 50rpx;
text-align: center;
line-height: 120rpx;
.sing-ing {
display: inline-block;
}
}
.bg-sing {
padding: 10rpx;
padding-top: 50rpx;
.sing-btn {
text-align: right;
}
.sing-cen {
text-align: center;
line-height: 50rpx;
.sing-ing {
display: inline-block;
.sing-tex {
font-size: 14px;
color: white;
}
}
}
}
}
.modal-slot {
line-height: 70rpx;
text-align: center;
.modal-img {
display: inline-block;
}
.model-btn {
margin-top: 20rpx;
margin-bottom: 20rpx;
}
.model-p {
font-size: 14px;
color: #686868;
line-height: 40rpx;
}
}
</style>
/pages/login/barberlogin
<template>
<view class="barber-box">
<u-form :model="form" ref="uForm" label-width="120" :rules="rules">
<u-form-item label="用户名" prop="username">
<u-input v-model="form.username" />
</u-form-item>
<u-form-item label="密码" prop="password">
<u-input type="password" v-model="form.password" />
</u-form-item>
</u-form>
<button type="warn" @click="submit">登陆</button>
</view>
</template>
<script>
import { mapMutations, mapState } from 'vuex'
export default {
data() {
return {
form: {
username: '',
password: ''
},
rules: {
username: [{
required: true,
message: '请输入用户名',
trigger: ['blur', 'change']
}],
password: [{
required: true,
message: '请输入密码',
trigger: ['blur', 'change']
}]
},
}
},
computed: {
},
methods: {
//将storemoduls模块下的updateUserInfo,updateToken方法映射到当前页面
...mapMutations('storemoduls', ['updateUserInfo', 'updateToken']),
submit() {
this.$refs.uForm.validate().then(res => {
uni.showToast({
title: '登录成功',
});
let obj = {
avatarUrl: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
nickName: '用户端'
}
let ken = '897658767'
//更新updateToken方法中的数据
this.updateToken(ken)
//更新updateUserInfo方法中的数据
this.updateUserInfo(obj)
uni.switchTab({
url: '/pages/login/login'
})
}).catch(errors => {
uni.$u.toast('校验失败')
})
}
}
}
</script>
<style lang="scss" scoped>
.barber-box {
padding: 50rpx;
}
</style>
components/cellgroup/barberucell.vue
<template>
<view>
<view class="bg-box">
<view class="bg-sing">
<view class="sing-btn">
<button type="warn" size="mini" class="btn" @click="Logout">退出</button>
</view>
<view class="sing-cen">
<view class="sing-ing">
<u--image radius="50px" :src="userinfo.avatarUrl" height="100px" width="100px"></u--image>
<text class="sing-tex">{{userinfo.nickName}}</text>
</view>
</view>
</view>
</view>
<u-cell-group v-for="(g,index) in grouplist" :key="index">
<u-cell icon="map" :title="g.title" :name="g.name" :value="g.value" :isLink="true" @click="cellrow()">
</u-cell>
</u-cell-group>
</view>
</template>
<script>
import { mapMutations } from 'vuex'
import { mapState } from 'vuex'
export default {
data() {
return {
login: false,
grouplist: [{
title: "客户预约信息",
name: "customerappointment",
value: "信息"
},
{
title: "工作时间",
name: "workinghours",
value: "时间"
}, {
title: "客户消费",
name: "customerconsumption",
value: "消费"
},
{
title: "报表",
name: "reportforms",
value: "报表"
}
],
clientuser: {},
showcellrow: false,
}
},
computed: {
//将storemoduls模块下的userinfo的内容映射到当前页面作为计算属性来使用
...mapState('storemoduls', ['userinfo']),
},
methods: {
//将storemoduls模块下的updateUserInfo,updateToken方法映射到当前页面
...mapMutations('storemoduls', ['updateUserInfo', 'updateToken']),
Logout() {
wx.clearStorageSync(); //一键清除所有本地数据缓存
this.updateToken('')//更新updateToken方法中的数据
},
cellrow(name) {
console.log(name);
},
},
}
</script>
<style lang="scss" scoped>
.bg-box {
background-image: linear-gradient(#e66465, #8081e5);
height: 480rpx;
.sing-out {
padding-top: 50rpx;
text-align: center;
line-height: 120rpx;
.sing-ing {
display: inline-block;
}
}
.bg-sing {
padding: 10rpx;
padding-top: 50rpx;
.sing-btn {
text-align: right;
}
.sing-cen {
text-align: center;
line-height: 100rpx;
.sing-ing {
display: inline-block;
.sing-tex {
font-size: 14px;
color: white;
}
}
}
}
}
</style>
components/cellgroup/clientucell.vue
<template>
<view>
<view class="bg-box">
<view class="bg-sing">
<view class="sing-btn">
<button type="warn" size="mini" class="btn" @click="Logout">退出</button>
</view>
<view class="sing-cen">
<view class="sing-ing">
<u--image radius="50px" :src="userinfo.avatarUrl" height="100px" width="100px"></u--image>
<text class="sing-tex">{{userinfo.nickName}}</text>
</view>
</view>
</view>
</view>
<u-cell-group v-for="(g,index) in grouplist" :key="index">
<u-cell icon="map" :title="g.title" :name="g.name" :value="g.value" :isLink="true" @click="cellrow()">
</u-cell>
</u-cell-group>
</view>
</template>
<script>
import { mapMutations } from 'vuex'
import { mapState } from 'vuex'
export default {
data() {
return {
login: false,
grouplist: [{
title: "会员",
name: "member",
value: ""
},
{
title: "我的订单",
name: "orderforgoods",
value: "订单"
},
{
title: "充值",
name: "Recharge",
value: ""
}, {
title: "消费明细",
name: "details",
value: "记录"
},
{
title: "预约记录",
name: "reservation",
value: ""
},
],
}
},
computed: {
//将storemoduls模块下的userinfo的内容映射到当前页面作为计算属性来使用
...mapState('storemoduls', ['userinfo']),
},
methods: {
//将storemoduls模块下的updateUserInfo,updateclcl方法映射到当前页面
...mapMutations('storemoduls', ['updateUserInfo', 'updateclcl']),
Logout() {
wx.clearStorageSync();//一键清除所有本地数据缓存
this.updateclcl('') //更新updateclcl方法中的数据
},
cellrow(name) {
console.log(name);
},
},
}
</script>
<style lang="scss" scoped>
.bg-box {
background-image: linear-gradient(#e66465, #8081e5);
height: 480rpx;
.sing-out {
padding-top: 50rpx;
text-align: center;
line-height: 120rpx;
.sing-ing {
display: inline-block;
}
}
.bg-sing {
padding: 10rpx;
padding-top: 50rpx;
.sing-btn {
text-align: right;
}
.sing-cen {
text-align: center;
line-height: 100rpx;
.sing-ing {
display: inline-block;
.sing-tex {
font-size: 14px;
color: white;
}
}
}
}
}
</style>