Vue3+ElementPlus+Pinia開發(fā)小兔鮮電商項目完整教程(附代碼資料)主要內(nèi)容講述:認識Vue3,使用create-vue搭建Vue3項目1. Vue3組合式API體驗,2. Vue3更多的優(yōu)勢,1. 認識create-vue,2. 使用create-vue創(chuàng)建項目,1. setup選項的寫法和執(zhí)行時機,2. setup中寫代碼的特點。什么是pinia,創(chuàng)建空Vue項目并安裝Pinia1. 安裝elementPlus和自動導(dǎo)入插件,2. 配置自動按需導(dǎo)入,3. 測試組件,1. 安裝sass,2. 準備定制化的樣式文件,3. 自動導(dǎo)入配置。靜態(tài)結(jié)構(gòu)搭建和分類實現(xiàn),banner輪播圖實現(xiàn)1. 整體結(jié)構(gòu)創(chuàng)建,2. 分類實現(xiàn),1. 熟悉組件,2. 獲取數(shù)據(jù)渲染組件,1. 純靜態(tài)結(jié)構(gòu),2. 完整代碼。靜態(tài)結(jié)構(gòu)搭建和路由配置,面包屑導(dǎo)航渲染1. 準備分類組件,2. 配置路由,3. 配置導(dǎo)航區(qū)域鏈接,1. 認識組件準備模版,2. 封裝接口,3. 渲染面包屑導(dǎo)航。整體認識和路由配置,渲染基礎(chǔ)數(shù)據(jù)1. 準備組件模版,2. 配置路由,3. 綁定模版測試跳轉(zhuǎn),1. 封裝接口,2. 獲取數(shù)據(jù)渲染模版,1. 渲染基礎(chǔ)熱榜數(shù)據(jù)。整體認識和路由配置,表單校驗實現(xiàn)1. 準備模版,2. 配置路由跳轉(zhuǎn),1. 校驗要求,2. 代碼實現(xiàn)。本地購物車,接口購物車1. 添加購物車,2. 頭部購物車,3. 列表購物車-基礎(chǔ)內(nèi)容渲染,4. 列表購物車-單選功能實現(xiàn),5. 列表購物車-全選功能實現(xiàn),6. 列表購物車-統(tǒng)計數(shù)據(jù)功能實現(xiàn)。路由配置和基礎(chǔ)數(shù)據(jù)渲染,切換地址-打開彈框交互1. 準備組件模版,2. 配置路由,3. 封裝接口,4. 渲染數(shù)據(jù),1. 準備彈框模版,2. 控制彈框打開。數(shù)據(jù)渲染1. 準備接口,2. 獲取數(shù)據(jù)渲染內(nèi)容,1. 支付攜帶參數(shù),2. 沙箱賬號信息,1. 準備模版,2. 綁定路由。Sku組件封裝1. 準備模版渲染規(guī)格數(shù)據(jù),2. 選中和取消選中實現(xiàn),3. 規(guī)格禁用功能實現(xiàn),4. 產(chǎn)出Prop數(shù)據(jù)。
全套筆記資料代碼移步: 前往gitee倉庫查看
感興趣的小伙伴可以自取哦,歡迎大家點贊轉(zhuǎn)發(fā)~
全套教程部分目錄:
部分文件圖片:
靜態(tài)結(jié)構(gòu)搭建和路由配置
1. 準備分類組件
<script setup>
</script>
<template>
<div class='top-category'>
我是分類
</div>
</template>
2. 配置路由
import { createRouter, createWebHashHistory } from 'vue-router'
import Layout from '@/views/Layout/index.vue'
import Home from '@/views/Home/index.vue'
import Category from '@/views/Category/index.vue'
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'layout',
component: Layout,
children: [
{
path: '',
name: 'home',
component: Home
},
{
path: 'category/:id',
name: 'category',
component: Category
}
]
},
{
path: '/login',
name: 'login',
component: Login
},
]
})
export default router
3. 配置導(dǎo)航區(qū)域鏈接
<li v-for="item in categoryStore.categoryList" :key="item.id">
<RouterLink active-class="active" :to="`/category/${item.id}`">
{{ item.name }}
</RouterLink>
</li>
面包屑導(dǎo)航渲染
1. 認識組件準備模版
<script setup>
</script>
<template>
<div class="top-category">
<div class="container m-top-20">
<!-- 面包屑 -->
<div class="bread-container">
<el-breadcrumb separator=">">
<el-breadcrumb-item :to="{ path: '/' }">首頁</el-breadcrumb-item>
<el-breadcrumb-item>居家</el-breadcrumb-item>
</el-breadcrumb>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.top-category {
h3 {
font-size: 28px;
color: #666;
font-weight: normal;
text-align: center;
line-height: 100px;
}
.sub-list {
margin-top: 20px;
background-color: #fff;
ul {
display: flex;
padding: 0 32px;
flex-wrap: wrap;
li {
width: 168px;
height: 160px;
a {
text-align: center;
display: block;
font-size: 16px;
img {
width: 100px;
height: 100px;
}
p {
line-height: 40px;
}
&:hover {
color: $xtxColor;
}
}
}
}
}
.ref-goods {
background-color: #fff;
margin-top: 20px;
position: relative;
.head {
.xtx-more {
position: absolute;
top: 20px;
right: 20px;
}
.tag {
text-align: center;
color: #999;
font-size: 20px;
position: relative;
top: -20px;
}
}
.body {
display: flex;
justify-content: space-around;
padding: 0 40px 30px;
}
}
.bread-container {
padding: 25px 0;
}
}
</style>
2. 封裝接口
import request from '@/utils/request'
/**
* @description: 獲取分類數(shù)據(jù)
* @param {*} id 分類id
* @return {*}
*/
export const getTopCategoryAPI = (id) => {
return request({
url:'/category',
params:{
id
}
})
}
3. 渲染面包屑導(dǎo)航
<script setup>
import { findTopCategoryAPI } from '@/apis/category'
const categoryData = ref({})
const route = useRoute()
const getCategory = async (id) => {
// 如何在setup中獲取路由參數(shù) useRoute() -> route 等價于this.$route
const res = await findTopCategoryAPI(id)
categoryData.value = res.result
}
getCategory(route.params.id)
</script>
<template>
<div class="bread-container">
<el-breadcrumb separator=">">
<el-breadcrumb-item :to="{ path: '/' }">首頁</el-breadcrumb-item>
<el-breadcrumb-item>{{ categoryData.name }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
</template>
分類Banner渲染
1. 適配接口
export function getBannerAPI (params = {}) {
// 默認為1 商品為2
const { distributionSite = '1' } = params
return httpInstance({
url: '/home/banner',
params: {
distributionSite
}
})
}
2. 遷移首頁Banner邏輯
<script setup>
// 部分代碼省略
import { getBannerAPI } from '@/apis/home'
// 獲取banner
const bannerList = ref([])
const getBanner = async () => {
const res = await getBannerAPI({
distributionSite: '2'
})
console.log(res)
bannerList.value = res.result
}
onMounted(() => getBanner())
</script>
<template>
<div class="top-category">
<div class="container m-top-20">
<!-- 面包屑 -->
<div class="bread-container">
<el-breadcrumb separator=">">
<el-breadcrumb-item :to="{ path: '/' }">首頁</el-breadcrumb-item>
<el-breadcrumb-item>{{ categoryData.name }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<!-- 輪播圖 -->
<div class="home-banner">
<el-carousel height="500px">
<el-carousel-item v-for="item in bannerList" :key="item.id">
<img :src="item.imgUrl" alt="">
</el-carousel-item>
</el-carousel>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
// 部分代碼省略
.home-banner {
width: 1240px;
height: 500px;
margin: 0 auto;
img {
width: 100%;
height: 500px;
}
}
</style>
導(dǎo)航激活設(shè)置分類列表渲染
1. 導(dǎo)航激活狀態(tài)設(shè)置
<RouterLink active-class="active" :to="`/category/${item.id}`">{{ item.name }}</RouterLink>
2. 分類數(shù)據(jù)模版
<div class="sub-list">
<h3>全部分類</h3>
<ul>
<li v-for="i in categoryData.children" :key="i.id">
<RouterLink to="/">
<img :src="i.picture" />
<p>{{ i.name }}</p>
</RouterLink>
</li>
</ul>
</div>
<div class="ref-goods" v-for="item in categoryData.children" :key="item.id">
<div class="head">
<h3>- {{ item.name }}-</h3>
</div>
<div class="body">
<GoodsItem v-for="good in item.goods" :goods="good" :key="good.id" />
</div>
</div>
路由緩存問題解決
緩存問題:當路由path一樣,參數(shù)不同的時候會選擇直接復(fù)用路由對應(yīng)的組件 解決方案: 1. 給 routerv-view 添加key屬性,破壞緩存 2. 使用 onBeforeRouteUpdate鉤子函數(shù),做精確更新
基于業(yè)務(wù)邏輯的函數(shù)拆分
基本思想:把組件內(nèi)獨立的業(yè)務(wù)邏輯通過
useXXX
函數(shù)做封裝處理,在組件中做組合使用
據(jù)業(yè)務(wù)相關(guān)代碼
import { onMounted, ref } from 'vue'
import { getCategoryAPI } from '@/apis/category'
import { useRoute } from 'vue-router'
import { onBeforeRouteUpdate } from 'vue-router'
export function useCategory () {
// 獲取分類數(shù)據(jù)
const categoryData = ref({})
const route = useRoute()
const getCategory = async (id = route.params.id) => {
const res = await getCategoryAPI(id)
categoryData.value = res.result
}
onMounted(() => getCategory())
// 目標:路由參數(shù)變化的時候 可以把分類數(shù)據(jù)接口重新發(fā)送
onBeforeRouteUpdate((to) => {
// 存在問題:使用最新的路由參數(shù)請求最新的分類數(shù)據(jù)
getCategory(to.params.id)
})
return {
categoryData
}
}
// 封裝banner輪播圖相關(guān)的業(yè)務(wù)代碼
import { ref, onMounted } from 'vue'
import { getBannerAPI } from '@/apis/home'
export function useBanner () {
const bannerList = ref([])
const getBanner = async () => {
const res = await getBannerAPI({
distributionSite: '2'
})
console.log(res)
bannerList.value = res.result
}
onMounted(() => getBanner())
return {
bannerList
}
}
<script setup>
import GoodsItem from '../Home/components/GoodsItem.vue'
import { useBanner } from './composables/useBanner'
import { useCategory } from './composables/useCategory'
const { bannerList } = useBanner()
const { categoryData } = useCategory()
</script>
本資源由 收集整理
整體業(yè)務(wù)認識和路由配置
1. 準備組件模版
<script setup>
</script>
<template>
<div class="container ">
<!-- 面包屑 -->
<div class="bread-container">
<el-breadcrumb separator=">">
<el-breadcrumb-item :to="{ path: '/' }">首頁</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/' }">居家
</el-breadcrumb-item>
<el-breadcrumb-item>居家生活用品</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="sub-container">
<el-tabs>
<el-tab-pane label="最新商品" name="publishTime"></el-tab-pane>
<el-tab-pane label="最高人氣" name="orderNum"></el-tab-pane>
<el-tab-pane label="評論最多" name="evaluateNum"></el-tab-pane>
</el-tabs>
<div class="body">
<!-- 商品列表-->
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.bread-container {
padding: 25px 0;
color: #666;
}
.sub-container {
padding: 20px 10px;
background-color: #fff;
.body {
display: flex;
flex-wrap: wrap;
padding: 0 10px;
}
.goods-item {
display: block;
width: 220px;
margin-right: 20px;
padding: 20px 30px;
text-align: center;
img {
width: 160px;
height: 160px;
}
p {
padding-top: 10px;
}
.name {
font-size: 16px;
}
.desc {
color: #999;
height: 29px;
}
.price {
color: $priceColor;
font-size: 20px;
}
}
.pagination-container {
margin-top: 20px;
display: flex;
justify-content: center;
}
}
</style>
2. 配置路由關(guān)系
import { createRouter, createWebHashHistory } from 'vue-router'
import Layout from '@/views/Layout/index.vue'
import Home from '@/views/Home/index.vue'
import Category from '@/views/Category/index.vue'
import SubCategory from '@/views/SubCategory/index.vue'
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'layout',
component: Layout,
children: [
{
path: '',
name: 'home',
component: Home
},
{
path: 'category/:id',
name: 'category',
component: Category
},
{
path: 'category/sub/:id',
name: 'subCategory',
component: SubCategory
},
]
},
{
path: '/login',
name: 'login',
component: Login
},
]
})
export default router
3. 跳轉(zhuǎn)配置
<div class="sub-list">
<h3>全部分類</h3>
<ul>
<li v-for="i in categoryData.children" :key="i.id">
<RouterLink :to="`/category/sub/${i.id}`">
<img :src="i.picture" />
<p>{{ i.name }}</p>
</RouterLink>
</li>
</ul>
</div>
面包屑導(dǎo)航實現(xiàn)
1. 準備接口
/**
* @description: 獲取二級分類列表數(shù)據(jù)
* @param {*} id 分類id
* @return {*}
*/
export const getCategoryFilterAPI = (id) => {
return request({
url:'/category/sub/filter',
params:{
id
}
})
}
2. 獲取數(shù)據(jù)渲染模版
<script setup>
import { getCategoryFilterAPI } from '@/apis/category'
// 獲取面包屑導(dǎo)航數(shù)據(jù)
const filterData = ref({})
const getFilterData = async () => {
const res = await getCategoryFilterAPI(route.params.id)
filterData.value = res.result
}
getFilterData()
</script>
<template>
<div class="bread-container">
<el-breadcrumb separator=">">
<el-breadcrumb-item :to="{ path: '/' }">首頁</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: `/category/${filterData.parentId}` }">{{ filterData.parentName }}
</el-breadcrumb-item>
<el-breadcrumb-item>{{ filterData.name }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
</template>
分類基礎(chǔ)列表實現(xiàn)
1. 準備接口
/**
* @description: 獲取導(dǎo)航數(shù)據(jù)
* @data {
categoryId: 1005000 ,
page: 1,
pageSize: 20,
sortField: 'publishTime' | 'orderNum' | 'evaluateNum'
}
* @return {*}
*/
export const getSubCategoryAPI = (data) => {
return request({
url:'/category/goods/temporary',
method:'POST',
data
})
}
2. 獲取數(shù)據(jù)列表
<script setup>
// 獲取基礎(chǔ)列表數(shù)據(jù)渲染
const goodList = ref([])
const reqData = ref({
categoryId: route.params.id,
page: 1,
pageSize: 20,
sortField: 'publishTime'
})
const getGoodList = async () => {
const res = await getSubCategoryAPI(reqData.value)
console.log(res)
goodList.value = res.result.items
}
onMounted(() => getGoodList())
</script>
列表篩選實現(xiàn)
思路:tab組件切換時修改reqData中的sortField字段,重新拉取接口列表文章來源:http://www.zghlxwxcb.cn/news/detail-847608.html
<script setup>
// tab切換回調(diào)
const tabChange = () => {
console.log('tab切換了', reqData.value.sortField)
reqData.value.page = 1
getGoodList()
}
</script>
<template>
<el-tabs v-model="reqData.sortField" @tab-change="tabChange">
<el-tab-pane label="最新商品" name="publishTime"></el-tab-pane>
<el-tab-pane label="最高人氣" name="orderNum"></el-tab-pane>
<el-tab-pane label="評論最多" name="evaluateNum"></el-tab-pane>
</el-tabs>
</template>
無限加載實現(xiàn)
基礎(chǔ)思路 1. 觸底條件滿足之后 page++,拉取下一頁數(shù)據(jù) 2. 新老數(shù)據(jù)做數(shù)組拼接 3. 判斷是否已經(jīng)全部加載完畢,停止監(jiān)聽文章來源地址http://www.zghlxwxcb.cn/news/detail-847608.html
// 加載更多
const disabled = ref(false)
const load = async () => {
console.log('加載更多數(shù)據(jù)咯')
// 獲取下一頁的數(shù)據(jù)
reqData.value.page++
const res = await getSubCategoryAPI(reqData.value)
goodList.value = [...goodList.value, ...res.result.items]
// 加載完畢 停止監(jiān)聽
if (res.result.items.length === 0) {
disabled.value = true
}
}
未完待續(xù), 同學(xué)們請等待下一期
全套筆記資料代碼移步: 前往gitee倉庫查看
感興趣的小伙伴可以自取哦,歡迎大家點贊轉(zhuǎn)發(fā)~
到了這里,關(guān)于【前端Vue】Vue3+Pinia小兔鮮電商項目第4篇:靜態(tài)結(jié)構(gòu)搭建和路由配置,1. 準備分類組件【附代碼文檔】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!