做项目中遇到的一些细节

axios的二次封装

后台管理系统

import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
​
// create an axios instance
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
})
​
// 请求拦截器 携带的token字段
service.interceptors.request.use(
  config => {
    // do something before request is sent
​
    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['token'] = getToken()
    }
    return config
  },
  error => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)
​
// 相应拦截器
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
  */
​
  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  response => {
    const res = response.data
​
    // 服务器响应失败在干什么 真实服务器返回的可能是20000 也可能是200
    if (res.code !== 20000 && res.code !== 200) {
      Message({
        message: res.message || 'Error',
        type: 'error',
        duration: 5 * 1000
      })
​
      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
        // to re-login
        MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
          confirmButtonText: 'Re-Login',
          cancelButtonText: 'Cancel',
          type: 'warning'
        }).then(() => {
          store.dispatch('user/resetToken').then(() => {
            location.reload()
          })
        })
      }
      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      // 服务器响应成功在干什么
      return res
    }
  },
  error => {
    console.log('err' + error) // for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)
​
export default service

前台管理系统(尚品汇)

// 对于axios进行二次封装
import axios from 'axios'
// 引入进度条
import nprogress from 'nprogress'
// 引入进度条样式
import 'nprogress/nprogress.css'
// start:进度条开始 done:进度条结束
​
//在当前模块中引入store
import store from '@/store' 
​
​
// 1.利用axios对象的方法create 去创建一个axios实例
// 2.request就是axios 只不过稍微配置一下
const requests = axios.create({
    // 配置对象
    // 基础路径 发请求的时候 路径当中会出现api
    baseURL:'/api',
    // 代表请求超时的时间5s
    timeout:5000,
​
});
​
// 请求拦截器:在发请求之前 请求拦截器可以检测到 可以在请求发出去之前做一些事情
requests.interceptors.request.use((config)=>{
    // config:配置对象 对象里面有一个属性很重要 header请求头
    if(store.state.detail.uuid_token){
        // 请求头添加一个字段(userTempId) 和后台老师商量好了
        config.headers.userTempId = store.state.detail.uuid_token
    }
    //需要携带token带给服务器
    if(store.state.user.token){
        config.headers.token = store.state.user.token
    }
    // 进度条开始动
    nprogress.start();
    return config;
})
​
// 响应拦截器
requests.interceptors.response.use((res)=>{
    // 成功的回调函数:服务器响应数据回来以后 响应拦截器可以检测到 可以做一些事情
    // 进度条借宿
    nprogress.done()
    return res.data
},(error)=>{
    // 响应失败的回调函数
    return Promise.reject(new Error('faile'))
})
​
export default requests

Axios发送请求时params和data的区别

1,params是添加到url的请求路径中后面用于get请求;
2,data是添加到请求体(body)中用于post请求。

浅拷贝和深拷贝

如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。

浅拷贝

我们来举个浅拷贝例子:

let a=[0,1,2,3,4],
    b=a;
console.log(a===b);
a[0]=1;
console.log(a,b);

嗯?明明b复制了a,为啥修改数组a,数组b也跟着变了,这里我不禁陷入了沉思。

 

深拷贝

1.我们怎么去实现深拷贝呢,这里可以递归递归去复制所有层级属性。

这么我们封装一个深拷贝的函数(PS:只是一个基本实现的展示,并非最佳实践)

采用递归去拷贝所有层级属性

//单级层次的对象或数组
function deepClone(obj){
    //Array.isArray()用来确定传递的值是否是一个Array
    let objClone = Array.isArray(obj)?[]:{};  
    if(obj && typeof obj==="object"){
        for(key in obj){
            //hasOwnProperty()方法返回一个布尔值,只是对象自身属性中是否具有指定属性(此处是key)
            if(obj.hasOwnProperty(key)){
                //判断ojb子元素是否为对象,如果是,递归复制
                if(obj[key]&&typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    //如果不是,简单复制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}    
let a=[1,2,3,4],
    b=deepClone(a);
a[0]=2;
console.log(a,b);
​
//多级层次的对象或数组
function deepClone(obj) {
            //Array.isArray()用来确定传递的值是否是一个Array
            let objClone = Array.isArray(obj) ? [] : {};
            if (obj && typeof obj === "object") {
                for (key in obj) {
                    console.log(key)
                    //hasOwnProperty()方法返回一个布尔值,只是对象自身属性中是否具有指定属性(此处是key)
                    if (obj.hasOwnProperty(key)) {
                        //判断ojb子元素是否为对象,如果是,递归复制
                        if (obj[key] && typeof obj[key] === "object") {
                            objClone[key] = deepClone(obj[key]);
                        } else {
                            //如果不是,简单复制
                            objClone[key] = obj[key];
                        }
                    }
                }
            }
            return objClone;
        }
        let a = [1, [1,2,3], 3, 4],
            b = deepClone(a);
        a[1][1] = 1;
        console.log(a, b);
        console.log(a.hasOwnProperty(4)) // 对于数组来说是判断是否有这个下标
​
​
        let a = {
            name:'123',
            age:[18,19,20],
        }
        b = deepClone(a)
        a.age[1]=21
        console.log(a,b)
​

 

 

 

 

JSON对象的parse和stringify

function deepClone(obj){
    let _obj = JSON.stringify(obj),
        objClone = JSON.parse(_obj);
    return objClone
}    
let a=[0,1,[2,3],4],
    b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);

注意!!! 缺点: 无法实现对对象中方法的深拷贝,会显示为undefined

 

slice()和concat()方法不传参

slice()测试例子:

var arr1 = ["1","2","3"];
var arr2 = arr1.slice(0);
arr2[1] = "9";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );

 

 

concat()测试例子:

var arr1 = ["1","2","3"];
var arr2 = arr1.concat();
arr2[1] = "9";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );

注意!!!!!!slice和concat这两个方法,仅适用于对不包含引用对象的一维数组的深拷贝 只适用于一层的结构 如果数组里包含数组以及对象等多层次的结构 这两个方法只能对最外层的结构实现

拓展运算符实现深拷贝

let oldObj = { id: 1 }
let newObj = { ...oldObj }

注意!!!! 拓展运算符的深拷贝同样不能运用于多层次的结构!!!

lodash函数库实现深拷贝

项目中常用

let result = _.cloneDeep(test)
​
// 按需引入lodash当中的深拷贝
import cloneDeep from 'lodash/cloneDeep'
​
this.attrInfo=cloneDeep(row)

总结:深拷贝最好使用lodash的cloneDeep方法或者JSON数据转换 其他方法都有坑

项目进度条的使用

1.下载进度条插件

npm i nprogress

2.在axios二次封装的时候引入进度条以及进度条的样式

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

3.在请求拦截器和响应拦截器中使用进度条

请求拦截器中
nprogress.start();  
响应拦截器中
nprogress.done()

常用的数组的一些方法(高级)

array.map()用法

语法:array.map(function(currentValue,index,arr))

currentValue必选,当前元素
index可选,当前元素的索引值
arr可选,该数组

定义:对数组中的每个元素进行处理,得到新的数组;

特点:不改变原有数据的结构和数据

1.map()方法使用return,进行回调;其他方法可不需要。

2.map()方法直接对数组的每个元素进行操作,返回相同数组长度的数组;其他方法可扩展数组的长度。

3.map() 不会对空数组进行检测。

        const arr = [
            {name:'123',age:18},
            {name:'456',age:20},
        ]
        const newArr = arr.map((item)=>{
            return{
                name1:item.name,
                age1:item.age
            }
        })
        console.log(newArr)

 

        const array = [1, 3, 6, 9];
        const newArray = array.map((item)=>{
            return item + 1;
        });
        console.log(newArray);
        console.log(array);

 

 

.filter()

filter方法是对数据中的元素进行过滤,也就是说是不能修改原数组中的数据,只能读取原数组中的数据,callback需要返回布尔值

为true的时候,对应的元素留下来,

为false的时候,对应的元素过滤掉

       let obj = [
            {name:'123',age:18},
            {name:'234',age:19},
            {name:'345',age:20},
            {name:'456',age:21},
        ]
​
        let newObj = obj.filter((item)=>{
            // return item.age>=19
            if(item.age>=19){
                return true
            }
        })
​
        console.log(newObj)

 

 

.some()

some 检测数组中是否有满足条件的 返回结果是一个布尔值 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。 如果没有满足条件的元素,则返回false。

let arr = [{
      name: '小明',
      sex: '男',
      age: 23
    },
    {
      name: '小红',
      sex: '女',
      age: 18
    },
    {
      name: '小兰',
      sex: '女',
      age: 21
    },
    {
      name: '小黑',
      sex: '男',
      age: 23
    }
  ];
 
const someResult = arr.some((value, index, arr) => {
    console.log(value);
    return value.age <= 20;
});
 
console.log(someResult); // true
  • 以上代码给定条件,判断数组中是否存在值的age属性小于等于20时,只要有一个值满足该条件,就返回true

.every()

every方法用于检测数组所有元素是否都符合指定条件 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。 如果所有元素都满足条件,则返回 true。

let arr = [{
      name: '小明',
      sex: '男',
      age: 23
    },
    {
      name: '小红',
      sex: '女',
      age: 18
    },
    {
      name: '小兰',
      sex: '女',
      age: 21
    },
    {
      name: '小黑',
      sex: '男',
      age: 23
    }
  ];
 
const everyResult = arr.every((value, index, arr) => {
    console.log(value);
    return value.age <= 20;
});
 
console.log(everyResult); // false
  • 以上代码给定条件,判断数组中是否所有值的age属性小于等于20时,只要有一个值不满足该条件,就返回false

.find()

给定条件,返回数组中第一个满足该条件的值,之后的值不再进行检测,当没有找到满足该条件的值时,返回undefined

let arr = [
    {
      name: '小明',
      sex: '男',
      age: 23
    },
    {
      name: '小红',
      sex: '女',
      age: 18
    },
    {
      name: '小兰',
      sex: '女',
      age: 21
    },
    {
      name: '小黑',
      sex: '男',
      age: 23
    }
  ];
 
const findResult = arr.find((item) => {
    console.log(item);
    return (item.age === 23);
});
 
console.log(findResult); // {name: "小明", sex: "男", age: 23}
​
//return value.age = 16 则返回的值为undefined 
  • 以上代码给定条件,当数组当前的值的age属性等于23时,返回该值。从数据中我们可以看到,有2项值符合该条件,但是find会找到第一个符合该条件的值,最终返回了第一个符合该条件的所对应的数据 小明,且后面的值不再进行检测

.indexOf()

  • 数组的indexOf方法是查找 查找元素在数组中是否存在 存在则返回第一个找到的下标 找不到则返回-1

    let arr = ['orange', '2016', '2016'];
     
    arr.indexOf('orange');  //0
    arr.indexOf('o');  //-1
     
    arr.indexOf('2016');  //1
    arr.indexOf(2016);  //-1
    ​
    //这里用的是严格等于(===)。大家做类似判断的时候多留意。不要误认为数字会转成字符串,同理字符串也不会转换成数字。
    • 实战

 var arr = [
                {"id":1,"name":"Tom"},
                {"id":2,"name":"Cathy"},
                {"id":3,"name":"Jack"}
            ];
​
        var obj  = arr[0]; 
        // console.log(obj)
        var theObj = {"id":1,"name":"Tom"};
        // console.log(theObj)
​
        console.log(obj==theObj) //false
        console.log(arr.indexOf(theObj));  // -1
        console.log(arr.indexOf(obj));   // 0
​
//上面这题想了很久才想通
// obj的值是arr数组里的第一项  所以他们的内存空间地址指向的是同一个地址
// 而theObj看起来是数组的第一项 数据也都一样 但是它的内存空间地址指向的是它新建的
// 因为 obj和theObj都是 Object类型的 他们之间的比较相等 比较的是指向的地址 他俩地址不同 所以比较为false
// obj指向的地址和arr[0] 是一样的 所以能indexOf能找到
// theObj则是新开辟了一个地址 在arr中找不到这个地址 所以 indexOf返回的是-1
​
  • 字符串也有这个方法 但不可以匹配正则 匹配正则需要用search

reduce()方法详解及高级技巧

详情博客

JS数组reduce()方法详解及高级技巧_行走在边缘的博客-CSDN博客_js中数组的reduce方法

深度选择器

  • scoped属性的作用 ------ 加上scoped的作用是只是对于当前的组件有用(样式) 对于某一个组件,如果style添加上scoped属性,给当前子组件的结构中都添加上一个data-v-xxx自定属性 会发现vue是通过属性选择器,给需要添加的元素添加上样式 例如:h3[data-v-7ba5bd90]

  • 子组件的根标签(拥有父组件当中自定义属性:一样的),如果子组件的根节点和父组件中书写的样式相同,也会添加上相应的样式

  • 注意!!! 如果父组件的样式(scoped) 而且还想影响到子组件的样式 像这种情况我们可以使用深度选择器

    61)深度选择器
    ​
    
    >>>  一般用于原生CSS
    ​
    /deep/ 一般用于less
    ​
     ::v-deep 一般用户scss

echarts

在非vue项目中

  • 引入echarts依赖包

  • 准备一个容器:容器就是显示图标的区域 (可以通过style来设置容器的宽和高)

  • 基于准备好的dom,初始化echarts实例

  • 创建echarts实例

  • 指定图表的配置项和数据

    <body>
        <!-- 准备一个容器:容器就是显示图标的区域 -->
        <div></div>
    ​
        <script>
            // 基于准备好的dom,初始化echarts实例 
            let dom = document.querySelector("div")
            //  创建echarts实例
            let mycharts = echarts.init(dom)
            // 指定图表的配置项和数据
            mycharts.setOption({
                // 图标的标题
                title:{
                    // 主标题的设置
                    text:'数据可视化',
                    // 子标题
                    subtext:'echarts基本使用',
                    // 主标题的颜色
                    textStyle:{ 
                        color:'#bfa'
                    },
                    left: "center",
                },
                // x轴的配置项
                xAxis:{
                    // 数据
                    data:['衣服','直播','游戏','电影']
                },
                // y轴的配置项
                yAxis:{
                    // 设置y轴的线
                    axisLine: {
                        show: true
                    },
                    // 显示y轴的刻度
                    axisTick: {
                        show: true
                    }
                },
                // 系列的设置:绘制什么类型的图表 数据的展示在这里设置
                series:[
                    {
                        // 图表类型的设置
                        type:'bar',
                        // bar是柱状图 line折线图 pie饼图
                        // 图表的数据
                        data:[10,20,30,40],
                        color:'red'
                    }
                ]
    ​
            })
        </script>
    </body>

在Vue项目中使用echarts

  • 安装插件npm i echarts@4.9.0 注意如果不指定安装版本的话是安装最新的版本 版本号是5.多 但是5.多的版本在vue项目中会出现问题

  • 引入import echarts from 'echarts' 对容器打ref 在mounted() 中获取对应图表的dom然后进行操作 以及要对图表初始化echarts实例 echart.init()

    <template>
      <!-- 容器 -->
      <div class="charts" ref="charts"></div>
    </template>
    ​
    <script>
    // 引入echarts
    import echarts from "echarts";
    export default {
      name: "",
      mounted() {
        // 初始化echarts实例
        let lineCharts = echarts.init(this.$refs.charts);
        lineCharts.setOption({
          xAxis: {
            // 隐藏x轴
            show: false,
            type: "category",
          },
          yAxis: {
            // 隐藏y轴
            show: false,
          },
          series: [
            {
              type: "line",
              data: [10, 7, 33, 12, 48, 9,29,10,44,],
              // 曲线平滑
              smooth:true,
              // 拐点的样式的设置
              itemStyle: {
                opacity: 0,
              },
              // 线条的样式
              lineStyle: {
                color: "purple",
              },
              // 填充颜色
              areaStyle: {
                color: {
                  type: "linear",
                  x: 0,
                  y: 0,
                  x2: 0,
                  y2: 1,
                  colorStops: [
                    {
                      offset: 0,
                      color: "purple", // 0% 处的颜色
                    },
                    {
                      offset: 1,
                      color: "#fff", // 100% 处的颜色
                    },
                  ],
                  global: false, // 缺省为 false
                },
              },
            },
          ],
          // 布局的调试
          grid: {
            left: 0,
            top: 0,
            right: 0,
            bottom: 0,
          },
    ​
        });
      },
    };
    </script>
    ​
    <style>
    .charts {
      width: 100%;
      height: 100%;
    }
    </style>
    • 动态展示echarts

    • 例子:切换图标的标题 数据 颜色

      //  准备一个容器
      <div class="charts" ref="charts"></div>
      ​
      //因为mounted 只是在页面加载完毕后挂载 它只能挂载一次 如果需要修改echarts里的数据 就需要将echarts转化为data里的动态展示的数据 让它成为vm里的响应式数据
      //所以需要在data里return
      mycharts: null,
          
      //所以在mounted中可以直接使用this.mycharts
      //在mounted中挂载该容器 该容器处于初始化阶段
       mounted() {
          this.mycharts = echarts.init(this.$refs.charts);
          // 配置数据
          this.mycharts.setOption({
            title: {
              text: "销售额趋势",
            },
            tooltip: {
              trigger: "axis",
              axisPointer: {
                type: "shadow",
              },
            },
            grid: {
              left: "3%",
              right: "4%",
              bottom: "3%",
              containLabel: true,
            },
            xAxis: [
              {
                type: "category",
                data: [
                  "一月",
                  "二月",
                  "三月",
                  "四月",
                  "五月",
                  "六月",
                  "七月",
                  "八月",
                  "九月",
                  "十月",
                  "十一月",
                  "十二月",
                ],
                axisTick: {
                  alignWithLabel: true,
                },
              },
            ],
            yAxis: [
              {
                type: "value",
              },
            ],
            series: [
              {
                name: "Direct",
                type: "bar",
                barWidth: "60%",
                data: [10, 52, 200, 334, 390, 330, 220, 60, 80, 90, 60, 44],
                color: "pink",
              },
            ],
          });
      ​
        },
            
      //修改mycharts的配置项和数据
      //因为要对修改数据 所以要对数据进行监听
      //activeName是v-model获得的 而title是对activeName计算出来的 所以对title进行监听 当然也可以其他的进行监听 这里就只是举一个例子
      //例如:对title进行监听 只要title一发生变化 就重新修改图表的配置数据
      //注意!!!!!!图表配置数据可以再次修改 如果有新的数值 新的数值 没有新的数值 还是用以前的
       this.mycharts.setOption({
              title: {
                text: this.title,
              },
              series: [
              {
                name: "Direct",
                type: "bar",
                barWidth: "60%",
                data: this.list,
                color: this.color
              },
            ],
            });
      },
          
      //在绑定标签的时候会v-model获取到title的内容
      //computed里的数据
       computed: {
          //计算属性之标题
          title() {
            return this.activeName == "sale" ? "销售额" : "访问量";
          },
          list(){
              return this.activeName == "sale" ?[10, 52, 200, 334, 390, 330, 220, 60, 80, 90,         60, 44]:[1320, 5232, 2300, 3334, 3905, 3630, 2202, 6150, 80322, 9120, 640, 444]
          },
          color(){
              return this.activeName == "sale" ? "pink" : "blue";
          }
        },    
           
  • 注意!!!! 使用echarts要多看官方的文档! 配置项手册

路由懒加载

正常的写路由的方法

  • 例子

import Home from '@/views/Home'
const routes=[
    {
        name:'home',
        path:'/home',
        component:Home,
    }
]

优化的方法

  • 路由懒加载(按需加载)

const routes=[
    {
        name:'home',
        path:'/home',
        component:()=>import('@/views/Home')
    }
]

为什么需要懒加载

  • 像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,时间过长,会出啊先长时间的白屏,即使做了loading也是不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时

  • 不需要在最上面引入import

防抖与节流

防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案。 在给DOM绑定事件时,有些事件我们是无法控制触发频率的。 如鼠标移动事件onmousemove, 滚动滚动条事件onscroll,窗口大小改变事件onresize,瞬间的操作都会导致这些事件会被高频触发。 如果事件的回调函数较为复杂,就会导致响应跟不上触发,出现页面卡顿,假死现象。

防抖(debounce)

防抖:就是将一段时间内连续的多次触发转化为一次触发

debounce的特点是当事件快速连续不断触发时,动作只会执行一次。 延迟debounce,是在周期结束时执行,前缘debounce,是在周期开始时执行。但当触发有间断,且间断大于我们设定的时间间隔时,动作就会有多次执行。

function debounce(fn, wait) {
  let timeout = null
  return function() {
    if(timeout){
      clearTimeout(timeout)
    }     
    timeout = setTimeout(fn, wait);
  }
}
function handle() {   
  console.log(Math.random())
}
window.addEventListener('scroll', debounce(handle, 1000))

节流(throttle)

节流:减少一段时间内触发的频率

当高频事件触发时,第一次会立即执行(给scroll事件绑定函数与真正触发事件的间隔一般大于delay,如果你非要在网页加载1000毫秒以内就去滚动网页的话,我也没办法o(╥﹏╥)o),而后再怎么频繁地触发事件,也都是每delay时间才执行一次。而当最后一次事件触发完毕后,事件也不会再被执行了 (最后一次触发事件与倒数第二次触发事件的间隔小于delay,为什么小于呢?因为大于就不叫高频了呀(╹▽╹))。

  • 函数节流主要有两种实现方法:时间戳和定时器。接下来分别用两种方法实现throttle~

//时间戳
function throttle(fn, delay) { 
  var prev = Date.now()         
  return function() {              
    if (Date.now() - prev > delay) {                   
      fn()                
      prev = Date.now()             
    }         
  }       
}       
function handle() {           
  console.log(Math.random())      
}
window.addEventListener('scroll', throttle(handle, 1000))
//定时器
var throttle = function(func, delay) {            
    var timer = null;            
    return function() {                
        var context = this;               
        var args = arguments;                
        if (!timer) {                    
            timer = setTimeout(function() {                        
                func.apply(context, args);                        
                timer = null;                    
            }, delay);                
        }            
    }        
}        
function handle() {            
    console.log(Math.random());        
}        
window.addEventListener('scroll', throttle(handle, 1000));

区别

  • 防抖是将多次执行变为最后一次执行,节流是将多次执行变为每隔一段时间执行

  • debounce和throttling 各有特点,在不同 的场景要根据需求合理的选择策略。如果事件触发是高频但是有停顿时,可以选择debounce; 在事件连续不断高频触发时,只能选择throttling,因为debounce可能会导致动作只被执行一次,界面出现跳跃。

  • 区别:两者区别在于函数节流是固定时间做某一件事,比如每隔1秒发一次请求。而函数防抖是在频繁触发后,只执行一次(两者的前提都是频繁触发)

  • 防抖是在某个时间段内只会执行一次,如果间隔时间内再次出发事件,则清除上次定时器,重新开始定时器,只有最后一次操作会被执行。节流是间隔时间执行,不管触发频率多频繁,都会保证在规定时间内执行一次。

    做尚品汇项目中有用到,在依赖中lodash可以直接用

    import throttle from 'lodash/throttle'
    ​
    ​
    <h3 @mouseenter="changeIndex(index)"></h3>
    ​
     // throttle回调函数别用箭头函数 可能出现上下文this问题
     changeIndex:throttle(function(index){
        // index鼠标移上某一个一级分类的元素的索引值
        this.currentIndex = index;
        // console.log("鼠标进入"+index)
     },50),

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值