如何移除多维数组中的双引号以适配moment.js时间选择器?
问题背景与尝试
- 之前找到过类似问题,但给出的解决方案会将字符串转换为数字,不符合需求。
- 需要移除双引号是为了符合moment.js语法规范,以此配置时间选择器的禁用时段。
- 尝试过从后端PHP代码移除双引号,未生效,接受JavaScript或PHP任一解决方案。
- 试过以下JavaScript代码,但结果仍保留双引号:
const timeIntervalsData = [ [ "moment({ hour:6, minute:45 }), moment({ hour:7, minute:45 })", ], [ "moment({ hour:10, minute:30 }), moment({ hour:11, minute:30 })", ], ] let string = JSON.stringify(timeIntervalsData) string.replace (/"/g,'')
实际业务代码
前端将多维数组用于时间选择器的配置:
const timeIntervalsData = [] // `timeIntervalsData` 存储后端接口返回的响应数据 $.ajax({ type: 'POST', url: 'call-url-of-backend', data: {_token: CSRF_TOKEN}, dataType: 'JSON', success: function (data) { if (data.status == true) { timeIntervalsData = data.time } },error: function(xhr, status, error) { var r = jQuery.parseJSON(xhr.responseText) console.log(r.message) } }) let options = { format: 'hh:mm A', // 此处加载多维数组 disabledTimeIntervals: timeIntervalsData, // 官方示例语法 disabledTimeIntervals: [ [moment({ hour:6, minute:45 }), moment({ hour:7, minute:45 })], [moment({ hour:10, minute:30 }), moment({ hour:11, minute:30 })], ], } $('.datetimepicker').datetimepicker(options)
后端PHP代码
当前后端生成数据的代码:
$user = User::find(1); $schedules = Schedule::select('start_time', 'end_time') ->whereBelongsTo($user) ->where('weekday', 1) ->get() ->toArray(); $collection = collect($schedules)->map(function ($time) { return [date("g:i", strtotime($time['start_time'])), date("g:i", strtotime($time['end_time']))]; }); $data = $collection->values()->all(); $carrier = []; foreach ($data as $key => $a) { $detail1 = preg_split('/:/i', $a[0]); $detail2 = preg_split('/:/i', $a[1]); // 尝试用str_replace移除双引号 array_push($carrier, array(str_replace('"', "", 'moment({ hour:'.$detail1[0].', minute:'.$detail1[1].' }), moment({ hour:'.$detail2[0].', minute:'.$detail2[1].' })'))); } return response()->json([ 'status' => true, 'time' => $carrier, ], 200); // `$carrier` 输出结果 [ [ "moment({ hour:6, minute:45 }), moment({ hour:7, minute:45 })", ], [ "moment({ hour:10, minute:30 }), moment({ hour:11, minute:30 })", ], ]
测试情况
编辑:测试代码结果
尝试以下代码后,控制台输出不符合预期:
const timeIntervalsData = JSON.stringify({ moments: [ { hour: 6, minute: 45 }, { hour: 7, minute: 45 }, { hour: 10, minute: 30 }, { hour: 11, minute: 30 } ] }); let options = { format: 'hh:mm A', disabledTimeIntervals: [ JSON.parse(timeIntervalsData).moments.forEach( interval => moment(interval) ) ], } console.log(options)
(控制台输出中disabledTimeIntervals为[undefined])
编辑2:测试更新后的代码结果
调整代码后,disabledTimeIntervals将所有moment实例合并为单个数组,仅前两个时段生效:
const timeIntervalsData = JSON.stringify( { moments: [ { hour: 6, minute: 45 }, { hour: 7, minute: 45 }, { hour: 10, minute: 30 }, { hour: 11, minute: 30 } ] }); JSON.parse(timeIntervalsData).moments.forEach( interval => console.log(moment(interval)) ); let options = { format: 'hh:mm A', disabledTimeIntervals: [ JSON.parse(timeIntervalsData).moments.map( interval => moment(interval) ) ], } console.log(options);
输出结果:
disabledTimeIntervals: [ [M, M, M, M] // 合并为单个数组,仅前两个时段生效 ],
而正确格式应为:
disabledTimeIntervals: [ [moment({ hour:6, minute:45 }), moment({ hour:7, minute:45 })], [moment({ hour:10, minute:30 }), moment({ hour:11, minute:30 })] ],
解决方案
方案1:后端PHP调整数据格式(推荐)
不要将moment代码字符串化,直接返回小时和分钟的结构化数据,由前端生成moment实例:
$user = User::find(1); $schedules = Schedule::select('start_time', 'end_time') ->whereBelongsTo($user) ->where('weekday', 1) ->get() ->toArray(); // 生成包含时段的结构化数组 $carrier = collect($schedules)->map(function ($time) { $start = date("H:i", strtotime($time['start_time'])); $end = date("H:i", strtotime($time['end_time'])); list($startHour, $startMin) = explode(':', $start); list($endHour, $endMin) = explode(':', $end); return [ ['hour' => (int)$startHour, 'minute' => (int)$startMin], ['hour' => (int)$endHour, 'minute' => (int)$endMin] ]; })->values()->all(); return response()->json([ 'status' => true, 'time' => $carrier, ], 200);
后端返回的数据格式为:
{ "status": true, "time": [ [{"hour":6,"minute":45},{"hour":7,"minute":45}], [{"hour":10,"minute":30},{"hour":11,"minute":30}] ] }
方案2:前端JS处理数据
拿到后端返回的数据后,解析生成符合要求的moment数组:
$.ajax({ type: 'POST', url: 'call-url-of-backend', data: {_token: CSRF_TOKEN}, dataType: 'JSON', success: function (data) { if (data.status == true) { // 处理后端返回的字符串数据,转成moment数组 const disabledIntervals = data.time.map(intervalStrArr => { const momentStrs = intervalStrArr[0].split(', '); return momentStrs.map(momentStr => { const hourMatch = momentStr.match(/hour:(\d+)/); const minuteMatch = momentStr.match(/minute:(\d+)/); return moment({ hour: parseInt(hourMatch[1]), minute: parseInt(minuteMatch[1]) }); }); }); // 初始化时间选择器 $('.datetimepicker').datetimepicker({ format: 'hh:mm A', disabledTimeIntervals: disabledIntervals }); } },error: function(xhr, status, error) { var r = jQuery.parseJSON(xhr.responseText) console.log(r.message) } })
此方式无需修改后端,直接在前端解析字符串生成moment实例,最终得到[[M, M], [M, M]]的正确格式。
内容的提问来源于stack exchange,提问作者Lucky Person
相关产品推荐
相关产品推荐

