这几天学习Vue的官网,看到 customRef 提供了一个例子,研究半天发现这是一个防抖函数,觉得挺好,于是把这个例子扩展了一下,可以用于表单子控件和查询子控件。

需求

  • v-model

    基于 element-plus 封装表单控件,同时也要封装一下表单子控件,还有查询控件。

    由于 el-input 这类的组件,把 value 封装成了 v-model,所以无法把组件的属性直接设置给内部的 el-input。

    必须在内部设置一个变量,然后做“属性” <==> “变量” 的转换。

    这样就比较麻烦,需要一个既优雅又实用的方式来解决。

  • 查询的防抖

    查询的时候,理想情况是用户输入一个完整的查询条件,然后自动去后端申请查询,但是vue默认的响应形式是,输入一个字符就会响应,如果立即去后端查询的话,会造成浪费的情况,另外用户体验也不好。

    如果用change事件,那么用户输入完毕,还得在其他的地方点一下,比较麻烦。

    所以需要一个简单的方式,比如防抖功能来优化用户体验。

设计

用 customRef (自定义的ref)设计get 和 set。

  • get:获取组件属性,返回给内部组件,比如 el-input。
  • set:用smit提交给父组件。
  • settimeout:实现防抖。

实施验证

想法挺好的,演示为0的时候也是好用的,但是把延迟设为200的时候确出现问题,首先是 el-input 的字符显示也一起延迟了,另外只会显示最后一个字符,中间的字符都被吃掉了。

这是怎么回事?用html5的 input 试验的时候是没有问题的呀。

办法重臂困难多,几经修改之后终于好用了。

/**
* 自定义的ref,实现属性和内部变量的数据转换
* @param { reactive } props 组件的属性
* @param { object } context 组件的上下文
* @param { number } delay 延迟刷新的时间,单位:毫秒,默认:0
* @param { string } name 要对应的属性名称,默认:modelValue
* @returns 自定义的ref
*/
export const debounceRef = (props, context, delay = 0, name = 'modelValue') => {
let value = props[name]
// 计时器
let timeout
// 是否输入状态。输入时取 value;输入完毕取 modelValue 属性
let isInput = false
return customRef((track, trigger) => {
return {
get () {
track()
if (isInput) {
return value
} else {
return props[name]
}
},
set (newValue) {
isInput = true
value = newValue // 绑定值
trigger() // 组件内部刷新模板
clearTimeout(timeout) // 清掉上一次的计时
timeout = setTimeout(() => {
// 修改 modelValue 属性
context.emit(`update:${name}`, newValue) // 提交给父组件
// 用于区分是哪个组件触发的事件。
context.emit('my-change', newValue, props.controlId, props.colName)
isInput = false
}, delay)
}
}
})
}
  • 参数
  1. props: 组件的属性,便于属性值变更的时候可以获得最新值。
  2. context 组件的上下文,方便向父组件提交。
  3. name:v-model的名称,默认是 modelValue。
  4. delay:延迟时间,默认是0。
  • value:内部变量,用于初始值和用户输入的时候的绑定。

  • let timeout:定时器,便于清掉之前的定时。

  • let isInput = false

    用户的输入状态,如果用户处于敲键盘的状态,那么获取内部的 value 绑定到 el-inupt;

    如果用户没有敲键盘,那么获取父组件的属性值,绑定到 el-inupt。

为啥要这么设置呢?没办法,如果直接获取组件的属性值的话,那么会出现延迟的情况,如果获取内部 value 的话,父组件的属性变化的时候,内部 el-input 不会有变化,所以只好这么折腾一下。

后面的就是常规操作了,get 里面根据状态获取属性和 value,set 里面向父组件提交。

使用

setup (props, context) {
const value = debounceRef(props, context)
return {
value
}
}
 <el-input v-model="value"></el-input>

基本上和普通的 ref 很像,只是需要设置组件的属性和上下文。

  • 如果名称不是默认的 modelValue 的话,需要传递名称;
  • 如果需要延迟响应的话,需要设置延迟时间,默认是不延迟的。

缺点:

  • 灵活性欠佳,只是针对一个特定需求封装的,没有考虑更多的情况。其他情况在写个函数好了,函数要符合原子性,不要承担太多的职责。

  • 还是要传递属性和上下文,这个也没啥办法省略。

  • CheckBox又不支持延迟了。记得之前好用的。。。

优点:

  • 自我感觉还是比较优雅的。

最新文章

  1. mvc webapi 返回字符串自动加双引号
  2. filestream read方法 循环读取固定文件
  3. 记录s标签范例
  4. html5 实现video标签的自定义播放进度条
  5. 在spring环境下集成ActiveMQ
  6. yum安装指定版本软件包__20160308
  7. ID3算法 决策树的生成(2)
  8. 使用EF6.0出现:CS0029 无法将类型“System.Data.Entity.Core.Objects.ObjectContext”隐式转换为“System.Data.Objects.ObjectContext”错误
  9. WisDom.Net 框架设计(二) 服务总线
  10. 视图中的Layout使用(转)
  11. Qt中如何 编写插件 加载插件 卸载插件
  12. SpringMvc多视图配置(jsp、velocity、freemarker) 在src目录views.properties配置
  13. Javascript中的noscript
  14. Netflix Recommendations
  15. 将你的前端应用打包成docker镜像并部署到服务器?仅需一个脚本搞定
  16. ubuntu google chrome 忽略证书错误 -- 解决自签名证书不支持的问题
  17. scrapy之日志等级
  18. 在tomcat8.0.x和tomcat9.0.x之间么突然冒出个tomcat 8.5
  19. maven使用中遇到的问题
  20. ZH奶酪:在博客中添加Latex公式

热门文章

  1. 手把手教你使用 js 实现一个 Canvas 编辑器
  2. web hack &amp; web security
  3. vue $emit bug
  4. NGK算力生态建设者狂欢!SPC之后又有VAST!
  5. Jupyter notebook操作技巧
  6. K8S部署Redis Cluster集群(三主三从模式) - 部署笔记
  7. 一条sql语句的执行过程
  8. oracle 中的左外连接、右外连接、全连接
  9. 微信小程序(二十)-UI组件(Vant Weapp)-01按装配置
  10. 必知必会之 Java