vue尚品汇商城项目-day02【15.动态展示三级菜单联动】

在这里插入图片描述

15.动态展示三级菜单联动

问题1:

在这里插入图片描述

代码:

<script>
export default {
  name: "TypeNav",
  computed:{
    ...mapState({categoryList:state=>state.home.categoryList})
  }
}
</script>

原因分析:因为缺少mapState引入,所以报错mapState不认识,添加引入即可

import { mapState } from "vuex";

15.1动态调用展示三级菜单步骤

简单总结使用步骤:

  1. 在字模块actions、mutations中定义函数
  2. 在App.vue中触发调用
  3. 编写计算属性,这样state中就已经保存最新的数据了
  4. 在模板代码处遍历动态拼接最新的数据,进行展示

详细使用步骤:

  • 第1步:/store/home/index.js引入方法定义actions、mutations中的函数。
import {getCategoryList} from '@/api'
//Home模块的小仓库
//actions代表一系列动作,可以书写自己的业务逻辑,也可以处理异步
const actions = {
    //getCategoryList返回的是一个Promise对象
    //需要用await接受成功返回的结果,await必须要结合async一起使用(CP)
    async getCategoryList(context) {
        let response = await getCategoryList();
        if (response.code == 200) {
            context.commit("GETCATEGORYLIST", response.data)
        }
    }
}
//mutations代表维护,操作维护的是state中的数据,且state中数据只能在mutations中处理
const mutations = {
    GETCATEGORYLIST(state, categoryList) {
        state.categoryList = categoryList
    }
}
//state代表仓库中的数据
const state = {
    //home仓库中存储三级菜单的数据
    categoryList:[]
}
//getters理解为计算属性,用于简化仓库数据,让组件获取仓库的数据更加方便
const getters = {}

//创建并暴露store
export default {
    actions,
    mutations,
    state,
    getters
}
  • 第2步:在App.vue中定义mounted钩子函数,派发一个action,获取商品分类的三级列表的数据。
mounted() {
    //派发一个action||获取商品分类的三级列表的数据
    this.$store.dispatch("getCategoryList")
  }
  • 第3步:/components/TypeNav/index.vue,在要使用state数据的地方使用mapState生成计算函数,然后模板中循环遍历使用数据。
<div class="item bo" v-for="(c1,index) in categoryList" :key="c1.categoryId">
    <h3>
        <a href="">{
   
   {c1.categoryName}}</a>
    </h3>
</div>

computed:{
    ...mapState({categoryList:state=>state.home.categoryList})
  }

问题2:为啥actions定义的getCategoryList函数要使用async+await?

答案:因为getCategoryList函数函数最后返回的是一个promise的对象,如图,而我们直接想要的是成功的回调函数,所以用async+await可直接获取到。

在这里插入图片描述

扫描二维码关注公众号,回复: 14797122 查看本文章

15.2完成一级菜单鼠标划入显示背景色

效果如下:

在这里插入图片描述

共有2种方式:

  • 方式1:css直接使用:hover添加背景色,知识点:hover在鼠标移到链接上时添加的特殊样式
//方式1::hover
.item:hover {
 	background: skyblue;
}
  • 方式2:通过定义鼠标划入事件添加背景色,思路说明,每一项都有自己的index,我们初始化currentIndex为-1,当鼠标划入时修改currentIndex的值,当判断currentIndex == index时动态绑定样式,同时搭配@mouseenter和@mouseleave即可实现划入划出的背景效果。
<div @mouseleave="leaveIndex" >
<h3 @mouseenter="changeIndex(index)" :class="{cur: currentIndex == index }">

methods: {
    //用于修改组件实例身上的currentIndex的属性值
    //当用户鼠标移入到h3身上的时候就会立即出发一次
    changeIndex(index) {
      this.currentIndex = index;
    },
    //当鼠标离开的时候,让商品分类列表进行隐藏
    leaveIndex() {
      this.currentIndex = -1;
    }
}
  
.cur {
    background: skyblue;
}

注意点1:mouseenter:当鼠标移入元素本身(不包含元素的子元素)会触发事件,事件不会叠加。对应的移除事件是 mouseleave。

注意点2:现在想实现个新效果,鼠标从第一项划入“全部商品分类”也不会去除背景色,具体效果如图,具体方案可采用“事件委派”指的是把事件委派给父亲元素去控制,逻辑就是把“全部商品分类”和一级菜单用一个div单独包起来,在外侧进行划出控制。

15.3控制二三级商品分类的显示与隐藏

共有2种方式:

  • 方式1:通过css的:hover控制display的block|none显示与隐藏
.item-list {
            display: none;
            ...
}
&:hover {
    .item-list {
        display: block;
    }
}
  • 方式2:通过js的方式控制display的显示与隐藏
 <div class="item-list clearfix" :style="{display: currentIndex == index ? 'block' : 'none'}">

问题:css中的&:hover,中的&啥意思?

答案:

贴个CSS代码进行讲解

.box{
		&:before{
			border-color: red;
		}
		&:after{
			border-color: green;
		}
	}

& 表示在嵌套层次中回溯一层,即&:before相当于.box:before

15.4演示卡顿现象引入防抖与节流

正常:事件触发非常频繁,而且每一次的触发,回调函数都要去执行(如果时间很短,而回调函数内部有计算,那么很可能出现浏览器卡顿现象),正常效果如图1,错误效果如,2。

在这里插入图片描述

如图1

在这里插入图片描述

如图2

节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发【给浏览器有充裕的时间解析代码】。

防抖:前面的所有的触发都被取消,最后一次执行在规定的时间之后才会触发,也就是说如果连续快速的触发只会执行一次。

注意点0:

安装命令:cnpm install --save lodash

使用方式:

//引入lodash:是把lodash全部封装好的函数全都引入进来了
//按需引入:只是引入节流函数,其他的函数没有引入(模块),这样做的好处是,当你打包项目的时候体积会小一些
import throttle from "lodash/throttle";

changeIndex: throttle(function(index) {
      //修改当前currentIndex索引值
      //函数节流:在20MS时间之内只能执行一次
      this.currentIndex = index;
    }, 20),

注意点1:可使用lodash插件:里面封装函数的防抖与节流的业务方法【闭包+延迟器】

注意点2:防抖与节流区别是啥?

答案:“节流”是规定时间内只执行一次,而“防抖”是无论多长时间我都是最后执行一次。

注意点3:lodash官网:https://www.lodashjs.com/

防抖:debounce(func, [wait=0], [options=])

节流:throttle(func, [wait=0], [options=])

15.5三级联动组件的路透跳转与传递参数

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

路由跳转:

  • 声明式导航:router-link

  • 编程式导航:push|replace

问题1:选用“声明式导航”还是“编程式导航“?

答案:应该选用编程式导航。如果使用声明式导航router-link,可以实现路由的跳转与传递参数,但是需要注意,会出现卡顿现象,因为三级联动菜单是循环遍历产生的,如果循环遍历1000次那得新生成/标签,很占用内存,肯定会卡顿。

问题2:既然选择”编程式导航“,那么是/标签绑定点击事件?还是采用其他方式?

答案:不能采用a标签绑定事件方式,应该采用“父元素委托事件”方式。因为这样只需定义一次函数即可,而采用a标签我还得循环遍历定义1000次函数。

问题3:我们想要效果是点击a标签才跳转路由,如何确认a标签?

答案:给a标签绑定自定义属性,使用event.target.dataset可以获取自定义属性名称,能获取自定义属性名称的一定是我们要的a标签。

问题4:采用“父元素委托事件”方式后,会出现如图错误效果:当点击1级菜单时 -> 先跳转到搜索页 -> 又自动跳转到首页

答案:把/标签的href属性必须删掉

问题5:自定义属性名为啥叫 data-xxx,输出打印的dataset名称全是小写,但是为啥前面的data-没了?举例说明自定义属性名称叫:data-categoryName,为啥最后dataset获取的名称却是categoryname,明显前缀data-没了,而且莫名变成小写了?

在这里插入图片描述

答案:JS中要想使用dataset获取自定义属性,那么在HTML模板中自定义属性名必须叫“data-xxx”。

下方为别人博客摘抄:

HTML5 中添加了 data-* 的方式来自定义属性,实际上就是在自定义属性名前加上前缀data- 即可,使用这样的结构可以进行数据存放。使用data-* 可以解决自定义属性混乱无管理的现状。

一个自定义一旦加上了前缀 data- ,那么在 JS 中就可以通过 elementNodeObject.dataset拿到这个属性,显然 dataset 是 attribute 集合的一个子集。
dataset 属性的值是 DOMStringMap的一个实例,也就是一个名值对儿的映射。在这个映射中,每个 data-name 形式的属性都会有一个对应的属性,只不过没有 data- 前缀。

完整代码 src/commponents/TypeNav/index.vue

<!--1级联动菜单-->
        <div class="sort">
          <div class="all-sort-list2" @click="goSearch">
            <div class="item bo" v-for="(c1,index) in categoryList" :key="c1.categoryId">
              <h3 @mouseenter="changeIndex(index)" :class="{cur: currentIndex == index }">
                <a :data-categoryName="c1.categoryName" :data-category1Id="c1.categoryId">{
   
   {c1.categoryName}}</a>
              </h3>
              <!--方式2:通过js的方式控制display的显示与隐藏-->
              <div class="item-list clearfix" :style="{display: currentIndex == index ? 'block' : 'none'}">
                <div class="subitem">
                  <!--2级联动菜单-->
                  <dl class="fore" v-for="(c2,index) in c1.categoryChild" :key="c2.categoryId">
                    <dt>
                      <a :data-categoryName="c2.categoryName" :data-category2Id="c2.categoryId">{
   
   {c2.categoryName}}</a>
                    </dt>
                    <dd>
                      <!--3级联动菜单-->
                      <em v-for="(c3,index) in c2.categoryChild" :key="c3.categoryId">
                        <a :data-categoryName="c3.categoryName" :data-category3Id="c3.categoryId">{
   
   {c3.categoryName}}</a>
                      </em>
                    </dd>
                  </dl>
                </div>
              </div>
            </div>
          </div>
        </div>
------------------------------------------------------------------------------------------------------
//进行路由跳转的回调函数
    goSearch(event) {
      //最好的解决方案:编程式导航+事件委派
      //存在一些问题:事件委派,是把全部的子节点【h3、dt、dl、em】的事件委派给父亲节点
      //问题1:点击a标签的时候,才会进行路由跳转【怎么能确认点击的一定是a标签?】
      //答案:给a标签绑定自定义data-categoryName属性,只要能获取到自定义属性就代表是a标签
      //event.target:获取到的是触发事件的元素(div、h3、a、em、dt、dl)
      let element = event.target;
      //节点有一个属性dataset,可以过去节点的自定义属性与属性值
      let {categoryname, category1id, category2id, category3id} = element.dataset;
      //如果标签身上带有categoryname一定是a标签,且当前这个if语句:一定是a标签才会进入
      if (categoryname) {
        //准备路由跳转的参数对象
        let location = {name: 'search'}
        let query = {categoryName: categoryname}
        //一级目录
        if(category1id) {
          query.category1Id = category1id
          //二级目录
        } else if (category2id) {
          query.category2Id = category2id
          //三级目录
        } else {
          query.category3Id = category3id
        }
        //动态给location配置对象添加query属性
        location.query = query;
        //路由跳转
        this.$router.push(location);
      }
    }

问题6:Vue项目启动默认打开http://0.0.0.0:8080,浏览器显示无法访问,而输入http://localhost:8080就能展示页面

在这里插入图片描述

解决方案:在vue.config.js文件中新增一行:host: 'localhost’即可。

module.exports = {
  productionSourceMap:false,
  // 关闭ESLINT校验工具
  lintOnSave: false,
  devServer: {
    //代理服务器解决跨域
    proxy: {
      "/api": {
        target: "http://39.98.123.211:8510"
      },
    },
    //解决默认打开浏览器,会出现0.0.0.0:8080,浏览器显示无法访问
    host: 'localhost'
  }
};

本人其他相关文章链接

1.vue尚品汇商城项目-day02【9.Home组件拆分+10.postman测试接口】
2.vue尚品汇商城项目-day02【vue插件-13.nprogress进度条的使用】
3.vue尚品汇商城项目-day02【11.对axios二次封装+12.接口统一管理】
4.vue尚品汇商城项目-day02【14.vuex状态管理库】
5.vue尚品汇商城项目-day02【15.动态展示三级菜单联动】

猜你喜欢

转载自blog.csdn.net/a924382407/article/details/129893255
今日推荐