来自 Web前端 2020-04-29 17:43 的文章
当前位置: 网上澳门金莎娱乐 > Web前端 > 正文

浅谈VUE防抖与节流的最佳解决方案_vue网上澳门金莎娱乐.js_脚本之家

时间: 2019-09-09阅读: 95标签: propvue

前言

将slot元素作为承载分发内容的出口

有echarts使用经验的同学可能遇到过这样的场景,在window.onresize事件回调里触发echartsBox.resize()方法来达到重绘的目的,resize事件是连续触发的这意味着echarts实例会连续的重绘这是非常耗性能的。还有一个常见的场景在input标签的input事件里请求后端接口,input事件也是连续触发的,假设我输入了“12”就会请求两次接口参数分别是“1”和“12”,比浪费网络资源更要命的是如果参数为“1”的请求返回数据的时间晚于参数为“12”的接口,那么我们得到的数据是和期望不符的。当然基于axios可以做很多封装可以取消上一个请求或者通过拦截做处理,但还是从防抖入手比较简单。

// layout.vuediv  main slot/slot /main/div

防抖和节流到底是啥

当组件渲染的时候,slot/slot将会被替换该组件起始标签和结束标签之间的任何内容

函数防抖

// hone.vuediv  layout pA paragraph for the main content./p pAnd another one./p /layout/div

解释:当持续触发某事件时,一定时间间隔内没有再触发事件时,事件处理函数才会执行一次,如果设定的时间间隔到来之前,又一次触发了事件,就重新开始延时。

react

案例:持续触发scroll事件时,并不立即执行handle函数,当1000毫秒内没有触发scroll事件时,才会延时触发一次handle函数。

每个组件都可以获取到props.children。它包含组件的开始标签和结束标签之间的内容。

function debounce { let timeout = null return function() { if clearTimeout timeout = setTimeout; }}function handle() { console.log}window.addEventListener('scroll', debounce
class Layout extends Component { render() { return ( div className="container" main {this.props.children} /main /div ); }}

addEventListener的第二个参数实际上是debounce函数里return回的方法,let timeout = null 这行代码只在addEventListener的时候执行了一次 触发事件的时候不会执行,那么每次触发scroll事件的时候都会清除上次的延时器同时记录一个新的延时器,当scroll事件停止触发后最后一次记录的延时器不会被清除可以延时执行,这是debounce函数的原理

props是 React 组件的输入。它们是从父组件向下传递给子组件的数据。

函数节流

function Home (params) { return (  Layout pA paragraph for the main content./p pAnd another one./p /Layout / )}

解释:当持续触发事件时,有规律的每隔一个时间间隔执行一次事件处理函数。

vue

案例:持续触发scroll事件时,并不立即执行handle函数,每隔1000毫秒才会执行一次handle函数。

有时我们需要多个插槽。对于这样的情况,slot元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:

function throttle { var prev = Date.now { var now = Date.now() if  { fn } } } function handle() { console.log }window.addEventListener('scroll', throttle
div  header slot name="header"/slot /header main slot/slot /main footer slot name="footer"/slot /footer/div

原理和防抖类似,每次执行fn函数都会更新prev用来记录本次执行的时间,下一次事件触发时判断时间间隔是否到达预先的设定,重复上述操作。

一个不带 name 的slot出口会带有隐含的名字“default”

防抖和节流都可以用于 mousemove、scroll、resize、input等事件,他们的区别在于防抖只会在连续的事件周期结束时执行一次,而节流会在事件周期内按间隔时间有规律的执行多次。

在向具名插槽提供内容的时候,我们可以在一个template元素上使用v-slot指令,并以v-slot的参数的形式提供其名称:

在vue中的实践

layout template v-slot:header h1Here might be a page title/h1 /template pA paragraph for the main content./p pAnd another one./p template v-slot:footer pHere's some contact info/p /template/layout

在vue中实现防抖无非下面这两种方法

现在template元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有v-slot的template中的内容都会被视为默认插槽的内容。

封装utils工具 封装组件

react

封装utils工具

注意:组件可以接受任意 props,包括基本数据类型,React 元素以及函数。

把上面的案例改造一下就能封装一个简单的utils工具

class Layout extends Component { render() { return ( div className="container" header {this.props.header} /header main {this.props.children} /main footer {this.props.footer} /footer /div ); }}
let timeout = nullfunction debounce { if clearTimeout timeout = setTimeout}export default debounce

import debounce from './utils'export default { methods: { debounceInput => { console.log }, 1000) } }}

少数情况下,你可能需要在一个组件中预留出几个“洞”。这种情况下,我们可以不使用children,而是自行约定:将所需内容传入props,并使用相应的prop。

封装组件

function Home (params) { return (  Layout header={ h1Here might be a page title/h1 } footer={ pHere's some contact info/p }  pA paragraph for the main content./p pAnd another one./p /Layout / )}

至于组件的封装我们要用到$listeners、$attrs这两个属性,他俩都是vue2.4新增的内容,官网的介绍比较晦涩,我们来看他俩到底是干啥的:

React 元素本质就是对象(object),所以你可以把它们当作 props,像其他数据一样传递。这种方法类似Vue“槽”(slot)的概念,但在 React 中没有“槽”这一概念的限制,你可以将任何东西作为props进行传递。

网上澳门金莎娱乐,$listeners: 父组件在绑定子组件的时候会在子组件上绑定很多属性,然后在子组件里通过props注册使用,那么没有被props注册的就会放在$listeners里,当然不包括class和style,并且可以通过 v-bind="$attrs" 传入子组件的内部组件。

$listeners: 父组件在子组件上绑定的不含.native修饰器的事件会放在$listeners里,它可以通过 v-on="$listeners" 传入内部组件。

简单来说$listeners、$attrs他俩是做属性和事件的承接,这在对组件做二次封装的时候非常有用。

我们以element-ui的el-input组件为例封装一个带防抖的debounce-input组件

debounce-input.vue

本文由网上澳门金莎娱乐发布于Web前端,转载请注明出处:浅谈VUE防抖与节流的最佳解决方案_vue网上澳门金莎娱乐.js_脚本之家

关键词: