目录
登录态校验
通过 beforeEach 路由导航守卫实现 (to 从哪来,from:去哪, next执行)
通过to.path 判断要去的页面 为个人中心,编辑个人信息,收藏 做拦截
判断vuex中 isLogin是否为登录 true不做拦截 false跳转到登录页
如果为null 跳转登录页 同时调取接口校验是否登录 通过commi同步vuex管理的状态
import { createRouter, createWebHashHistory, } from "vue-router";
import routes from './routes';
const router = createRouter({
//createWebHistory-->History路由 createWebHashHistory-->HASH路由
//基于Hash指定模式
history: createWebHashHistory(),
routes,
})
import store from '../store/index'
import { CheckLogin } from '../api/index'
import { Toast } from 'vant'
//路由前置导航守卫 to去哪 from从哪来 next必须执行
router.beforeEach(async (to, from, next) => {
//个人中心,编辑个人信息,收藏
const arr = ['/person', '/update', '/store']
if (arr.includes(to.path)) {
//校验是否登录
let isLogin = store.state.isLogin
if (isLogin) {
next();
return
}
if (isLogin == false) {
Toast('小主,请先登录哦~')
next('/login')
return
}
if (isLogin == null) {
// 不可以派发任务 只会执行一次,应该发送请求访问
// store.dispatch('changeIsLoginAsync')
try {
let { code, data } = await CheckLogin()
if (code != 0) {
Toast('小主,请先登录哦~')
next('/login')
return
}
store.commit('changeIsLogin', true)
store.commit('changeInfo', data)
next()
} catch (err) { }
return
}
return
}
next()
})
export default router
header组件
首页header组件
通过 计算属性 决定头象的显示
增加代码严谨性在初次渲染完毕后校验vuex状态是否为空 为空派发任务更新状态
<template>
<header class="header-box">
<div class="left">
<div class="time">
<span>{{ time.day }}</span>
<span>{{ time.month }}</span>
</div>
<h1 class="title">知乎日报</h1>
</div>
<div class="pic-box">
<router-link :to="`/person`"> <img :src="pic" alt="" /></router-link>
</div>
</header>
</template>
<script>
import { reactive, ref, toRefs, computed, onBeforeMount } from "vue";
import { formatTime } from "../assets/utils";
import timg from "../assets/images/timg.jpg";
import { useStore } from "vuex";
export default {
name: "Header",
setup() {
//状态
let state = reactive({
today: formatTime(null, "{0}{1}{2}"),
});
const store = useStore();
// 派发获取登录状态和用户信息的方法
onBeforeMount(() => {
let { isLogin, info } = store.state;
if (isLogin === null) store.dispatch("changeIsLoginAsync");
if (info === null) store.dispatch("changeInfoAstnc");
});
//基于计算属性,处理时间
let time = computed(() => {
let { today } = state;
let [month, day] = formatTime(today, "{1}-{2}").split("-");
let newMonth = month.slice(1, 2);
let arr = [
"",
"一",
"二",
"三",
"四",
"五",
"六",
"七",
"八",
"九",
"十",
"十一",
"十二",
];
return {
day,
month: arr[newMonth] + "月",
};
});
//通过计算属性,决定头像
let pic = computed(() => {
let { isLogin, info } = store.state;
if (isLogin && info) {
return info.pic || timg;
}
return timg;
});
return {
...toRefs(state),
time,
pic,
};
},
};
</script>
<style lang="less" scoped>
个人中心
实现安全退出 应该清除token vuex 跳转到首页
replace和piush的区别 :piush为压栈增加一条历史记录,返回上一级,replace为替换返回两级
<template>
<Nav></Nav>
<div class="base-info" v-if="info">
<router-link :to="`/Update`">
<img :src="info.pic" alt="" />
</router-link>
<p>{{ info.name }}</p>
</div>
<van-cell-group>
<van-cell title="我的收藏" is-link url="#/store"></van-cell>
<van-cell title="退出登录" @click="signout"></van-cell>
</van-cell-group>
</template>
<script>
import { computed, onBeforeMount } from "vue";
import { useRouter } from "vue-router";
import { useStore } from "vuex";
import { Toast } from "vant";
import Nav from "../components/Nav.vue";
export default {
name: "Person",
setup() {
const router = useRouter();
const store = useStore();
//清除token、 清空vuex状态
const signout = () => {
Toast("小主,您已安全退出");
localStorage.removeItem("token");
store.commit("changeIsLogin", null);
store.commit("changeInfo", null);
router.replace("/login");
};
// 派发获取登录状态和用户信息的方法
onBeforeMount(() => {
let { isLogin, info } = store.state;
if (isLogin === null) store.dispatch("changeIsLoginAsync");
if (info === null) store.dispatch("changeInfoAstnc");
});
//通过计算属性,获取用户信息
let info = computed(() => {
let { isLogin, info } = store.state;
if (isLogin && info) {
return info;
}
return null;
});
return { signout, info };
},
components: { Nav },
};
</script>
<style lang="less" scoped>
.base-info {
img {
width: 80px;
height: 80px;
display: block;
margin: 10px auto;
border-radius: 50%;
}
p {
text-align: center;
}
}
</style>
修改个人信息
api
使用FormData 格式发送
//修改用户信息
export const Userupdate = (username, file) => {
let fm = new FormData()
fm.append('username', username)
fm.append('file', file);
return axios.post('/api/user_update', fm)
}
van-uploader组件 返回file文件对象
<template>
<Nav></Nav>
<div class="from-box">
<van-cell-group inset>
<van-field v-model="name" label="用户名" label-width="60px"></van-field>
<van-field label="用户头像" label-width="60px">
<template #input>
<van-uploader v-model="pic" max-count="1"></van-uploader>
</template>
</van-field>
</van-cell-group>
<div style="margin: 20px 40px">
<van-button round block type="primary" @click="submit"
>修改信息
</van-button>
</div>
</div>
</template>
<script>
import { useStore } from "vuex";
import { reactive, toRefs } from "vue";
import { Toast } from "vant";
import { useRouter } from "vue-router";
import Nav from "../components/Nav.vue";
import { Userupdate } from "../api/index";
export default {
components: { Nav },
name: "UpdataPerson",
setup() {
const router = useRouter();
const store = useStore();
let { name } = store.state.info;
let state = reactive({
name,
pic: [],
});
const submit = async () => {
let { name, pic } = state;
//格式检验
let reg = /^[\w\u4e00-\u9fa5]+$/;
if (!reg.test(name)) {
Toast("小主,用户名输入错误~");
return;
}
if (pic.length == 0) {
Toast("小主,必须上传一张图片~");
return;
}
console.log(pic[0].file);
let { code, data } = await Userupdate(name, pic[0].file);
if (code != 0) {
Toast("小主,信息修改失败,请稍后再试~");
return;
}
Toast("小主太棒了,信息修改成功");
store.commit("changeInfo", data);
router.replace("/person");
};
return {
...toRefs(state),
submit,
};
},
};
</script>
FormData
1.创建一个空对象
var formData = new FormData();//通过append方法添加数据
2、使用已有表单来初始化对象
//表单示例
<form id="myForm" action="" method="post">
<input type="text" name="name">名字
<input type="password" name="psw">密码
<input type="submit" value="提交">
</form>
//方法示例
// 获取页面已有的一个form表单
var form = document.getElementById("myForm");
// 用表单来初始化
var formData = new FormData(form);
// 我们可以根据name来访问表单中的字段
var name = formData.get("name"); // 获取名字
var psw = formData.get("psw"); // 获取密码
// 当然也可以在此基础上,添加其他数据
formData.append("token","kshdfiwi3rh");
formData里面存储的数据是以健值对的形式存在的,key是唯一的,一个key可能对应多个value。
如果是使用表单初始化,每一个表单字段对应一条数据,它们的HTML name属性即为key值,它们value属性对应value值。
FormData操作方法
- formData.append:添加数据
- formData.set 设置值
- formData.has 判断是否存在对应数据
- delete(key)删除数据
//通过get(key)/getAll(key)来获取对应的value
formData.get("name"); // 获取key为name的第一个值
formData.getAll("name"); // 返回一个数组,获取key为name的所有值
//通过append(key, value)来添加数据,如果指定的key不存在则会新增一条数据,如果key存在,则添加到数据的末尾
formData.append("k1", "v1");
formData.append("k1", "v2");
formData.append("k1", "v3");
formData.get("k1"); // "v1"
formData.getAll("k1"); // ["v1","v2","v3"]
//set(key, value)来设置修改数据,如果指定的key不存在则会新增一条,如果存在,则会修改对应的value值
formData.append("k1", "v1");
formData.set("k1", "1");
formData.getAll("k1"); // ["1"]
//has(key)来判断是否对应的key值
formData.append("k1", "v1");
formData.append("k2",null);
formData.has("k1"); // true
formData.has("k2"); // true
formData.has("k3"); // false
//delete(key)删除数据
formData.append("k1", "v1");
formData.append("k1", "v2");
formData.append("k1", "v1");
formData.delete("k1");
formData.getAll("k1"); // []