尚硅谷-尚品汇
作者:互联网
目录
三天一更新 总结一下三天学习成果
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