日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

vue+vant 移动端H5 商城项目_03

發布時間:2024/9/27 vue 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue+vant 移动端H5 商城项目_03 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.




文章目錄

          • 一、·首頁搜索功能
            • 1. 搜索頁面
            • 2. 歷史記錄和熱門搜索組件
            • 3. 搜索框提示列表組件
            • 4. 綜合-價格-分類
            • 5. 搜索出的產品展示
            • 6. 異常修復
            • 7. 路由攔截/路由守衛
          • 二、詳情頁
            • 2.1. 效果圖
            • 2.2. 詳情api
            • 2.3. 配置路由
            • 2.4. 詳情頁面
            • 2.5. 詳情頁源碼

技術選型

組件版本說明
vue^2.6.11數據處理框架
vue-router^3.5.3動態路由
vant^2.12.37移動端UI
axios^0.24.0前后端交互
amfe-flexible^2.2.1Rem 布局適配
postcss-pxtorem^5.1.1Rem 布局適配
less^4.1.2css編譯
less-loader^5.0.0css編譯
vue/cli~4.5.0項目腳手架

vue-cli + vant+ less +axios 開發

一、·首頁搜索功能
1. 搜索頁面



{path: '/home',//首頁name: 'Home',component: () => import('@/views/home/Home'),meta: { // 用來判斷該組件對應的頁面是否顯示底部tabbarisShowTabbar: true},children: [{path: 'searchPopup',name: 'SearchPopup',component: () => import('@/views/home/search/SearchPopup')}]},

1.在http.js文件中定義接口請求

// 2.搜索頁 SearchPopup // 歷史記錄列表和熱門搜索列表 export function GetPopupData(params) {return instance({url: '/search/index',method: 'get',params}) } //刪除歷史記錄 export function Clearhistory(params) {return instance({url: '/search/clearhistory',method: 'post',data: params}) }//搜索提示列表 export function GetSearchTipsListData(params) {return instance({url: '/search/helper',method: 'get',params}) } //根據關鍵字搜索商品 export function GetSearchData(params) {return instance({url: '/goods/list',method: 'get',params}) }

2.views /SearchPopup.vue

在views 目錄下創建SearchPopup.vue 頁面,作為點擊搜索后的頁面

<template><div class="search-popup-box"><!--搜索框 --><van-searchshape="round"v-model="value"show-action:placeholder="placeholderVal"@search="onSearch"@cancel="onCancel"@input="onInput"/><!-- 歷史記錄和熱門搜索 組件 --><!-- 接受子組件傳來的數據 --><HistoryHotv-if="blockShow == 1":historyKeywordList="historyKeywordList":hotKeywordList="hotKeywordList"@goSearch="setValue"></HistoryHot><!-- 搜索提示 組件 --><SearchTipsListv-else-if="blockShow == 2":dataList="dataList"@setValue="setValue"></SearchTipsList><!-- 在父組件中綁定自定義事件 priceChange1 categoryChange1 --><!-- 下拉菜單 --><searchProducts:filterCategory="filterCategory":goodsList="goodsList"@priceChange1="priceChange1"@categoryChange1="categoryChange1"v-else></searchProducts></div> </template><script> import HistoryHot from "@/views/home/search/HistoryHot"; import searchProducts from "@/views/home/search/searchProducts"; import SearchTipsList from "@/views/home/search/SearchTipsList"; // 引入請求接口 import { GetSearchData, GetPopupData, GetSearchTipsListData } from "@/https/http"; export default {name: "search-popup",data() {return {value: "", // 搜索值page: 1, //頁數size: 20, // 每頁數據條數order: "desc", // 價格由高到底categoryId: 0, // 商品類別id 全家、居家、餐飲。。。sort: "id", // 排序字段 price 和id 2種情況goodsList: [], // 搜索出來的商品數據filterCategory: [], // 商品類別參數historyKeywordList: [], //歷史記錄數據hotKeywordList: [], // 熱門搜索 數據blockShow: 1, //控制顯示哪個?( 歷史記錄和熱門搜索組件 、 搜索提示組件、下拉菜單組件)dataList: [], //搜索提示數據placeholderVal: '' // 搜索框的默認提示詞};},methods: {priceChange1(value) {// value為子組件searchProducts傳來的價格排序參數asc,descconsole.log("父組件:價格", value);this.order = value;this.sort = "price";this.onSearch();// this.$router.go(0);},categoryChange1(value) {// value為子組件searchProducts傳來的種類參數console.log("父組件:類別id", value);this.sort = "id";this.categoryId = value;this.onSearch();},// 搜索框搜索功能onSearch() {this.blockShow = 3// 關鍵字搜索接口數據let obj = {keyword: this.value,page: 1,size: this.size, // 每頁數據條數order: this.order, // 價格由高到底categoryId: this.categoryId, // 商品類別id 全家、居家、餐飲。。。sort: this.sort, // 排序字段};// 發送數據請求// 搜索框商品搜索功能接口,獲取對應的商品列表GetSearchData(obj).then((res) => {// console.log(22, res);this.filterCategory = res.data.filterCategory;// 將商品的類別中的字段替換一下this.filterCategory = JSON.parse(JSON.stringify(this.filterCategory).replace(/id/g, "value").replace(/name/g, "text"));this.goodsList = res.data.goodsList;});},// 搜索取消onCancel() {this.$router.push("/home");},// 獲得歷史記錄gethistoryHotData() {GetPopupData().then((res) => {console.log(555, res);this.historyKeywordList = res.data.historyKeywordList;this.hotKeywordList = res.data.hotKeywordList;this.placeholderVal = res.data.defaultKeyword.keyword;});},// 獲取搜索提示getSearchHelperData(value) {this.blockShow = 2 // 展示搜索提示列表組件// 輸入觸發// 搜索提示數據請求GetSearchTipsListData({ keyword: value }).then((res) => {console.log(333333, res);this.dataList = res.data})},setValue(m) {console.log(6666, m);this.value = mthis.onSearch()},onInput(value) {this.getSearchHelperData(value)}},created() {this.gethistoryHotData();},components: {HistoryHot,searchProducts,SearchTipsList,}, }; </script><style></style>
2. 歷史記錄和熱門搜索組件

components/HistoryHot.vue

在components目錄下 創建 HistoryHot.vue(歷史記錄和熱門搜索) 組件,引入到SearchPopup.vue中

<template><div class="box"><div class="history-hot" v-if="isShowHistory"><h4>歷史記錄</h4><van-icon name="delete" class="delete-icon" @click="clearFn" /><van-tagplaintype="primary"v-for="(item, index) in historyKeywordList":key="index"v-if="item"@click="goSearch(item)">{{ item }}</van-tag></div><div class="hot-box"><h4>熱門搜索</h4><van-tagplain:type="item.is_hot ? 'danger' : 'primary'"v-for="(item, index) in hotKeywordList":key="index"v-if="item.keyword"@click="goSearch(item.keyword)">{{ item.keyword }}</van-tag></div></div> </template><script> import { Clearhistory } from '@/https/http' export default {name: "history-hot",data() {return {isShowHistory: 1}},props: ["historyKeywordList", "hotKeywordList"],methods: {clearFn() {Clearhistory().then((res) => {console.log(res);this.isShowHistory = 0})},goSearch(value) {this.$emit('goSearch', value)}} }; </script> <style lang="less" scoped> .box {font-size: 16px;span {margin-right: 3px;}.history-hot {margin-bottom: 10px;position: relative;.delete-icon {position: absolute;top: 10px;right: 10px;}} } </style>
3. 搜索框提示列表組件

components/SearchTipsList.vue

在components目錄下 創建 SearchTipsList.vue(搜索框提示列表組件) 組件,引入到SearchPopup.vue中

<template><div class="search-tips-list-box"><van-listv-model="loading":finished="finished"finished-text="沒有更多了"@load="onLoad"><van-cellv-for="item in dataList":key="item":title="item"@click="geiValue(item)"/></van-list></div> </template><script> export default {name: "search-tips-list",data() {return {list: [],loading: false, // //是否處于加載狀態finished: false, // 是否加載完成};},props: ["dataList"], 父傳子數組methods: {onLoad() {},geiValue(value){this.$emit('setValue',value)}}, }; </script><style lang="less" scoped> </style>
4. 綜合-價格-分類

components/SearchProducts.vue




在components 下 新建SearchProducts.vue (綜合-價格-分類組件)組件,引入到SearchPopup.vue

<template><div class="search-popup-box"><!--搜索框 --><van-searchshape="round"v-model="value"show-action:placeholder="placeholderVal"@search="onSearch"@cancel="onCancel"@input="onInput"/><!-- 歷史記錄和熱門搜索 組件 --><!-- 接受子組件傳來的數據 --><HistoryHotv-if="blockShow == 1":historyKeywordList="historyKeywordList":hotKeywordList="hotKeywordList"@goSearch="setValue"></HistoryHot><!-- 搜索提示 組件 --><SearchTipsListv-else-if="blockShow == 2":dataList="dataList"@setValue="setValue"></SearchTipsList><!-- 在父組件中綁定自定義事件 priceChange1 categoryChange1 --><!-- 下拉菜單 --><searchProducts:filterCategory="filterCategory":goodsList="goodsList"@priceChange1="priceChange1"@categoryChange1="categoryChange1"v-else></searchProducts></div> </template><script> import HistoryHot from "@/views/home/search/HistoryHot"; import searchProducts from "@/views/home/search/searchProducts"; import SearchTipsList from "@/views/home/search/SearchTipsList"; // 引入請求接口 import { GetSearchData, GetPopupData, GetSearchTipsListData } from "@/https/http"; export default {name: "search-popup",data() {return {value: "", // 搜索值page: 1, //頁數size: 20, // 每頁數據條數order: "desc", // 價格由高到底categoryId: 0, // 商品類別id 全家、居家、餐飲。。。sort: "id", // 排序字段 price 和id 2種情況goodsList: [], // 搜索出來的商品數據filterCategory: [], // 商品類別參數historyKeywordList: [], //歷史記錄數據hotKeywordList: [], // 熱門搜索 數據blockShow: 1, //控制顯示哪個?( 歷史記錄和熱門搜索組件 、 搜索提示組件、下拉菜單組件)dataList: [], //搜索提示數據placeholderVal: '' // 搜索框的默認提示詞};},methods: {priceChange1(value) {// value為子組件searchProducts傳來的價格排序參數asc,descconsole.log("父組件:價格", value);this.order = value;this.sort = "price";this.onSearch();// this.$router.go(0);},categoryChange1(value) {// value為子組件searchProducts傳來的種類參數console.log("父組件:類別id", value);this.sort = "id";this.categoryId = value;this.onSearch();},// 搜索框搜索功能onSearch() {this.blockShow = 3// 關鍵字搜索接口數據let obj = {keyword: this.value,page: 1,size: this.size, // 每頁數據條數order: this.order, // 價格由高到底categoryId: this.categoryId, // 商品類別id 全家、居家、餐飲。。。sort: this.sort, // 排序字段};// 發送數據請求// 搜索框商品搜索功能接口,獲取對應的商品列表GetSearchData(obj).then((res) => {// console.log(22, res);this.filterCategory = res.data.filterCategory;// 將商品的類別中的字段替換一下this.filterCategory = JSON.parse(JSON.stringify(this.filterCategory).replace(/id/g, "value").replace(/name/g, "text"));this.goodsList = res.data.goodsList;});},// 搜索取消onCancel() {this.$router.push("/home");},// 獲得歷史記錄gethistoryHotData() {GetPopupData().then((res) => {console.log(555, res);this.historyKeywordList = res.data.historyKeywordList;this.hotKeywordList = res.data.hotKeywordList;this.placeholderVal = res.data.defaultKeyword.keyword;});},// 獲取搜索提示getSearchHelperData(value) {this.blockShow = 2 // 展示搜索提示列表組件// 輸入觸發// 搜索提示數據請求GetSearchTipsListData({ keyword: value }).then((res) => {console.log(333333, res);this.dataList = res.data})},setValue(m) {console.log(6666, m);this.value = mthis.onSearch()},onInput(value) {this.getSearchHelperData(value)}},created() {this.gethistoryHotData();},components: {HistoryHot,searchProducts,SearchTipsList,}, }; </script><style></style>
5. 搜索出的產品展示

components/Products.vue

在components 下 新建 Products.vue(搜索出的產品展示組件),引入到SearchProducts.vue,作為其子組件使用。

<template><!-- 數據列表渲染 --><ul class="goods_list"><li v-for="item in goodsList" :key="item.id" @click="gotodetail(item.id)"><img v-lazy="item.list_pic_url" alt="" /><p>{{ item.name }}</p><p>{{ item.retail_price | moneyFlrmat }}</p></li></ul> </template><script> export default {name:'products',props:['goodsList'],data(){return{}},methods: {gotodetail(id_){this.$router.push({path:'/productDetail',query:{id:id_}})}} } </script><style lang="less" scoped>.goods_list {display: flex;flex-wrap: wrap;justify-content: space-between;font-size: 16px;line-height: 20px;text-align: center;li {width: 48%;img {width: 100%;}}} </style>
6. 異常修復

關于重復點擊同一個路由出現的報錯問題解決
在新版本的vue-router中,重復點擊同一個路由會出現以下報錯:

方案1、vue-router降級處理(但不推薦)

npm i vue-router@3.0.7

方案2、直接在push方法最后添加異常捕獲,例如:

<van-search v-model="SearchVal" shape="round" placeholder="請輸入搜索關鍵詞" disabled @click="$router.push('/home/searchPopup').catch(err=>{})"/>

方案3、直接修改原型方法push(推薦)

// 把這段代碼直接粘貼到router/index.js中的Vue.use(VueRouter)之前 const originalPush = VueRouter.prototype.push; VueRouter.prototype.push = function(location) {return originalPush.call(this, location).catch(err => {}) };
7. 路由攔截/路由守衛

vue-router文檔地址
路由攔截(導航守衛:前置導航守衛和后置導航守衛)
前置導航守衛有三個參數
to: 表示即將進入的路由
from: 表示即將離開的路由
next() :表示執行進入這個路由

// 路由前置守衛 router.beforeEach((to, from, next) => {// 有token就表示已經登錄// 想要進入購物車頁面,必須有登錄標識token// console.log('to:', to)// console.log('from:', from)let token = localStorage.getItem('token')if (to.path == '/cart') {// 此時必須要有tokenif (token) {next(); // next()去到to所對應的路由界面} else {Vue.prototype.$toast('請先登錄');// 定時器setTimeout(() => {next("/user"); // 強制去到"/user"所對應的路由界面}, 1000);}} else {// 如果不是去往購物車的路由,則直接通過守衛,去到to所對應的路由界面next()} })
二、詳情頁
2.1. 效果圖


2.2. 詳情api

1.在http.js 文件中定義詳情頁請求接口

//3.詳情頁 ProductDetail // 產品詳情 export function GoodsDetailApi(params) {return instance({url: '/goods/detail',method: 'get',params}) } //詳情頁相關產品 export function GetGoodsRelatedData(params) {return instance({url: '/goods/related',method: 'get',params}) } //獲取商品數量 export function GetCartNum(params) {return instance({url: '/cart/goodscount',method: 'get',params}) } // 添加到購物車 export function AddToCart(params) {return instance({url: '/cart/add',method: 'post',data: params}) }
2.3. 配置路由

router/index.js
在components 目錄下創建ProductDetail.vue (詳情頁組件),并在路由中配置( 一級路由)

{path: '/productDetail', //產品詳情name: 'ProductDetail',component: () => import('@/views/productdetail/ProductDetail')},
2.4. 詳情頁面

components /ProductDetail.vue

2.5. 詳情頁源碼
<template><div class="product-detail-box"><van-swipe :autoplay="3000"><van-swipe-item v-for="item in gallery" :key="item.id"><img :src="item.img_url" /></van-swipe-item></van-swipe><div class="info" v-if="info.name"><p class="info-name">{{ info.name }}</p><p class="info-brief">{{ info.goods_brief }}</p><p class="info-price">{{ info.retail_price | moneyFlrmat }}</p></div><div class="attribute"><div class="mytitle"><span></span><h3>商品參數</h3></div><ul><li v-for="item in attribute" :key="item.id"><span class="attribute-name">{{ item.name }}</span><span class="attribute-value">{{ item.value }}</span></li></ul></div><!-- 產品詳情 --><div class="mytitle"><span></span><h3>產品詳情</h3></div><!-- 產品描述信息 --><div class="goods_desc" v-html="info.goods_desc"></div><div class="mytitle"><span></span><h3>常見問題</h3></div><!-- 常見問題 --><ul class="issue"><li v-for="item in issue" :key="item.id"><h3>{{ item.question }}</h3><p>{{ item.answer }}</p></li></ul><!-- 產品列表 --><Weekproduct :newGoodsList="goodsList" title="相關產品"> </Weekproduct><!-- 添加購物車面板 --><van-skuv-model="show"ref="sku":sku="sku":goods="goods":hide-stock="sku.hide_stock"@add-cart="onAddCartClicked"/><!-- 下方購物車 --><van-goods-action><van-goods-action-icon:icon="star_flag ? 'star' : 'star-o'":text="star_flag ? '已收藏' : '未收藏'":color="star_flag ? '#ff5000' : '#323233'"@click="clickFn"/><van-goods-action-iconicon="cart-o"text="購物車":badge="badge"@click="$router.push('/cart')"/><van-goods-action-buttontype="warning"text="加入購物車"@click="addCar"/><van-goods-action-button type="danger" text="立即購買" /></van-goods-action></div> </template><script> import { getDetailData, AddToCart, GetGoodsRelatedData,GetCartCountData } from "@/https/http"; import Weekproduct from "@/views/home/Weekproduct";export default {name: "product-detail",data() {return {gallery: [],info: {},attribute: [], //參數show: false,sku: {tree: [], //規格類目 顏色 尺寸 。。。price: "", // 默認價格(單位元)stock_num: 227, // 商品總庫存// 數據結構見下方文檔hide_stock: false, //是否隱藏剩余庫存},goods: {// 默認商品 sku 縮略圖picture: ''},productList: [], // 當前產品信息issue: [],goodsList: [],star_flag: false,badge:0,};},created() {this.GetDetailData()this.getRelatedData()this.getCartData()},methods: {addCar() {this.show = true},// 加入購物車onAddCartClicked() {console.log(666,this.$refs.sku.getSkuData());let obj = {}obj.goodsId = this.$route.query.idobj.productId = this.productList[0].idobj.number = this.$refs.sku.getSkuData().selectedNumAddToCart(obj).then((res) => {console.log(res);// 顯示添加成功this.$toast.success("添加成功");this.getCartData()})// 隱藏 商品規格面板this.show = false;},// ?獲取產品明細數據列表GetDetailData() {getDetailData({ id: this.$route.query.id }).then((res) => {console.log(33, res);this.gallery = res.data.gallery;this.info = res.data.info;this.productList = res.data.productList;this.attribute = res.data.attribute;this.issue = res.data.issue;this.goods.picture = res.data.info.list_pic_urlthis.sku.price = res.data.info.retail_pricethis.sku.stock_num = res.data.info.goods_number});},// ?獲取相關產品數據列表getRelatedData() {GetGoodsRelatedData({ id: this.$route.query.id }).then((res) => {console.log(3366, res);this.goodsList = res.data.goodsList});},// ?獲取購物車商品數量getCartData(){GetCartCountData().then((res)=>{console.log(7778,res);this.badge = res.data.cartTotal.goodsCount})},clickFn() {this.star_flag = !this.star_flagif (this.star_flag) {this.$toast('收藏成功')} else {this.$toast('取消寶貝收藏成功')}}},components: {Weekproduct} }; </script><style lang="less" scoped> .product-detail-box {font-size: 14px;line-height: 30px;padding-bottom: 100px;img {width: 100%;}.info {text-align: center;.info-brief {color: #666;}.info-price {color: red;}}.attribute {ul {li {border-bottom: 1px solid #eee;font-size: 12px;display: flex;.attribute-name {width: 15%;}.attribute-value {flex: 1;}}}}.mytitle {text-align: center;font-size: 16px;margin-top: 20px;position: relative;height: 50px;span {width: 50%;height: 2px;background-color: #ccc;display: inline-block;position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);}h3 {width: 30%;background-color: #fff;position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);}}.issue {li {h3 {padding-left: 10px;line-height: 20px;position: relative;&:before {content: "";width: 4px;height: 4px;border-radius: 50%;background-color: red;display: inline-block;position: absolute;left: 2px;top: 50%;margin-top: -2px;}}margin-bottom: 15px;}}/deep/.goods_desc {img {width: 100%;}} } </style>

總結

以上是生活随笔為你收集整理的vue+vant 移动端H5 商城项目_03的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。