You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Angular与Moment.js构建日期选择器时遇clone函数错误求助

解决Angular日期选择器中的"TypeError: scope.viewDate.clone is not a function"错误

我一眼就揪出问题所在了——你把scope.viewDate直接赋值成了moment构造函数本身,而不是一个moment.js的日期实例!clone()是moment实例专属的方法,直接调用构造函数的话肯定找不到这个方法,这就是报错的核心原因。

错误根源分析

看你这段代码:

scope.viewDate = moment;

这里的moment是一个函数,不是已经创建好的日期对象。要调用clone()、startOf()这些方法,你必须先通过moment()(或带参数的moment('2024-05-20'))创建一个具体的moment实例才行。

修复方案

只需要把scope.viewDate的赋值改成创建moment实例的形式,再给你补充几个优化细节:

angular.module('myApp')
.directive('datepicker', function () {
    return{
        restrict: 'EA',
        scope: true,
        require: 'ngModel',
        link: function (scope, elm, attr, ngModel) {
            // 修复:创建当前时间的moment实例,而非赋值构造函数
            scope.viewDate = moment(); 
            // 可选:给选中日期一个初始值,后续也可通过ngModel同步
            var selectedDate = moment(); 
            
            function generateDays() {
                scope.days = [];
                var startOfSelectedDate = moment.isMoment(selectedDate) ? selectedDate.clone().startOf('day') : null;
                // 现在viewDate是实例,能正常调用clone()了
                var startDate = scope.viewDate.clone().startOf('month').startOf('week').startOf('day');
                var endDate = scope.viewDate.endOf('month').endOf('week').endOf('day');
                
                // 用moment官方推荐的isBefore()代替<,比较更可靠
                while (startDate.isBefore(endDate)){ 
                    scope.days.push({
                        label: startDate.date(),
                        inMonth: startDate.month() === scope.viewDate.month() && startDate.year() === scope.viewDate.year(),
                        date: startDate.valueOf(),
                        // 加上'day'精度,避免时间部分干扰选中判断
                        selected: startDate.isSame(selectedDate, 'day') 
                    });
                    startDate.add(1, 'day');
                }
            }
            generateDays();
        }
    }
});

额外小建议

  1. 用isBefore()代替<比较日期:这是moment官方推荐的比较方式,能避免原生JS比较日期对象时的潜在问题。
  2. 给isSame()加精度参数:比如isSame(selectedDate, 'day'),确保只要日期相同就判定为选中,不受时分秒影响。
  3. 绑定ngModel:如果需要和父组件的日期值同步,记得在link函数里监听ngModel的变化,或者把选中的日期同步回ngModel,这样指令才更实用。

内容的提问来源于stack exchange,提问作者NevrMore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:40:56