本篇文章主要是,使用 vite 創(chuàng)建一個(gè)vue3 書(shū)籍商城的小型案例,項(xiàng)目中主要運(yùn)用到路由router及接口axios等知識(shí)點(diǎn)。
1.開(kāi)始搭建項(xiàng)目框架,使用vite來(lái)構(gòu)建項(xiàng)目
npm create vite@latest
2.由于vite構(gòu)建的項(xiàng)目中需要自己手動(dòng)下載路由以及創(chuàng)建路由文件夾,所以在創(chuàng)建好的項(xiàng)目文檔中找到src文件夾,在src文件夾下創(chuàng)建router文件夾,并且在其下創(chuàng)建index文件,對(duì)于index文件中要寫(xiě)的內(nèi)容如下,在此之前還需要?jiǎng)?chuàng)建一個(gè)views文件夾,本次項(xiàng)目主要用到三個(gè)頁(yè)面,所以需要在views文件夾下需創(chuàng)建三個(gè)文件,包括HomeView.vue、AboutView.vue、UserLoginView.vue。這些準(zhǔn)備好之后還有重要的一點(diǎn)就是手動(dòng)安裝router。
npm install vue-router//終端中安裝router
index.js文件中的內(nèi)容:
import { createRouter, createWebHashHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
const routes = [
{//首頁(yè)
path: "/",
name: "home",
component: HomeView,
},
{//書(shū)籍商城
path: "/about",
name: "about",
component: () =>
import( "../views/AboutView.vue"),
},
{//登錄頁(yè)
path: "/userlogin",
name: "userlogin",
component: () =>
import("../views/UserLoginView.vue"),
},
];
const router = createRouter({
history: createWebHashHistory(),
routes,
});
export default router;
3.上述內(nèi)容完成之后,還需要在main.js中引入router,不然會(huì)報(bào)錯(cuò),以及在app.vue中需要撰寫(xiě)跳轉(zhuǎn)過(guò)程。
import router from "./router";
createApp(App).use(router).mount("#app");
<template>
<nav>
<router-link to="/">首頁(yè)</router-link> |
<router-link to="/about">書(shū)籍商城</router-link> |
<router-link to="/userlogin">登錄</router-link>
</nav>
<router-view />
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
nav {
padding: 40px;
}
nav a {
font-weight: bold;
font-size: 1.4rem;
color: #2c3e50;
text-decoration: none;
}
nav a.router-link-exact-active {
color: #42b983;
}
</style>
4.接下來(lái)就是書(shū)寫(xiě)每個(gè)頁(yè)面的代碼,首先是首頁(yè),首頁(yè)中未涉及過(guò)于復(fù)雜的過(guò)程,只是一個(gè)單純的靜態(tài)頁(yè)面。
<template>
<div class="home">
<div class="box"></div>
<!-- 書(shū)籍新聞列表部分 -->
<div class="booklist">
<table>
<tr v-for="item in list">
<td>{{ item.type }} <a href="">{{ item.title }}</a></td>
<td>{{ item.type }} <a href="">{{ item.title }}</a></td>
</tr>
</table>
</div>
<!-- 好書(shū)推薦部分 -->
<div class="bookrec">
<div class="booktitle">
<h3 >好書(shū)推薦</h3>
</div>
<ul class="recomd">
<li class="booItem" v-for="item in bookitem">
<img :src="item.url" alt="">
<a href="#">{{item.title}}</a>
<p class="intro">{{ item.intro }}</p>
<p class="price">{{ item.price }}</p>
</li>
</ul>
</div>
</div>
</template>
<script setup>
import { ref} from 'vue'
const list=ref([
{
type:'[懸疑]',
title:'河尸詭棺:大河生兇煞,送棺三千里'
},
{
type:'[仙俠]',
title:'成就系統(tǒng):我在武道世界里偷偷修仙'
},
{
type:'[歷史]',
title:'一品權(quán)臣:權(quán)臣護(hù)國(guó)保民,安定社稷'
},
{
type:'[玄幻]',
title:'詭道修仙:雨淋血染草,月照鬼守尸'
},
{
type:'[都市]',
title:'我的空間能修仙:我混的風(fēng)生水起!'
},
])
const bookitem=ref([
{
url:'../src/assets/img1.jpeg',
title:'大明:寒門(mén)輔臣',
intro:'寒門(mén)出身,臨淵而行,三朝輔臣,巔峰大明!',
price:'¥23'
},
{
url:'../src/assets/img2.jpeg',
title:'津門(mén)詭事錄',
intro:'浮尸丹鼎、黃仙尋仇、水鬼拉腳、兇靈砌墻……怪力亂神?裝神弄鬼!',
price:'¥26'
},
{
url:'../src/assets/img3.jpeg',
title:'一品',
intro:'世家少年入江湖,一刀將這天下捅了個(gè)通透。',
price:'¥28'
},
{
url:'../src/assets/img4.jpeg',
title:'怒火狂飆',
intro:'一段視頻引發(fā)戰(zhàn)神狂怒,鐵拳霸絕橫推一切不平,九萬(wàn)里山河染血。',
price:'¥35'
}
])
</script>
<style lang="scss" scoped>
a{
text-decoration: none;
}
ul,li{
list-style: none;
}
.box{
width: 55rem;
height: 26rem;
background: url('../assets/pic3.jpg') no-repeat;
background-size: 100% 100%;
margin-left: auto;
margin-right: auto;
}
.booklist{
width: 50rem;
// height: 10rem;
// background: #fc0;
margin-left: auto;
margin-right: auto;
margin-top: 0.5rem;
table{
display: flex;
flex-wrap: wrap;
}
td{
width: 25rem;
height: 3rem;
color: rgb(160, 160, 159);
background: rgb(188, 205, 251);
a{
text-decoration: none;
color: rgb(46, 45, 44);
cursor: pointer;
transition: all 0.5s;
&:hover{
color: rgb(233, 115, 37);
}
}
}
}
.bookrec{
width: 55rem;
height: 25rem;
margin-top: 0.5rem;
background: rgba(219, 206, 245, 0.6);
margin-left: auto;
margin-right: auto;
.booktitle{
width: 55rem;
height: 3.2rem;
border-bottom: 1px rgb(161, 161, 159) solid;
h3{
float: left;
padding-left: 1rem;
}
}
.recomd{
display: flex;
justify-content: space-around;
li{
width: 10rem;
img{
width: 9.6rem;
height: 12.6rem;
}
a{
color: rgb(60, 60, 58);
&:hover{
color: rgb(233, 115, 37);
}
}
.intro{
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
white-space: nowrap;
overflow: hidden;
color: rgb(146, 146, 143);
}
.price{
color: rgb(243, 149, 8);
font-weight: 400;
}
}
}
}
</style>
?首頁(yè)效果圖:
?
5.其次是書(shū)籍商城頁(yè)面,本頁(yè)面中由于查詢(xún)之后會(huì)展示相應(yīng)的書(shū)籍,所以涉及到了接口問(wèn)題,還需要另外自己手動(dòng)下載接口,對(duì)于接口文檔是借用小說(shuō)搜索 - LRY_API這個(gè)網(wǎng)站的。
npm install axios --save//在終端中下載接口
<template>
<div class="about">
<h2>{{ title }}</h2>
<!-- 搜索 -->
<div class="search">
<input type="text" placeholder="請(qǐng)輸入要查詢(xún)的書(shū)籍類(lèi)型" class="searchinput" @keyup.enter="search" v-model="book">
<button class="btn" @click="search">搜索</button>
</div>
<!-- 搜索結(jié)果 -->
<div class="searchResult">
<h3>搜索結(jié)果</h3>
</div>
<ul class="allbook">
<li class="bdesign" v-for="item in bookList">
<img :src="item.cover" alt="">
<div class="intro">
<h4 >{{item.title}}</h4>
<p class="bookintro">作者:{{ item.author }}</p>
<p class="bookintro">類(lèi)型:{{ item.fictionType }}</p>
<p class="bookintro">簡(jiǎn)介:{{ item.descs }}</p>
<p class="bookintro">出版時(shí)期:{{ item.updateTime }}</p>
</div>
</li>
</ul>
</div>
</template>
<script setup>
// import { reactive } from 'vue';
import {useRoute} from 'vue-router'
import {ref} from 'vue'
import axios from 'axios'
const route=useRoute();
// let data=reactive({
// query: route.query
// })
const title=ref('歡迎來(lái)到閱讀站')
const bookList = ref('')
const book=ref('')
//調(diào)用書(shū)籍目錄接口
const search = () => {
axios.get(`https://api.pingcc.cn/fiction/search/title/小說(shuō)/1/10`)
.then((result) => {
bookList.value=result.data.data
console.log(result.data);
})
.catch((err)=>{
alert("書(shū)籍輸入錯(cuò)誤")
console.log(err)
})
}
</script>
<style lang="scss" scoped>
a{
text-decoration: none;
}
ul,li,ol{
list-style: none;
}
.about{
width:55rem;
height:100rem;
background:rgba(214, 197, 248, 0.6);
margin-left: auto;
margin-right: auto;
h2{
color: rgb(39, 14, 162);
}
}
.searchinput{
width: 30rem;
height: 2.3rem;
margin-right: 1rem;
}
.btn{
width: 5rem;
height: 2.3rem;
background: rgb(66, 104, 240);
color: #fff;
border: none;
border-radius: 0.5rem;
cursor: pointer;
transition: all 0.5s;
}
.btn:hover{
background: rgb(245, 185, 66);
}
.searchResult{
margin-top: 1.5rem;
width: 55rem;
height: 3.2rem;
// background: #59c71e;
border-bottom: 1px #b1aeae solid;
h3{
padding-left: 1rem;
float: left;
}
}
.allbook{
margin-top: 1rem;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
align-content: flex-start;
padding:0 10px;
.bdesign{
display: flex;
padding-top: 2rem;
img{
width: 12rem;
height: 14rem;
}
.intro{
width: 12rem;
height: 14rem;
// background: #c64848;
margin-left: 0.5rem;
.bookintro{
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
white-space: nowrap;
// text-overflow: ellipsis;
overflow: hidden;
text-align: justify;
}
}
}
}
</style>
?書(shū)籍商城效果圖:
?
6.最后就是登錄界面,登錄界面功能要相對(duì)復(fù)雜一些,在登錄界面中點(diǎn)擊其他界面是禁止的,同時(shí)在登錄之后會(huì)跳轉(zhuǎn)到書(shū)籍商城界面,內(nèi)容如下:
<template>
<div class="box">
<div class="title">
<h3>{{ msg }}</h3>
</div>
<div class="box_form">
<form method="post">
<div class="img_control">
<img src="../assets/pic.jpeg" class="pic"/>
</div>
<label class="form-label txt" for="username">用 戶 名:</label>
<input class="form-input txt" type="text" placeholder="用戶名" required="required" ref="username"/><br>
<label class="form-label" for="password">密 碼:</label>
<input class="form-input paw" type="password" placeholder="密碼" required="required" ref="password"/><br>
<label class="form-label" for="password">沒(méi)有賬號(hào)?<a href="#">點(diǎn)擊注冊(cè)</a></label><br>
<input class="form-button" type="submit" value="登錄" @click="login"/>
</form>
</div>
</div>
</template>
<script setup>
import {useRouter,onBeforeRouteLeave} from 'vue-router';
import {ref} from "vue";
const router = useRouter();
const msg=ref('歡迎登錄');
const username=ref(null);
const password=ref(null);
const login=()=>{
if(username.value.value === 'zhangsan' && password.value.value==='123456'){
window.localStorage.setItem('userToken',username.value.value+password.value.value)
router.push({
path:'/about',
query:{
username:"zhangsan",
password:123456
}
})
}else{
alert('用戶名或密碼錯(cuò)誤!')
}
console.log(username.value.value)
}
onBeforeRouteLeave((to)=>{
let userToken=localStorage.getItem('userToken')
if(to.name!='userlogin' && userToken==null){
return false;
}
})
</script>
<style lang="scss" scoped>
.box{
width: 50rem;
height: 30.5rem;
background-color: rgba(188, 176, 212, 0.6);
margin-left: auto;
margin-right: auto;
}
.title {
text-align: center;
font-size: 2rem;
color: rgba(115, 87, 172, 0.6);
// margin-top: 1rem;
padding-top: 0.8rem;
}
.box_form {
width: 50rem;
height: 18rem;
margin-left: auto;
margin-right: auto;
.img_control{
margin-top: 6.5rem
}
.pic{
margin-left: 3rem;
float: left;
}
img{
width: 15rem;
height: 15rem;
}
.form-input {
width: 20rem;
height: 2.5rem;
padding-left: 0.5rem;
border-radius: 0.5rem;
border: none;
}
.paw{
margin-top: 2rem;
margin-bottom: 1rem;
margin-left: 0.7rem;
}
.form-label{
margin-left: 2rem;
margin-right: 1rem;
a{
// display: block;
text-decoration: none;
color: rgb(58, 58, 57);
&:hover{
color: #f17e0b;
}
}
}
.form-button {
width: 20.5rem;
height: 2.5rem;
margin-top: 1rem;
margin-left: 6.5rem;
font-size: 1.8rem;
border: none;
border-radius: 0.8rem;
font-family: "宋體";
background: rgb(245, 150, 199);
color: #fff;
font-weight: 400;
cursor: pointer;
&:hover{
background: #f17e0b;
}
}
}
</style>
?登錄效果圖:
?
7.最后來(lái)看看實(shí)際效果吧文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-757688.html
書(shū)籍商城案例文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-757688.html
到了這里,關(guān)于vue3+axios+router實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)及登錄的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!