尚硅谷尚品汇学习笔记03 三级联动态数据、节流、路由跳转

242 阅读1分钟

note

1. vue模块开发

  • 当项目比较大,组件通信数据比较复杂,这种情况在使用vuex Vuex是插件,通过vuex仓库进行存储项目的数据
  • vuex模块式开发【modules】 由于项目体积比较大,你向服务器发请求的接口过多,服务器返回的数据也会很多,如果还用以前的方式存储数据,导致vuex中的state数据格式比较复杂。采用vuex模块式管理数据。 Vuex核心概念:state、actions、mutations、getters、modules

1:重写push与replace方法 工作的时候想处理掉,不想处理对于你的程序没有任何影响 function push(){ return new Promise(resolve,reject){

}

}

2. 商品分类三级联动展示动态数据

1.数据的获取,在组件中使用获取数据的方法

  1. TypeNav三级联动展示动态数据,全局组件,放在component中
  2. 组件挂载完毕,发送请求,通知vue发送请求,获取数据,存储于仓库中 TypeNav/index.js
  • 挂载的时候发送请求,获取数据。用计算属性“接”返回的数据
  mounted() {
    // 通知vue发送请求,获取数据,存储于仓库中
    this.$store.dispatch("categoryList");
  },
    computed: {
    // 对象写法:name:函数(1. 会注入一个参数state,是大仓库的数据 2. 当使用此计算属性时,此函数会立即被调用)
    ...mapState({
      categoryList: (state) => {
        return state.home.categoryList;
      },
    }),
  },
  • 以前基础课程的时候,发请求操作如下:在组件的mounted中书写axios.get||post,获取到数据存储到组件的data当中进行使用

  • 你们写项目的时候发请求在哪里发呀? mounted|created:都可以 mounted:模板已经变为真是DOM【只不过没有数据,显示空白】,因为ajax是异步,需要时间的。 created:稍微好那么一丢丢(不算啥)

2.数据结构的分析

[
    {
        id:1,categoryName:'图书',
        child:[
             {id:3.14,
              categoryName:'影像'child:[
                   {id:4,categoryName:'华为'}
              ]
             }
        ]
    }
]
// 根据返回的数组,使用v-for

3.vuex 中的共享数据,请求数据的方法

store/search.js

  • 在actions中发送异步的数据请求reqCategoryList,根据返回状态调用mutations里的方法[[06async 与 await]]
  • 在mutations里面修改数据
  • 根据返回的数组的类型,在state中为数据设初始值
const state = {
    //* state中的默认初始值不要瞎写,与服务器返回值类型一致
    categoryList: []
};
const mutations = {
    GATEGORYLIST(state, categoryList) {
        state.categoryList = categoryList;
    }
};

const actions = {
    async categoryList({ commit }) {
        // 通过api里面的函数接口调用,想服务器发请求,获取数据.根据接口的返回值初始化
        let result = await reqCategoryList();
        // console.log(result);
        if (result.code == 200) {
            commit("GATEGORYLIST", result.data)
        }
    }
};

4.跨域问题的解决

[[vue_cli#13 vue脚手架配置代理服务器]] [[05跨域]] 本地代理服务器 vue.config,js

  //*配置代理跨域
  // !服务器与服务器之间无跨域问题,浏览器与服务器有
  devServer: {
    proxy: {
      "/api": {
        target: "http://gmall-h5-api.atguigu.cn",
      },
    },
  }

3. 三级联动动态背景颜色

第一种解决方案:CSS hover 怎么接单怎么来

  1. 设置一个currentIndex存储用户鼠标移到了哪一个一级分类,并设置changeIndex,leaveIndex改变currentIndex的值
  data() {
    return {
      // 存储用户鼠标移到了哪一个一级分类
      currentIndex: -1, //*
    };
  },
    methods: {
    // 鼠标进入,修改currentIndex
    changeIndex(index) {
      // index:鼠标移到哪一个一级分类的索引值
      this.currentIndex = index;
    },
    leaveIndex() {
      // 鼠标移出
      this.currentIndex = -1;
    }
  },
  1. vue的class绑定之对象写法:currentIndex的值与当前index相等,使用此class
 <h3 @mouseenter="changeIndex(index)" :class="{ cur: currentIndex == index }">
                <a href="">{{ c1.categoryName }}</a>
 </h3>
  1. 时间委托。把mouseleave事件委托给公共的父盒子
<div @mouseleave="leaveIndex">
	<h2 class="all">全部商品分类</h2>
	<div class="sort">···
	</div>
</div>

4. 通过js控制二三级菜单的显示与隐藏

  1. css方法:display:none/block隐藏与显示二三级菜单
  2. js :
 <!-- 二级分类 -->
 <div class="item-list clearfix" :style="{display:currentIndex == index?'block':'none'}">

5.防抖与节流

卡顿现象:用户触发过快。浏览器执行不过来==> 触发多个不重复事件,没有全部执行 @mouseenter="changeIndex(index)" 可能发生

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

1.防抖

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

 <body>
    <button id="debounce">防抖</button>
    <script>
      // 防抖
      /* 函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。 */
      function debounce(fn, wait) {
        let timer = null;
        return function () {
          let context = this,
            args = arguments;
          if (timer) {
            clearTimeout(timer);
            //清空timer
            timer = null;
          } else {
            timer = setTimeout(() => {
              // 用apply改变this走向
              fn.apply(context, args);
            }, wait);
          }
        };
      }
      //   防抖测试
      document.querySelector("#debounce").onclick = debounce(() => {
        console.log("debounce");
      }, 2000);
    </script>

2.节流

节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发

 <body>
    <button id="throttle">节流</button>
    <script>
      //   节流
      /* 函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。 */
      function throttle(fn, delay) {
        let curTime = Date.now();
        // Date.now() 方法返回自 1970 年 1 月 1 日 00:00:00 (UTC) 到当前时间的毫秒数。
        return function () {
          let nowTime = Date.now(),
            context = this,
            args = arguments;
          // 如果两次时间间隔超过了指定时间,则执行函数
          if (nowTime - curTime >= delay) {
            fn.apply(context, args);
            curTime = Date.now();
          }
        //   !只有触发成功了才会更新时间
        };
      }
      // 节流测试
      document.querySelector("#throttle").onclick = throttle(() => {
        console.log("throttle");
      }, 2000);
    </script>

D:\我的学习\前端\基础算法\手撕\02防抖节流.html

  • 防抖与节流的原理,通过JS实现【闭包 + 延迟器】

3.三级联动的节流操作

  1. 引入lodash, node_modules中已经引入
import throttle from 'lodash/throttle';//按需引入,throttle默认暴露,不需要加{}
methods: {

    // 鼠标进入,修改currentIndex
    // changeIndex(index) {
    //   // index:鼠标移到哪一个一级分类的索引值
    //   this.currentIndex = index;
    //   console.log("鼠标进入"+index);
    // },
    changeIndex: throttle(function (index) {
      // throttle不要使用箭头函数,可能出现this问题
      this.currentIndex = index;
      console.log("鼠标进入" + index);
    }, 50),
  },

6.三级联动路由跳转与传参

1. 需求分析

  1. 路由跳转-参数传递:categoryName categoryId%%路由跳转的时候【home->search】:需要进行路由传递参数【分类的名字、一、二、三级分类的id】%%
  2. 卡顿现象-编程式路由导航 %%三级分类由于使用router-link的时候,会出现卡顿现象,因此采用编程式导航。 两种路由导航
  • 声明式导航:为什么使用router-link组件的时候,会出现卡顿那? router-link是一个组件:相当于VueComponent类的实例对象,当服务端返回数据后,会循环出很多router-link组件,一瞬间 new VueComponent很多实例(1000+),很消耗内存,因此导致卡顿。
  • 编程式导航:push|replace%%
  1. 要绑定的路由跳转事件太多===>事件委派

2.解决方案

编程式导航+事件委派 ===>路由跳转+传参数 存在问题:使用事件委派后,如何辨别点击的时目标标签?如何辨别点击时几级标签?自定义属性 新知识: 1. element.dataset,存储当前节点的自定义属性与属性值 2. 浏览器会自动把自定义属性的名字全部改为小写 %%事件委派,把所有的子节点都(h3,3m,dt,dl)等都委托给父节点。但当点击a标签的时候,才会进行跳转。

  • 如何辨别点击的目标标签?如何辨别点击时几级标签? 解决方案:a标签加上自定义属性,event.target (触发当前事件的dom元素)%%
  1. 加上自定义属性
<a 
   :data-categoryName="c1.categoryName"
   :data-category1Id="c1.categoryId"
   >{{ c1.categoryName }}</a>
  1. 根据自定义属性判断a标签,是几级标签
  2. 整理路由参数location
 goSearch(event) {
      let element = event.target;
      // 1. element.dataset,存储当前节点的自定义属性与属性值
      // 2. 浏览器会自动把自定义属性的名字全部改为小写
      let { categoryname, category1id, category2id, category3id } = element.dataset;//对象的解构赋值
      //  todo 整理路由参数
      let location = { name: 'Search' };
      let query = { categoryName: categoryname }
      // *判断是否为a标签:自定义标签上有categoryname的是a标签
      // *判断为几级标签:自定义标签是category1id,还是category2id,还是category3id
      if (categoryname) {
        if (category1id) {
          query.category1Id = category1id
        } else if (category2id) {
          query.category2Id = category2id
        } else if (category3id) {
          query.category3Id = category3id
        }
      }
      // todo 路由参数整理完毕
      location.query = query;
      // todo路由跳转
      this.$router.push(location)
    }

location 内部结构示例

this.$router.push()
{ 
 name:'search',
 query:{
    categoryName:'电子书',
    category2Id:4
 }
}

question

报错

1. Uncaught ReferenceError: VueX is not defined vuex的模块化与一般形式

面试

1.性能优化

v-if|v-show 按需加载 函数防抖与节流 按需加载:对于loadsh插件,它里面封装的函数功能很多;import _ from lodash 相当于把全部功能引入进来,但是我们只是需要节流。