一行看懂高阶函数:用 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 是一个漂亮的"回调工厂",能把重复逻辑一次封装、到处复用。
相关推荐
卿·静7 小时前
Node.js对接即梦AI实现“千军万马”视频
前端·javascript·人工智能·后端·node.js
Mintopia7 小时前
🚀 Next.js 全栈 Web Vitals 监测与 Lighthouse 分析
前端·javascript·全栈
Mintopia7 小时前
🤖 AIGC + CMS:内容管理系统智能化的核心技术支撑
前端·javascript·aigc
HelloGitHub7 小时前
这款开源调研系统越来越“懂事”了
前端·开源·github
whysqwhw7 小时前
hippy的主要原理
前端
子兮曰7 小时前
🚀95%的前端开发者都踩过坑:JavaScript循环全解析,从基础到高阶异步迭代
前端·javascript·性能优化
2401_853406887 小时前
Tdesign-React 组件 Card 实现头部固定,内容区单独可滚动
前端·react.js·tdesign
蓝倾9767 小时前
小红书获取用户作品列表API接口操作指南
java·服务器·前端·python·电商开放平台·开放api接口
小桥风满袖7 小时前
极简三分钟ES6 - 数值的扩展
前端·javascript