10. 用户列表页面实现

从云端将用户列表读进来

  1. 安装 npm i jquery 使用ajax
  2. 页面中import $ from 'jquery';

从云端动态获取用户(使用AJAX)

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
<template>
<contentElem>用户列表</contentElem>
</template>

<script>
import contentElem from "../components/contentElem.vue";
import $ from 'jquery';
import { ref } from 'vue';
export default {
name: 'UserList',
components: {
contentElem,
},
setup(){
let users= ref([]);
$.ajax({
url:"https://app165.acapp.acwing.com.cn/myspace/userlist/",
type:"get",
success(resp){
console.log(resp);
}
});

return {
users
}
},
}
</script>

<style scoped>

</style>


使用bootstrap的 Grid system进行布局:
vue17.png
微调样式,
vue18.png
访问不存在的页面,则跳转到404:
vue19.png

给链接加上id
vue20.png
路由中需要添加参数,用:
vue21.png
对应的UserProfileView中,使用提供的useRoute接口,即可获取这个参数
vue22.png
vue23.png

11. 实现登录页面

需要双向绑定两个变量username,password
vue24.png
vue25.png
vue26.png
vue27.png
vue28.png
vue29.png
ref中的值需要.value访问
vue29.png
阻止默认行为
vue28.png

11.1 vuex

因为很多前端行为需要获得用户信息,所以要将登录的用户信息存到全局变量中——此时需要vuex
交互:
vue30.png
vuex创建的全局唯一对象:
/store/index.js
vue31.png
vue32.png
vue33.png
访问:

vue34.png

11.1.1 传统登录方式

vue35.png
存到cookie中,跨域时难处理。

11.1.2 JWT方式

json web token
vue36.png

11.2 实现登录

1
2
3
4
5
6
7
vuex:存储全局状态,全局唯一。
state: 存储所有数据,可以用modules属性划分成若干模块
getters:根据state中的值计算新的值
mutations:所有对state的修改操作都需要定义在这里,不支持异步,可以通过$store.commit()触发
actions:定义对state的复杂修改操作,支持异步,可以通过$store.dispatch()触发。注意不能直接修改state,只能通过mutations修改state。
modules:定义state的子模块

dispatch调用store中的事件
vue37.png
附注:使用ajax需要import $ from 'jquery';\

vue38.png
从获得的access字符串中解码出用户信息,需要安装一个解码包
vue39.png
然后在user.js中引入
import jwt_decode from 'jwt-decode';

使用:
const access_obj=jwt_decode(access);

纯背过:用于授权
vue40.png
vue41.png
可以成功获得现在登录的用户信息:
vue42.png
有了这些信息后,要将这些信息存到state里面:
但是action里面是不能直接更新的,要通过mutations

vue43.png
完整版user.js

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import $ from 'jquery';
import jwt_decode from 'jwt-decode';
const ModuleUser={
state: {
id:"",
username:"",
photo:"",
followerCount:"",
access:"",
refresh:"",
is_login:false,
},
getters: {
},
mutations: {
updateUser(state,user){//第一个参数是state,第二个参数是自己定义的
state.id=user.id;
state.username=user.username;
state.photo=user.photo;
state.followerCount=user.followerCount;
state.access=user.access;
state.refresh=user.refresh;
state.is_login=user.is_login;
}

},
actions: {
login(context,data){ //context 传api,data传一些信息(dispatch的参数)
$.ajax({
url:"https://app165.acapp.acwing.com.cn/api/token/",
type: "POST",
data:{
username: data.username,
password: data.password,
},
success(resp){
// console.log(resp);
// const access=resp.access;
// const refresh=resp.refresh;
const {access,refresh}=resp; //ES6语法
const access_obj=jwt_decode(access);
// console.log(access_obj,refresh);
//然后可以根据其中的user_id和我们的api去获取信息
$.ajax({
url:"https://app165.acapp.acwing.com.cn/myspace/getinfo/",
type:"GET",
data:{
user_id:access_obj.user_id,
},
headers:{
'Authorization':"Bearer "+access,
},
success(resp){
context.commit("updateUser",{
...resp,
access:access,
refresh:refresh,
is_login:true,
});
data.success();
},
error(){
data.error();
}
})

}

})
}
},
modules: {
}

};

export default ModuleUser;


LoginView.vue

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<template>
<contentElem>
<div class="row justify-content-md-center">
<div class="col-3">
<form @click.prevent="login">
<div class="mb-3">
<label for="username" class="form-label">用户名</label>
<input v-model="username" type="text" class="form-control" id="username">
</div>
<div class="mb-3">
<label for="password" class="form-label">密码</label>
<input v-model="password" type="password" class="form-control" id="password">
</div>
<div class="error-message">{{error_message}}</div>
<button type="submit" class="btn btn-primary">登录</button>
</form>
</div>
</div>

</contentElem>
</template>

<script>
import contentElem from "../components/contentElem.vue";
import { ref } from "vue";
import { useStore } from "vuex";
export default {
name: 'UserList',
components: {
contentElem,
},
setup(){
let username=ref('');
let password=ref('');
let error_message=ref('');
const store=useStore();
const login=()=>{
// console.log(username.value);
// console.log(password.value);
//如果想调用外面action中的一个api,用dispatch
store.dispatch("login",{
username:username.value,
password:password.value,
success(){
console.log("success");
},
error(){
console.log("fail");
}
})

}

return {
username,
password,
error_message,
login

}

}
}
</script>

<style scoped>
.error-message{
color: red;
}
button{
float: right;
}

</style>


11.3 使用refresh刷新access

因为5分钟access会过期,所以需要用到refresh进行刷新。

方法1. 访问的时候发现access过期了,此时去获取一个新的access
方法2. 每隔五分钟获取一次access,调用刷线access的接口,每五分钟一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
setInterval(()=>{
$.ajax({
url:"https://app165.acapp.acwing.com.cn/api/token/refresh/",
type:"POST",
data:{
refresh:access_obj.refresh,
},
success(resp){
context.commit("updateAccess",resp.access);

},
error(){
data.error();
}

});

},4.5*60*1000);



12. 登录后跳转到用户列表页面

  1. 引入router
    vue44.png

  2. 使用api
    vue45.png

13. 登录后修改展示页面

NavBar修改一下。让这些页面都符合逻辑
想要获取store中的全局变量,可以使用$ xxx
vue46.png
vue47.png

14. 实现退出

只需要写一个事件即可。
vue48.png
凡是要修改全局state,要把事件写到action/mutations里面 (需要store)
vue49.png

15. 未登录时的跳转

userList.vue
vue50.png
点击时触发函数:
vue51.png

16. 用户动态从云端获取

用户动态页面根据userId的改变而改变。
还是ajax!
vue52.png

17. 判断发帖子模块是否需要

只有在自己的页面才能发帖子。
vue53.png

18. 用完整链接判断页面是否相同

App.vue
vue54.png
默认是用页面的name判断的,都叫userprofile,所以到别人页面,再点击自己的,就会出现不刷新不跳转的情况。

19. 从前端删除到真的删除

vue55.png

vue56.png

20. 部署

  1. build 打包成可以发布的版本

vue57.png
2. 打包
vue58.png
3. 传到服务器上