其他分享
首页 > 其他分享> > 尚硅谷-尚品汇

尚硅谷-尚品汇

作者:互联网

目录

1.项目目录分析:

2.先上三天代码

3.一些知识点


三天一更新 总结一下三天学习成果


1.项目目录分析:

首先当我们拿到一个项目我们先来分析它的结构 然后把它拆分成一个个组件,我们会发现有的组件 页面都存在,比如这个项目,当我们进入首页home模块的时候 它分为上中下三部分,有头部header和尾部footer.当我们点击搜索的时候,不会整合页面都改变,也只是中间变化,它的头部和尾部依然存在,而当我们点击登陆或者注册的时候,会发现它只有头部,而没有尾部.所以header和footer可以注册成全局组件,在多个页面使用,一般情况我们把全局组件放在components中.至于登陆注册只有头部没有尾部的情况我们后边写到显示与隐藏.

api:接口目录 用来存放后台接口

components: 一般存放在多个页面中使用的全局组件

views/pages:存放其他组件 可以是一个大组件拆分成多个小组件

 main.js:入口文件 用来注册全局组件、import引入路由router或者仓库store等的地方

App.vue:路由组件出口的地方(先在script引入组件,然后再template写路由)

<router-view></router-view>

举个栗子:前面说到我们这个项目,

头部header:<!-- 在Home、Search,Login、Register均显示 -->

尾部footer:<!-- 在Home、Search显示,在Login、Register隐藏 -->

我们把<Header></Header> 和<Footer></Footer>写在App.vue 然后给footer加上显示与隐藏的条件v-show

<Footer v-show="$route.meta.show"></Footer>

 对应的找到相应路由加上显示(true)或隐藏(false)即可

接下来我们说路由部分

router:用来配置路由,我们在此处引入路由,引入的即是我们在views/pages内的路由,至于components里面的我们已经在app.vue引入过了,不用在router引入 

目录大致就这些,有补充的我以后再加

2.先上三天代码

注:我这里只上了部分代码 至于图片大家可以直接去git下载 拖进自己项目

components /Footer/index.vue

<template>
  <div class="footer">
    <div class="footer-container">
      <div class="footerList">
        <div class="footerItem">
          <h4>购物指南</h4>
          <ul class="footerItemCon">
            <li>购物流程</li>
            <li>会员介绍</li>
            <li>生活旅行/团购</li>
            <li>常见问题</li>
            <li>购物指南</li>
          </ul>
        </div>
        <div class="footerItem">
          <h4>配送方式</h4>
          <ul class="footerItemCon">
            <li>上门自提</li>
            <li>211限时达</li>
            <li>配送服务查询</li>
            <li>配送费收取标准</li>
            <li>海外配送</li>
          </ul>
        </div>
        <div class="footerItem">
          <h4>支付方式</h4>
          <ul class="footerItemCon">
            <li>货到付款</li>
            <li>在线支付</li>
            <li>分期付款</li>
            <li>邮局汇款</li>
            <li>公司转账</li>
          </ul>
        </div>
        <div class="footerItem">
          <h4>售后服务</h4>
          <ul class="footerItemCon">
            <li>售后政策</li>
            <li>价格保护</li>
            <li>退款说明</li>
            <li>返修/退换货</li>
            <li>取消订单</li>
          </ul>
        </div>
        <div class="footerItem">
          <h4>特色服务</h4>
          <ul class="footerItemCon">
            <li>夺宝岛</li>
            <li>DIY装机</li>
            <li>延保服务</li>
            <li>尚品汇E卡</li>
            <li>尚品汇通信</li>
          </ul>
        </div>
        <div class="footerItem">
          <h4>帮助中心</h4>
          <img src="./images/wx_cz.jpg" />
        </div>
      </div>
      <div class="copyright">
        <ul class="helpLink">
          <li>
            关于我们
            <span class="space"></span>
          </li>
          <li>
            联系我们
            <span class="space"></span>
          </li>
          <li>
            关于我们
            <span class="space"></span>
          </li>
          <li>
            商家入驻
            <span class="space"></span>
          </li>
          <li>
            营销中心
            <span class="space"></span>
          </li>
          <li>
            友情链接
            <span class="space"></span>
          </li>
          <li>
            关于我们
            <span class="space"></span>
          </li>
          <li>
            营销中心
            <span class="space"></span>
          </li>
          <li>
            友情链接
            <span class="space"></span>
          </li>
          <li>关于我们</li>
        </ul>
        <p>地址:北京市昌平区宏福科技园综合楼6层</p>
        <p>京ICP备19006430号</p>
      </div>
    </div>
  </div>
</template>
<script>
</script>

<style scoped lang="less">
.footer {
  background-color: #eaeaea;

  .footer-container {
    width: 1200px;
    margin: 0 auto;
    padding: 0 15px;

    .footerList {
      padding: 20px;
      border-bottom: 1px solid #e4e1e1;
      border-top: 1px solid #e4e1e1;
      overflow: hidden;
      padding-left: 40px;

      .footerItem {
        width: 16.6666667%;
        float: left;

        h4 {
          font-size: 14px;
        }

        .footerItemCon {
          li {
            line-height: 18px;
          }
        }

        &:last-child img {
          width: 121px;
        }
      }
    }

    .copyright {
      padding: 20px;

      .helpLink {
        text-align: center;

        li {
          display: inline;

          .space {
            border-left: 1px solid #666;
            width: 1px;
            height: 13px;
            background: #666;
            margin: 8px 10px;
          }
        }
      }

      p {
        margin: 10px 0;
        text-align: center;
      }
    }
  }
}
</style>

components /Header/index.vue 

<template>
	<header class="header">
		<!-- 头部的第一行 -->
		<div class="top">
			<div class="container">
				<div class="loginList">
					<p>尚品汇欢迎您!</p>
					<!-- 没有用户名:未登录 -->
					<p v-if="!userName">
						<span>请</span>
						<!-- 声明式导航:router-link务必要有to属性 -->
						<router-link to="/login">登录</router-link>
						<router-link class="register" to="/register">免费注册</router-link>
					</p>
					<!-- 登录了 -->
					<p v-else>
						<a>{{userName}}</a>
						<a class="register" @click="logout">退出登录</a>
					</p>
				</div>
				<div class="typeList">
					<router-link to="/center/myorder">我的订单</router-link>
					<router-link to="/shopcart">我的购物车</router-link>
					<a href="###">我的尚品汇</a>
					<a href="###">尚品汇会员</a>
					<a href="###">企业采购</a>
					<a href="###">关注尚品汇</a>
					<a href="###">合作招商</a>
					<a href="###">商家后台</a>
				</div>
			</div>
		</div>
		<!--头部第二行 搜索区域-->
		<div class="bottom">
			<h1 class="logoArea">
				<!-- router-link组件本省就是一个a标签 -->
				<router-link to="/home" class="logo">
					<img src="./images/logo.png" alt="" />
				</router-link>
			</h1>
			<div class="searchArea">
				<form action="###" class="searchForm">
					<input type="text" id="autocomplete" class="input-error input-xxlarge" v-model="keyword" />
					<button class="sui-btn btn-xlarge btn-danger" type="button" @click="goSearch">
						搜索
					</button>
				</form>
			</div>
		</div>
	</header>
</template>

<script>
	export default{
		name:"",
		data(){
			return{
				keyword:''
			}
		},
		methods:{
			//搜索按钮的回调函数 需要向搜索组件跳转
			goSearch(){
				
				this.$router.push({name:"search",params:{keyword:this.keyword},query:{k:this.keyword.toUpperCase()}})
			}
		}
	}
</script>

<style scoped lang="less">
	.header {
		&>.top {
			background-color: #eaeaea;
			height: 30px;
			line-height: 30px;

			.container {
				width: 1200px;
				margin: 0 auto;
				overflow: hidden;

				.loginList {
					float: left;

					p {
						float: left;
						margin-right: 10px;

						.register {
							border-left: 1px solid #b3aeae;
							padding: 0 5px;
							margin-left: 5px;
						}
					}
				}

				.typeList {
					float: right;

					a {
						padding: 0 10px;

						&+a {
							border-left: 1px solid #b3aeae;
						}
					}
				}
			}
		}

		&>.bottom {
			width: 1200px;
			margin: 0 auto;
			overflow: hidden;

			.logoArea {
				float: left;

				.logo {
					img {
						width: 175px;
						margin: 25px 45px;
					}
				}
			}

			.searchArea {
				float: right;
				margin-top: 35px;

				.searchForm {
					overflow: hidden;

					input {
						box-sizing: border-box;
						width: 490px;
						height: 32px;
						padding: 0px 4px;
						border: 2px solid #ea4a36;
						float: left;

						&:focus {
							outline: none;
						}
					}

					button {
						height: 32px;
						width: 68px;
						background-color: #ea4a36;
						border: none;
						color: #fff;
						float: left;
						cursor: pointer;

						&:focus {
							outline: none;
						}
					}
				}
			}
		}
	}
</style>

components/TypeNav

<template>
	<div class="type-nav">
		<div class="container">
			<!-- 事件的委派|委托 -->
			<div @mouseleave="leaveIndex">
				<h2 class="all">全部商品分类</h2>
				<!-- 三级联动 -->
				<div class="sort">
					<!-- 利用事件的委派+编程式导航实现路由的跳转与传递参数 -->
					<div class="all-sort-list2" @click="goSearch">
						<div class="item" v-for="(c1,index) in categoryList" :key="c1.categoryId"
							:class="{cur:currentIndex==index}">
							<h3 @mouseenter="changeIndex(index)">

								<a :data-categoryName="c1.categoryName" :data-category1Id="c1.categoryId">{{c1.categoryName}}--{{index}}</a>
								<!-- 尝试一下声明式导航 -->
								<!-- <router-link to="/search">{{c1.categoryName}}</router-link> -->

							</h3>
							<!-- 二级三级 -->
							<div class="item-list clearfix" :style="{display:currentIndex==index?'block':'none'}">
								<div class="subitem" v-for="(c2) in c1.categoryChild" :key="c2.categoryId">
									<dl class="fore">
										<dt>
											<a :data-categoryName="c2.categoryName" :data-category2Id="c2.categoryId">{{c2.categoryName}}--{{index}}</a>
											<!-- <router-link to="/search">{{c2.categoryName}}</router-link> -->
										</dt>
										<dd>
											<em v-for="(c3) in c2.categoryChild" :key="c3.categoryId">

												<a :data-categoryName="c3.categoryName" :data-category3Id="c3.categoryId">{{c3.categoryName}}--{{index}}</a>
												<!-- <router-link to="/search">{{c3.categoryName}}</router-link> -->
											</em>

										</dd>
									</dl>
								</div>
							</div>
						</div>

					</div>
				</div>
			</div>
			<nav class="nav">
				<a href="###">服装城</a>
				<a href="###">美妆馆</a>
				<a href="###">尚品汇超市</a>
				<a href="###">全球购</a>
				<a href="###">闪购</a>
				<a href="###">团购</a>
				<a href="###">有趣</a>
				<a href="###">秒杀</a>
			</nav>

		</div>
	</div>
</template>

<script>
	import {
		mapState
	} from 'vuex';
	// 引入方式:是把lodash全部功能函数引入 _.throttle
	// import _ from 'lodash';  
	// 最好的引入方式 按需加载 throttle
	// 默认暴露throttle,引入的时候不用加{{}} 
	import throttle from "lodash/throttle";


	// console.log(_)
	export default {
		// 全局组件的名字
		name: 'TypeNav',
		data() {
			return {
				// 存储用户鼠标移上哪一个一级分类
				currentIndex: -1
			}
		},
		// 组件挂载完毕:可以向服务器发送请求,获取服务器的数据 展示服务器的数据
		mounted() {
			// 通知vuex发请求,获取数据,存储于仓库当中
			this.$store.dispatch('categoryList')
		},
		methods: {
			// 鼠标进入修改响应式数据currentIndex

			changeIndex: throttle(function(index) {
				// console.log(index)
				//index :鼠标移上某一个一级分类元素的索引值
				this.currentIndex = index
				// console.log("鼠标进入" + index)
			}, 50),
			leaveIndex() {
				// 一级分类鼠标移出的事件的回调
				this.currentIndex = -1
			},
			// 进行路由跳转的方法
			goSearch(event) {
				// this.$router.push('/search')

				// 最优秀的解决方案 结合编程式导航和事件的委派进行路由跳转
				// 存在一些问题:事件委派,是把全部的子节点【h3 dt dl em】的事件委派给父亲节点
				// 点击a标签的时候 才会进行路由的跳转【怎么能确定点击的一定是a标签呢】
				// 解决:把子节点当中a标签,我加上自定义属性data-categoryName 其余子节点是没有的
				// 怎么拿到你点击的这个节点,以及判断这个节点是不是a ----event
				let element = event.target;
				// console.log(element)  获取到当前触发这个事件的节点【h3/a/dt/dl】但是我们需要带有data-categoryname这样的节点<==一定是a标签
				// 节点有一个dataset属性,可以获取节点的自定义属性与属性值
				// console.log(element.dataset);
				
				let {categoryname ,category1id,category2id,category3id} = element.dataset;
				// 如果标签身上拥有categoryName那一定是a标签
				if(categoryname){
					// 整理路由跳转的参数
					let location = {name:'search'};
					let query = {categoryName:categoryname};
					// alert('我是a标签')
					// 一级分类、二级分类、三级分类的a标签
					if(category1id){
						query.category1Id = category1id;
					}else if(category2id){
						query.category2Id = category2id;
					}else{
						query.category3Id = category3id;
					}
					// 整理完参数
					// console.log(location,query)
					location.query = query;
					// 然后进行路由跳转
					this.$router.push(location)
				}
				
				// 另外问题:即使你能确定点击的是a标签 又如何区分是一级二级三级分类的标签
				
			}
		},
		computed: {
			...mapState({
				categoryList: state => state.home.categoryList
				// console.log(state);


			})
		}
	}
</script>

<style scoped lang="less">
	.type-nav {
		border-bottom: 2px solid #e1251b;

		.container {
			width: 1200px;
			margin: 0 auto;
			display: flex;
			position: relative;

			.all {
				width: 210px;
				height: 45px;
				background-color: #e1251b;
				line-height: 45px;
				text-align: center;
				color: #fff;
				font-size: 14px;
				font-weight: bold;
			}

			.nav {
				a {
					height: 45px;
					margin: 0 22px;
					line-height: 45px;
					font-size: 16px;
					color: #333;
				}
			}

			.sort {
				position: absolute;
				left: 0;
				top: 45px;
				width: 210px;
				height: 461px;
				position: absolute;
				background: #fafafa;
				z-index: 999;

				.all-sort-list2 {
					.item {
						h3 {
							line-height: 30px;
							font-size: 14px;
							font-weight: 400;
							overflow: hidden;
							padding: 0 20px;
							margin: 0;

							a {
								color: #333;
							}
						}

						.item-list {
							display: none;
							position: absolute;
							width: 734px;
							min-height: 460px;
							background: #f7f7f7;
							left: 210px;
							border: 1px solid #ddd;
							top: 0;
							z-index: 9999 !important;

							.subitem {
								float: left;
								width: 650px;
								padding: 0 4px 0 8px;

								dl {
									border-top: 1px solid #eee;
									padding: 6px 0;
									overflow: hidden;
									zoom: 1;

									&.fore {
										border-top: 0;
									}

									dt {
										float: left;
										width: 54px;
										line-height: 22px;
										text-align: right;
										padding: 3px 6px 0 0;
										font-weight: 700;
									}

									dd {
										float: left;
										width: 415px;
										padding: 3px 0 0;
										overflow: hidden;

										em {
											float: left;
											height: 14px;
											line-height: 14px;
											padding: 0 8px;
											margin-top: 5px;
											border-left: 1px solid #ccc;
										}
									}
								}
							}
						}

						// &:hover {
						// 	.item-list {
						// 		display: block;
						// 	}
						// }
					}
				}

				.cur {
					background: skyblue;
				}

			}
		}
	}
</style>

尚品汇静态源码

views/Home/Floor

由目录我们可以看到Home模块被拆分成了多个小组件,这里我贴一个floor的小组件的代码,其他小组件同理,用静态源码CV过来直接改就行了 没啥难度

<template>
	<!--楼层-->
	<div class="floor">
		<div class="py-container">
			<div class="title clearfix">
				<h3 class="fl">家用电器</h3>
				<div class="fr">
					<ul class="nav-tabs clearfix">
						<li class="active">
							<a href="#tab1" data-toggle="tab">热门</a>
						</li>
						<li>
							<a href="#tab2" data-toggle="tab">大家电</a>
						</li>
						<li>
							<a href="#tab3" data-toggle="tab">生活电器</a>
						</li>
						<li>
							<a href="#tab4" data-toggle="tab">厨房电器</a>
						</li>
						<li>
							<a href="#tab5" data-toggle="tab">应季电器</a>
						</li>
						<li>
							<a href="#tab6" data-toggle="tab">空气/净水</a>
						</li>
						<li>
							<a href="#tab7" data-toggle="tab">高端电器</a>
						</li>
					</ul>
				</div>
			</div>
			<div class="tab-content">
				<div class="tab-pane">
					<div class="floor-1">
						<div class="blockgary">
							<ul class="jd-list">
								<li>节能补贴</li>
								<li>4K电视</li>
								<li>空气净化器</li>
								<li>IH电饭煲</li>
								<li>滚筒洗衣机</li>
								<li>电热水器</li>
							</ul>
							<img src="./images/floor-1-1.png" />
						</div>
						<div class="floorBanner">
							<div class="swiper-container" id="floor1Swiper">
								<div class="swiper-wrapper">
									<div class="swiper-slide">
										<img src="./images/floor-1-b01.png">
									</div>
								
								</div>
								<!-- 如果需要分页器 -->
								<div class="swiper-pagination"></div>

								<!-- 如果需要导航按钮 -->
								<div class="swiper-button-prev"></div>
								<div class="swiper-button-next"></div>
							</div>
						</div>
						<div class="split">
							<span class="floor-x-line"></span>
							<div class="floor-conver-pit">
								<img src="./images/floor-1-2.png" />
							</div>
							<div class="floor-conver-pit">
								<img src="./images/floor-1-3.png" />
							</div>
						</div>
						<div class="split center">
							<img src="./images/floor-1-4.png" />
						</div>
						<div class="split">
							<span class="floor-x-line"></span>
							<div class="floor-conver-pit">
								<img src="./images/floor-1-5.png" />
							</div>
							<div class="floor-conver-pit">
								<img src="./images/floor-1-6.png" />
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	

	
		
	</div>

</template>

<script>
</script>

<style scoped lang="less">
	.floor {
		margin-top: 15px;

		.py-container {
			width: 1200px;
			margin: 0 auto;

			.title {
				.fl {
					float: left;
					color: #c81623;
					font-size: 20px;
					line-height: 30px;
					margin: 9px 0;
					font-weight: 700;
				}

				.fr {
					float: right;

					.nav-tabs {
						margin: 10px 0 0;
						display: inline-block;

						li {
							float: left;
							line-height: 18px;

							a {
								padding-top: 1px;
								font-weight: 400;
								background-color: #fff;

								&::after {
									content: "|";
									padding: 0 10px;
								}
							}

							&:nth-child(7) {
								a {
									&::after {
										content: "";
									}
								}
							}

							&.active {
								a {
									color: #e1251b;
								}
							}
						}
					}
				}
			}

			.tab-content {
				border-top: 2px solid #c81623;
				border-bottom: 1px solid #e4e4e4;

				.tab-pane {
					.floor-1 {
						height: 360px;
						display: flex;

						.blockgary {
							width: 210px;
							height: 100%;
							background: #f7f7f7;

							.jd-list {
								padding: 15px 0;
								overflow: hidden;

								li {
									list-style-type: none;
									float: left;
									width: 40%;
									margin: 0 10px;
									border-bottom: 1px solid #e4e4e4;
									text-align: center;
									line-height: 26px;
								}
							}

							img {
								width: 100%;
							}
						}

						.floorBanner {
							width: 330px;
							height: 100%;
						}

						.split {
							width: 220px;
							height: 100%;
							position: relative;

							.floor-x-line {
								position: absolute;
								background: #e4e4e4;
								width: 220px;
								height: 1px;
								top: 180px;
							}

							.floor-conver-pit {
								width: 100%;
								height: 50%;

								img {
									width: 100%;
									height: 100%;
									transition: all 400ms;

									&:hover {
										opacity: 0.8;
									}
								}
							}
						}

						.center {
							border: 1px solid #e4e4e4;
						}
					}
				}
			}
		}
	}
</style>

登录注册搜索模块还没做效果 只做了路由跳转部分 就不贴下面那样代码了

views/Login

<template>
	<div>登录</div>
</template>

<script>
</script>

<style>
</style>

views/Search

<template>
	<div>
		<h1>params参数{{$route.params.keyword}}=======</h1>
		<h2>query参数{{$route.query.k}}</h2>
		
	</div>
</template>

<script>
	export default{
		name:'',
		路由组件能传递props数据
		props:['keyword','a','b']
	}
</script>

<style>
</style>

router:

import Vue from 'vue';
import VueRouter from 'vue-router';
//使用插件
Vue.use(VueRouter);
//配置路由
//引入路由组件
import Home from '@/views/Home'
import Search from '@/views/Search'
import Login from '@/views/Login'
import Register from '@/views/Register'
//先把VueRouter原型对象的push,先保存一份
let originPush = VueRouter.prototype.push;
let originReplace = VueRouter.prototype.replace;
//重写push|replace
//第一个参数:告诉原来push方法,你在哪里跳转(传递哪些参数)
//第二个参数:成功回调
//第三个参数:失败的回调
//call || apply区别
//相同点 都可以调用函数一次,都可以篡改函数的上下文一次
//不同点:call与apply传递参数,call传递参数用逗号隔开,apply方法执行,传递数组
 VueRouter.prototype.push = function(location,resolve,reject){
	if(resolve&&reject){
		originPush.call(this,location,resolve,reject)
	}else{
		originPush.call(this,location,()=>{},()=>{});
	}
}
VueRouter.prototype.replace = function(location,resolve,reject){
	if(resolve&&reject){
		originReplace.call(this,location,resolve,reject)
	}else{
		originReplace.call(this,location,()=>{},()=>{});
	}
}
export default new VueRouter({
	//配置路由
	routes:[
		{
			path:'/',
			redirect:'/home'
		},
		{
			path:'/home',
			component:Home,
			meta:{show:true}
		},
		{
			path:'/search/:keyword',
			component:Search,
			meta:{show:true},
			name:'search',
			//路由组件能不能传递props数据?
			//布尔值写法:params
			// props:true
			//对象写法,额外给路由组件传递一些props
			// props:{a:1,b:2}
			//函数写法:可以把params参数 query参数 通过props传递给路由组件
			// props:($route)=>{
			// 	return{keyword:$route.params.keyword,K:$route.query.k}
			// }
			props:($route)=>({keyword:$route.params.keyword,k:$route.query.k})
		},
		{
			path:'/login',
			component:Login,
			meta:{show:false}
		},
		{
			path:'/register',
			component:Register,
			meta:{show:false}
		},
	]
})

App.vue

<template>
	<div>
		<Header></Header>
		<!-- 路由组件出口的地方 -->
		<router-view></router-view>
		<!-- 在Home、Search显示,在Login、Register隐藏 -->
		<Footer v-show="$route.meta.show"></Footer>
	</div>
</template>

<script>
	// import HelloWorld from './components/HelloWorld.vue'
	import Header from './components/Header'
	import Footer from './components/Footer'
	export default {
		name: '',
		components: {
			Header,
			Footer
		}
	}
</script>

<style>
	/* #app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
} */
</style>

main.js

import Vue from 'vue'
import App from './App.vue'
//三级联动组件 ---- 注册成全局组件
import TypeNav from '@/components/TypeNav';
//第一个参数 全局组件的名字 第二个参数 哪一个组件
Vue.component(TypeNav.name,TypeNav);
//引入路由
import router from '@/router';
//引入仓库
import store from '@/store';
Vue.config.productionTip = false
//测试
// import {reqCategoryList} from '@/api';
// reqCategoryList();

new Vue({
  render: h => h(App),
  //注册路由 :底下的写法kv一致省略v
  router,
  //注册仓库:组件实例的身上,会多了一个$store属性
  store
}).$mount('#app')

api/index.js

//当前模块 api进行亭驿馆里
import requests from './request';


//三级联动接口
//  /api/product/getBaseCategoryList  get 无参数
	//发请求 axios发请求返回的是promise对象
export const reqCategoryList = ()=>requests({url:'/product/getBaseCategoryList',method:'get'});

 api/request.js

//对于axios进行二次封装
import axios from "axios";
// 引入进度条
import nprogress from 'nprogress';
//引入进度条样式
import "nprogress/nprogress.css";
// console.log(nprogress);
//start:进度条开始 done:进度条结束



//1.利用axios对象的方法create,去创建一个axios实例
//request 就是axios,只不过稍微配置一下
const requests = axios.create({
	//配置对象
	//基础路径,发送请求的时候,路径中会出现api
	baseURL:"/api",
	//代表请求超时的时间5s
	timeout:5000
});
//请求拦截器:在发请求之前,请求拦截器可以检测到,可以在请求发出去之前做一些事情

requests.interceptors.request.use((config)=>{
	//config:配置对象,对象里面里边的一个属性很重要,header请求头
	//请求时,进度条开始动
	nprogress.start();
	return config
})

//响应拦截器
requests.interceptors.response.use((res)=>{
	//服务器成功的回调函数 服务器响应数据回来以后,响应拦截器可以检测到,可以做一些事情
	//响应完成 进度条结束
	nprogress.done();
	return res.data;
},(error)=>{ // eslint-disable-line no-unused-vars
	//服务器相应失败 回调函数
	//终结promise链
	return Promise.reject(new Error('faile'));
});




//对外暴露
export default requests;

store/index.js

import Vue from 'vue';
import Vuex from 'vuex';
//需要使用插件一次
Vue.use(Vuex);
//引入小仓库
import home from './home/';
import search from './search';
// //对外暴露store类的一个实例
export default new Vuex.Store({
	//实现vuex仓库模块式开发存储数据
	modules:{
		home,search
	}
})

 store/home/index.js

import {reqCategoryList} from '@/api';
// home模块小仓库
const state = {
	// state中的数据默认初始值不要瞎写,服务器返回谁你的初始值就要是谁,服务器返回数组你的初始值就要是数组 返回对象 初始值是对象
	categoryList:[]
};
const mutations = {
	CATEGORYLIST(state,categoryList){
		state.categoryList = categoryList;
	}
};
const getters = {};
const actions = {
	//通过API里面的接口函数调用,向服务器发请求,获取服务器的数据
	async categoryList({commit}){
		let result = await reqCategoryList();
		// console.log(result);
		if (result.code==200){
			commit("CATEGORYLIST",result.data);
		}
	}
};
// 对外暴露 别的模块才能使用
export default {
	state,
	mutations,
	getters,
	actions

}

  store/search/index.js

// search模块小仓库
const state = {};
const mutations = {};
const getters = {};
const actions = {};
// 对外暴露 别的模块才能使用
export default {
	state,
	mutations,
	getters,
	actions

}

emm....差不多代码就这些...代码太多了可能有遗漏的地方 大家哪里看不懂或者我丢了的地方 可以直接评论 我再修改 我们一起学习!!!

---------------------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------------------

3.一些知识点

9.vuex状态管理

9.1 vuex是什么?

vuex是官方提供的一个插件,状态管理库,集中式管理项目中组件的共用数据
切记并不是全部的项目都需要vuex
(项目很小 组件很少可以不用vuex,反之数据很多,数据维护费劲可以使用vuex)
modules
actions
getters
mutation
state


9.2 vuex基本使用

// //state:仓库存储数据的地方 即状态
// const state = {}
// //mutations:修改state的唯一手段
// const mutations = {}
// //action:处理action,可以书写自己的业务逻辑 也可以处理异步
// const actions = {}
// //getters:理解为计算属性 用于简化仓库的数据,让组件获取仓库的数据更加方便
// const getters = {}

9.3 vuex实现模块式开发
如果项目过大,组件过多,接口也很多 数据也很多 可以让vuex实现模块开发

把所有的全局组件都放到components当中
拿到promise的成功的结果 await
await和async必须同时存在

完成一级分类动态添加背景颜色
1.采用样式完成----.item:hover{
                    background: skyblue;
                }
2.通过js去完成-----

通过js控制二三级商品分类的显示与隐藏

<div class="item-list clearfix" :style="{display:currentIndex==index?'block':'none'}">
                                <div class="subitem" v-for="(c2) in c1.categoryChild" :key="c2.categoryId">
                                    <dl class="fore">
                                        <dt>
                                            <a href="">{{c2.categoryName}}</a>
                                        </dt>
                                        <dd>
                                            <em v-for="(c3) in c2.categoryChild" :key="c3.categoryId">
                                                <a href="">{{c3.categoryName}}</a>
                                            </em>

                                        </dd>
                                    </dl>
                                </div>
                            </div>

最开始的时候是通过css样式display:block|none显示与隐藏二三级商品分类
// &:hover {
                        //     .item-list {
                        //         display: block;
                        //     }
                        // }
                        
3)演示卡顿现象
正常:事件触发非常频繁,而且每一次的触发,回调函数都要去执行
(如果时间很短,而回调函数内部有计算,那么很可能出现浏览器卡顿)
节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发(闭包延时器)_.throttle
用户操作很频繁,但是把频繁的操作变为少量操作【可以给浏览器充足的时间解析代码】
防抖:前面的所有的触发都被取消,最后一次执行 在规定的时间之后才会触发,也就是说如果连续快速的触发 只会执行一次
用户操作很频繁,但是只执行一次

//lodash插件:里面封装函数的防抖与节流的业务【闭包+延迟器】
//1.lodash函数库对外暴露_函数
debounce函数
let result = _.debounce(function(){

},1000);
result();

三级联动组件的路由跳转与传递参数
三级联动用户可以点击的:一级分类、二级分类、三级分类、当你点击的时候 Home模块 跳转到Search模块,
一级会把用户选中的产品(产品的名字、产品的ID)在路由跳转的时候,进行传递。

路由跳转 
声明式导航:router-link
编程式导航:push|replace(可以书写自己的业务逻辑)


三级联动这里 如果使用声明式导航router-link 可以实现路由的跳转 但是出现了卡顿现象
router-link:可以一个组件,当服务器数据返回之后,循环出很多的router-link组件【创建组件实例多】
创建组件实例的时候,一瞬间创建1000+ 很耗内存,因此出现了卡顿现象。

所以我们采用编程式导航

最优秀的解决方案 结合编程式导航和事件的委派进行路由跳转

------------------------------未完待续---------------------


 

标签:尚品,height,width,组件,import,硅谷,路由,left
来源: https://blog.csdn.net/m0_61726249/article/details/121726145