快来看!我用原生js实现表单的双向绑定和防抖节流

386 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情

最近刷到一道js题。要求用原生js实现类似v-model的效果,并且再添加上防抖节流,乍一听需求挺多,其实写下来也就几行代码,这个主要考察还是我们的js基础

直接上代码,首先实现input输入框的双向绑定

<body>
<input
  type="text"
  id="input"
  oninput="watch()"
  onporpertychange="watch()"
/>
<hr />
<h1 id="show"></h1>
</body>

<script>
let input = document.getElementById('input')
let show = document.getElementById('show')
const watch = () => {
  show.innerText = input.value
  console.log(show.innerText)
}
// onload 当页面载入完毕后执行的事件:
window.onload = function () {
  watch()
}
</script>

这段代码很简单,主要就是通过input事件在我们输入内容时,触发已经定义好的函数,拿到输入框里的值赋值给p标签

这里有两个注意点

  • 第一个就是把函数调用写在window.onload里面,onload是当页面载入完毕后执行的事件,避免页面没加载完毕执行函数报错
  • onporpertychange事件只要当前对象属性发生改变,就会触发事件,但它是IE专属的,写了input和onporpertychange这两个事件,可以避免出现兼容性问题

image.png

这个时候我们看页面就已经完成一个input输入框的双向绑定

实现防抖效果

  • 声明一个变量存储定时器ID(在react中一般要用useRef保存这个ID,不然这个ID会随着组件更新而更新)

  • 每次触发这个函数先清除上一次的定时器ID

  • 开启一个定时器,定时器的内部写需要防抖的代码

    let timeId = null
    
    const watch = () => {
       clearTimeout(timeId)
       timeId = setTimeout(() => {
         show.innerText = input.value
         console.log(input.value)
       }, 1000)
    }
    

只需要对刚才的watch函数稍微改造就能完成

image.png

实现节流

let isEdit = false

const watch = () => {
  // isEdit===true的时候直接return
  if (isEdit) return
  isEdit = true
  show.innerText = input.value
  isEdit = false
}

节流用在这个场景没有防抖合适,节流适合用在鼠标的移动事件和页面滚动条、窗口缩放, 这几个场景特别适合用节流来做

节流顾名思义节流阀,声明一个变量为false,当我调用这个函数先判断,这个变量等于false才能往下走,不等于直接return,然后在我要节流的代码前将这个变量的值设置成true,这样的话只要我的代码没走完,触发函数变量一直为true,就会一直return掉,直到我的代码走完在设置成false,再允许下一次正常的进入函数

这种是使用了开关思想, 也可以通过定时器,记录第一次触发的函数的时间,后面每次触发都用当前的时间减去上一次记录的那个时间,相差大于多少秒才能够走代码,然后再把这一次的时间赋值为上一次时间,为下一次触发作比较,这两种方法都是可以的,开关思想可能要更简洁一些