logo

前言

主要记录我在开发这个小说网项目的使用的代码块,方便忘记之后复用和分析

配置

本项目配置了

1.Element Plus 的全局方式

2.阿里ico图标

3.pinna的插件 持久化存储

vue 项目 页面刷新404问题

vue页面访问正常,但是一刷新就会404的问题解决办法:

第一种解决方法:

将vue路由模式mode: ‘history’ 修改为 mode: ‘hash’

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
//router.js文件



const router = new Router({



//mode: 'history',



mode: 'hash',



routes: [



{ path: '/', redirect: '/login' },



{ path: '/login', component: Login },



]



})

第二种解决方法:

在服务器Nginx配置文件里,添加如下代码,再刷新就OK了

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
location / {



try_files $uri $uri/ @router;



index index.html;



}







location @router {



rewrite ^.*$ /index.html last;



}

nginx配置跨域的参数

1
2
3
4
5
6
  #REWRITE-END
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}

插入的位置应该在location /块内的顶部。配置完成后,保存并重新加载Nginx配置。这样,来自任何来源的请求都将允许访问该资源。

请注意,这只是一个简单的配置示例,允许来自所有来源的请求。如果你只想允许特定的域名或IP地址访问,你可以将'Access-Control-Allow-Origin'的值设置为相应的域名或IP地址。

代码分析

api代码块分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import request from "@/utils/http";
export function getFictionAPI(id){
return request({
url: '/fiction/fictionid',
params: {
id
}
})
}
export const getCategoryAPI = (params) => {
return request({
url: '/fiction/list',
method: 'GET',
params
});
};

这个代码主要是使用的是api发送的两种格式 第一种传入接口 第二种传入对象;

api在vue组件里面的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { onMounted,ref } from 'vue'
import { getCategoryAPI } from '/src/apis/fictionAPI'
import {useRoute} from "vue-router";
const route = useRoute()
const fictionList = ref([])
const fictiontotal = ref('')

const data = ref({
page:route.params.id,
size:10,
bigclass:route.params.bigclass,
classify:route.params.classify
})

const getFiction = async () =>{
const res = await getCategoryAPI(data.value)
fictionList.value = res.data
fictiontotal.value = res.total
}

onMounted(() => {
getFiction()
});

此方法是传入对象类型的 这个可以去参考路由表

还有一种方法是api里面套用api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import{getcontentAPI} from "/src/apis/contentAPI";
import{getFictionAPI} from "@/apis/fictionAPI";

import {useRoute} from "vue-router";
import {ref, computed, onMounted, watch} from "vue";
const route = useRoute()
const contentData = ref({})
const fictionData = ref({})

const getcontent = async () =>{
const res = await getcontentAPI(route.params.id)
contentData.value = res.data
text.value = res.data.content
const fictionId = res.data.fictionId;
await getfiction(fictionId); // 将fictionId作为参数传递给getfiction函数
}
const getfiction = async (fictionId) => { // 接收fictionId作为参数
const res = await getFictionAPI(fictionId);
fictionData.value = res.data;
}
onMounted(() => {
getcontent();
});

监控路由变化进行跳转

路由变化后应该进行跳转 我在设计的时候有两个思路 第一使用watch进行监测路由 第二监测实行跳转并且回到最开始的位置

x:0,y:0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const reloadPage = () => {
// 执行刷新页面的逻辑,例如重新加载数据或重新渲染组件等
// ...
location.reload(); // 刷新页面
};

watch(
() => route.params.id,
(newId, oldId) => {
// 在 id 参数变化时执行刷新页面的操作
console.log('id 参数变化了:', newId);
// 执行刷新页面的逻辑,例如重新加载数据或重新渲染组件等
reloadPage();
window.scrollTo(0, 0);//加入后可以回到原始位置
}
);

如果你想要同时监控多个参数的变化,可以使用 watch 函数来实现。在 Vue 3 中,可以在组件的 setup 函数中使用 watch 函数来监听多个参数的变化。

下面是一个示例,展示如何监控多个参数的变化:

1
2
3
4
5
6
7
8
9
10
11
12
13
watch(
() => ({
bigclass: route.params.bigclass,
classify: route.params.classify,
id: route.params.id,
}),
(newParams, oldParams) => {
console.log('参数变化了:', newParams);
// 执行其他操作...
reloadPage();
window.scrollTo(0, 0);//加入后可以回到原始位置
}
);

刷新页面是数据进行了更新,但是应该还得回到首页 所以应该在组件加入每次刷新回到最开始

1
2
3
4
5
6
7
import {onMounted} from "vue";
function created(){
window.scrollTo(0, 0);
}
onMounted(() => {
created();
});

vue路由表知识点

1
2
3
4
{
path: '/category/:bigclass/:id/:classify?',
component:Category
},

后面加?可以是可选参数

这些都可以通过路由的 route.params.你命名的变量 进行调用

路由跳转链接

1
<router-link :to="'/detail/'+item.fictionId" class="link"> </router-link>

在上面的示例中,我们使用了:来表示to属性是一个动态绑定,然后使用插值表达式'/detail/' + item.fictionId来拼接字符串。

确保item.fictionId是一个在你的数据中存在的属性,这样才能正确获取到该值进行拼接。

在js中如何写路由跳转

在 Vue 3 的 Composition API 中,使用 useRoute() 不能直接获取路由对象,而是通过 useRouter() 来获取路由实例。请使用以下方式修改代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
javascriptCopy codeimport { useRouter } from 'vue-router';

export default {
setup() {
const router = useRouter();

const handlePageChange = (currentPage) => {
console.log('当前页码:', currentPage);

// 构造新的路由路径
const newRoute = {
path: `/your-path/${currentPage}`, // 新的路由路径,将 currentPage 作为路径的一部分
};

// 使用 router.push() 方法进行路由跳转
router.push(newRoute);
};

return {
handlePageChange,
};
},
};

在上述代码中,我们通过 useRouter() 获取路由实例,并将其赋值给 router 变量。然后,在 handlePageChange 方法中,使用 router.push() 进行路由跳转。

ref知识

一个 ref 对象,你可以使用 .value 访问它的值

一个 ref 字符串,你可以直接使用

目前我理解的是这样

  • ref 用于包装单个的值,通过 .value 属性访问和修改其值。
  • reactive 用于包装整个对象,返回一个代理对象,通过访问和修改代理对象的属性来实现响应式。

通常情况下,当你只需要处理单个值时,可以使用 ref;当你需要处理一个复杂的对象时,可以使用 reactive

reactive

1
2
3
4
const form = reactive({
username: '',
password: '',
})

多个api按照条件调用

1
2
3
4
5
6
7
8
9
10
11
onMounted(() => {
rankinglist.value = route.params.rankinglist;
if(rankinglist.value === 'collect'){
getfictioncollect();
}else if(rankinglist.value === 'click'){
getfictionclick();
}else if (rankinglist.value === 'recommend'){
getRecommendpage();
}

});

核心实现思路

v-for如果id=1和id=2 内容不一样

如果在v-for循环中的不同元素需要展示不同的内容或具有不同的样式,你可以使用条件语句(如v-ifv-elsev-show)来根据元素的属性或条件进行渲染。

以下是示例代码,展示如何在v-for循环中根据元素的属性进行不同的渲染:

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
htmlCopy code<template>
<div>
<div v-for="item in items" :key="item.id">
<div v-if="item.id === 1">
<!-- 第一个元素的内容 -->
</div>
<div v-else-if="item.id === 2">
<!-- 第二个元素的内容 -->
</div>
<div v-else>
<!-- 其他元素的内容 -->
</div>
</div>
</div>
</template>

<script>
export default {
data() {
return {
items: [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
// ...
]
};
},
// 其他选项...
};
</script>

在上述示例中,我们在v-for循环中的每个元素根据item.id的值使用条件语句来决定展示不同的内容。通过使用v-ifv-else-ifv-else指令,我们可以根据元素的属性进行不同的渲染。

你可以根据实际需求在相应的条件语句中编写不同的内容,例如展示不同的HTML结构、应用不同的样式或执行不同的逻辑。

这样,你就可以在v-for循环中根据元素的属性或条件展示不同的内容。根据你的具体需求,可以自由调整条件语句和对应的渲染逻辑。

也可以使用index

xxxxxxxxxx @RestControllerAdvicepublic class GlobalException {​ // 拦截:未登录异常 @ExceptionHandler(NotLoginException.class) public SaResult handlerException(NotLoginException e) {​ // 打印堆栈,以供调试 e.printStackTrace(); ​ // 返回给前端 return SaResult.error(e.getMessage()); } }java

1
2
3
4
5
6
7
8
9
const propss = defineProps({
href:{
type: String,
},
bclass:{
type: String,
},
})

刚开始让我感到奇怪的是,我好像不用变量去接收,在template里也能正常使用。

那我还用变量接收干啥呢?这个API的返回值有毛线用啊?

image.png

image.png

也不用像React那样变量前面都得加一个props.才可以访问,也没有结构去拿。这么方便吗?

4.恍然大悟

原来在script标签里直接拿属性用是拿不到的……

image.png

image.png

这里变量名不一定非得是props,js可并没有规定不允许汉字作为变量名哦

xxxxxxxxxx @RestControllerAdvicepublic class GlobalException {​ // 拦截:未登录异常 @ExceptionHandler(NotLoginException.class) public SaResult handlerException(NotLoginException e) {​ // 打印堆栈,以供调试 e.printStackTrace(); ​ // 返回给前端 return SaResult.error(e.getMessage()); } }java

element-puls分页的几个小提示

:current-page="newcurrentPage" 这个是默认页的时候,如果页面有刷新 应该首先使用这个

vscode问题

瞎报错误

关掉所有检测就好 具体参考这篇文章

解决VS code代码爆红的问题(VUE)_vscode代码显示红色_哥哥好棒棒的博客-CSDN博客

引入iconfont图标

参考这篇文章

Vue3 + Vite + TS项目引入iconfont图标(Svg方式)-阿里云开发者社区 (aliyun.com)

vue的键盘监测

1
2
3
4
5
6
7
onMounted(() => {
getcontent();
window.addEventListener('keydown', handleKeydown.bind(this));
});
onBeforeMount(() => {
window.removeEventListener('keydown', handleKeydown);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const handleKeydown = (event) => {
// handle your keydown event here
if (event.key=='ArrowLeft') {
const newRoute = {
path: `/read/${route.params.id-1}`// 新的路由路径,将 currentPage 作为路径的一部分
};
router.push(newRoute);

} else if (event.key=='ArrowRight') {
const id = Number(route.params.id);
const newRoute = {
path: `/read/${id+1}`// 新的路由路径,将 currentPage 作为路径的一部分
};
router.push(newRoute);
}
};

vue最新的键盘监测

axios对于txt文件进行转码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const getcontent = async () =>{
const res = await getcontentAPI(route.params.id)
contentData.value = res.data
const url = res.data.content;
const txtResponse = await axios.get(url, { responseType: "arraybuffer" });

// 将返回的数据视为 ArrayBuffer,然后进行解码
const decoder = new TextDecoder("GBK");
const decodedText = decoder.decode(new Uint8Array(txtResponse.data));

text.value = decodedText;
const fictionId = res.data.fictionId;
await getfiction(fictionId); // 将fictionId作为参数传递给getfiction函数
}

通过将 responseType 设置为 "arraybuffer",响应数据将以 ArrayBuffer 的形式返回。然后,你可以使用 TextDecoder 解码这个 ArrayBuffer。

确保你在解码之前提供了正确的编码方式,这里示例中使用的是 "utf-8"。如果你知道文本文件使用的是其他编码方式,可以相应地更改解码器的参数。

请注意,这种方法假设返回的数据是有效的 ArrayBuffer,并且使用了正确的编码方式。如果数据类型或编码方式不正确,可能仍然会导致解码错误。

pinia的使用

博客主页_WEB前端_前端课程_前端学习路线_小鹿线 (xuexiluxian.cn)

关于图片组件

因为写了很多图书的效果组件 最后统一去书架的那个去复制

消息弹出框(饿了么的)

1
2
3
4
ElMessage({
message: login.password,
type: 'success',
});

不能使用ref 只能使用reactive

传参数

在发json请求适合 新建的两种响应式必须是单引号 双引号会报错

1
password: '',

关于pinna持久化插件临时失效

这个应该是和路由撞了或者是莫名其妙的原因,只能所有的用最原始方法开始实现

localStorage 如何存储JSON数据并读取JSON数据

localStorage是HTML5提供的再客户端实现本地存储的一种方法,但是localStorage方法只能存储字符串数据,有时候我们需要存储对象到本地比如:JSON;那么,localStorage怎么才能实现JSON数据的存储与读取呢?

思路:既然localStorage只能存储字符串数据,那么我们就可以先把JSON对象转换成字符串,然后用localStorage方法存储起来;等到需要用到这些JSON数据时,先把它们读取出来,然后再转换成JSON对象加以利用。

具体代码如下:

1
2
3
4
5
6
7
8
9
var jsonData = {'name': '张三', 'age': 29}; // 定义一个JSON对象
var str_jsonData = JSON.stringify(jsonData);
console.log(typeof(str_jsonData)); // string
localStorage.setItem('localData', str_jsonData); // 存储字符串数据到本地
var getLocalData = localStorage.getItem('localData'); // 读取字符串数据
console.log(typeof(getLocalData)); // string
var jsonObj = JSON.parse(getLocalData);
console.log(typeof(jsonObj)); // obj
console.log(jsonObj.age); // 29

扩展:

stringify()用于从一个对象解析出字符串;

parse()用于从一个字符串中解析出json对象。

下面的代码片段访问了当前域名下的本地 Storage 对象,并通过 Storage.setItem() 增加了一个数据项目。

JSCopy to Clipboard

1
localStorage.setItem('myCat', 'Tom');

该语法用于读取 localStorage 项,如下:

JSCopy to Clipboard

1
let cat = localStorage.getItem('myCat');

该语法用于移除 localStorage 项,如下:

JSCopy to Clipboard

1
localStorage.removeItem('myCat');

该语法用于移除所有的 localStorage 项,如下:

JSCopy to Clipboard

1
2
// 移除所有
localStorage.clear();