一行看懂高阶函数:用 handleConfirm 拿下 DatePicker 回调

这篇文章用项目里的真实代码,讲清"高阶函数"的实战用法。读完你将彻底明白:

(1) 为什么要"函数返回函数",

(2) optionsvalues 到底是什么,

(3) 如何优雅复用到多个日期选择器。

备注 :讲解使用NutUI React 小程序端 DatePicker 组件

实际代码

  • 高阶函数(返回真正给组件用的回调):
js 复制代码
const handleConfirm = (setDesc, setValue) => (options, values) => {
  // 添加空值检查
  if (!options || !values) {
    console.warn('DatePicker onConfirm: options or values is null/undefined');
    return;
  }

  try {
    const dateStr = options.map(option => option.label).join('');
    setDesc(dateStr);

    if (setValue) {
      const valueStr = values.join('-');
      setValue(valueStr);
    }
  } catch (error) {
    console.error('DatePicker handleConfirm error:', error);
  }
};
  • 绑定到 DatePicker(这里是"配置后"再交给组件):
jsx 复制代码
<DatePicker
  title='注册日期'
  visible={showRegisterDate}
  pickerProps={{
    popupProps: { zIndex: 1220 }
  }}
  defaultValue={new Date()}
  showChinese
  onClose={() => setShowRegisterDate(false)}
  onConfirm={handleConfirm(setRegisterDateDesc, value => {
    setFormData(prev => ({
      ...prev,
      registerDate: value
    }));
  })}
/>

这行"看不懂"的语法,其实很简单

把这一行拆开理解:

javascript 复制代码
const handleConfirm = (setDesc, setValue) => (options, values) => { ... }

等价于:

javascript 复制代码
function handleConfirm(setDesc, setValue) {
  return function onConfirm(options, values) {
    // 真正处理 DatePicker 回传的数据
  };
}
  • 第一次调用(配置阶段):handleConfirm(setDesc, setValue)
    • 告诉它:选完后"如何更新展示文案"(setDesc)和"如何写入表单值"(setValue
  • 第二次调用(执行阶段):(options, values) => { ... }
    • 由 DatePicker 在"用户点击确定"时,传入它的回调数据

一句话心智模型:handleConfirm(A, B)(X, Y)

  • A/B:你提前注入的"处理策略"(如何展示、如何存储)
  • X/Y:组件在 onConfirm 时给你的"数据"(选中的 options/values)

(options, values) 到底是什么?

NutUI DatePickeronConfirm 时会给你两份数据:

  • options:每一列被选中的对象,适合用于"展示",例如:

    js 复制代码
    [{ label: '2024年', value: '2024' }, { label: '01月', value: '01' }, { label: '15日', value: '15' }]

    代码用它生成中文描述:

    js 复制代码
    options.map(o => o.label).join('')  // → "2024年01月15日"
  • values:每一列的原始值,适合用于"存储",例如:

    js 复制代码
    ['2024', '01', '15']

    代码用它生成提交值:

    js 复制代码
    values.join('-')  // → "2024-01-15"
  • 为什么要两份?

    • options.label 用于 UI 显示(带"年/月/日")
    • values 用于后端或表单(标准化"YYYY-MM-DD")

为什么要用高阶函数(而不是直接写 onConfirm)

  • 复用:同样的处理流程,只需替换 setDescsetValue,就能用于"注册日期""有效期至"等多个 DatePicker。
  • 解耦:逻辑(如何把 options/values 转化)与状态绑定(写到 registerDate 还是 validDate)分离,改字段不改逻辑。
  • 配置化:把"差异点"放到入参,整体更像"回调工厂"。

若不用高阶函数,等价"直写版"是这样(可读但不可复用):

javascript 复制代码
<DatePicker
  onConfirm={(options, values) => {
    if (!options || !values) return;
    const text = options.map(o => o.label).join('');
    setRegisterDateDesc(text);
    setFormData(prev => ({ ...prev, registerDate: values.join('-') }));
  }}
/>

进阶:把格式化也"配置化"(更通用的工厂)

javascript 复制代码
const createConfirm =
  ({ setDesc, setValue, toText = os => os.map(o => o.label).join(''),
     toValue = vs => vs.join('-') }) =>
  (options, values) => {
    if (!options || !values) return;
    setDesc(toText(options));
    setValue?.(toValue(values));
  };

// 用法:注册日期
onConfirm={createConfirm({
  setDesc: setRegisterDateDesc,
  setValue: v => setFormData(p => ({ ...p, registerDate: v }))
})}

// 用法:有效期至(可用同一套)
onConfirm={createConfirm({
  setDesc: setValidDateDesc,
  setValue: v => setFormData(p => ({ ...p, validDate: v }))
})}

易错点与建议

  • 空值检查要保留:个别情况下(取消或异常)可能出现 options/values 为空。
  • 格式化规范一致:values.join('-') 保证"YYYY-MM-DD";如果涉及月/日补零,在数据源或格式化器中处理。
  • 如果 setValue 内部引用了其他状态,注意闭包与依赖(useCallbackuseRef)。

结语(最短记忆法)

  • 高阶函数 = 先配置、后执行。
  • 先告诉它"选完后怎么展示/怎么落库",再让 DatePicker 把"选了什么"交给它。
  • options 用于展示(带"年/月/日"),values 用于存储("YYYY-MM-DD")。
  • handleConfirm 是一个漂亮的"回调工厂",能把重复逻辑一次封装、到处复用。
相关推荐
wearegogog1237 小时前
基于 MATLAB 的卡尔曼滤波器实现,用于消除噪声并估算信号
前端·算法·matlab
Drawing stars7 小时前
JAVA后端 前端 大模型应用 学习路线
java·前端·学习
品克缤7 小时前
Element UI MessageBox 增加第三个按钮(DOM Hack 方案)
前端·javascript·vue.js
小二·7 小时前
Python Web 开发进阶实战:性能压测与调优 —— Locust + Prometheus + Grafana 构建高并发可观测系统
前端·python·prometheus
小沐°7 小时前
vue-设置不同环境的打包和运行
前端·javascript·vue.js
qq_419854058 小时前
CSS动效
前端·javascript·css
烛阴8 小时前
3D字体TextGeometry
前端·webgl·three.js
桜吹雪8 小时前
markstream-vue实战踩坑笔记
前端
C_心欲无痕8 小时前
nginx - 实现域名跳转的几种方式
运维·前端·nginx
花哥码天下9 小时前
恢复网站console.log的脚本
前端·javascript·vue.js