原生JS实现一个日期选择器(DatePicker)组件

这是通过原生HTML/CSS/JavaScript完成一个日期选择器(datepicker)组件,一个纯手搓的组件的开发。主要包括datepicker静态结构的编写、日历数据的计划获取、组件的渲染以及组件事件的处理。

根据调用时的时间格式参数,可以控制短日期格式或长日期格式。

实现效果(短日期格式) 实现效果(长日期格式)

完整代码包含4个文件:

  1. JavaScript实现功能代码全部在 datepicker-v1.20250113.js 文件
  2. CSS实现样式渲染代码全部在 datepicker-v1.20250113.css 文件
  3. HTML实现一个调用demo 在 datepicker.html 文件
  4. 另外就是 输入框的小图标 calendar-icon.png

datepicker-v1.20250113.js 完整代码如下:
点击查看代码

/*!
 * datepicker Library v1.0
 *
 * Copyright 2025, xiongzaiqiren
 * Date: Mon Jan 13 2025 11:27:27 GMT+0800 (中国标准时间)
 */
; (function () {
    var datepicker = {
        paramsDate: function (inputElement, targetFormat) {
            this.inputElement = inputElement; // 当前输入框
            this.targetFormat = targetFormat || 'yyyy/MM/dd HH:mm:ss'; // 目标日期时间格式
            this.monthData = {}; // 绘制日历组件的数据源
            this.sureTime = { year: 0, month: 0, date: 0, hour: -1, minute: -1, second: -1 }; // 确定的选中的日期时间,或者初始化到某个时刻,或者是初始化到当前时刻。这里时分秒必需初始化小于0,后米面才好判断是否要构建时分秒控件
        },
        getMonthDate: function (year, month) {
            var ret = [];
            if (!year || !month) {
                var today = new Date();
                year = today.getFullYear();
                month = today.getMonth() + 1;
            }
            var firstDay = new Date(year, month - 1, 1);//获取当月第一天
            var firstDayWeekDay = firstDay.getDay();//获取星期几,才好判断排在第几列
            if (0 === firstDayWeekDay) {//周日
                firstDayWeekDay = 7;
            }

            year = firstDay.getFullYear();
            month = firstDay.getMonth() + 1;

            var lastDayOfLastMonth = new Date(year, month - 1, 0);//获取最后一天
            var lastDateOfLastMonth = lastDayOfLastMonth.getDate();

            var preMonthDayCount = firstDayWeekDay - 1;
            var lastDay = new Date(year, month, 0);
            var lastDate = lastDay.getDate();

            for (var i = 0; i < 7 * 6; i++) {
                var date = i + 1 - preMonthDayCount;
                var showDate = date;
                var thisMonth = month;
                //上一月
                if (0 >= date) {
                    thisMonth = month - 1;
                    showDate = lastDateOfLastMonth + date;
                } else if (date > lastDate) {
                    //下一月
                    thisMonth = month + 1;
                    showDate = showDate - lastDate;
                }
                if (0 === thisMonth) {
                    thisMonth = 12;
                }
                if (13 === thisMonth) {
                    thisMonth = 1;
                }
                ret.push({
                    month: thisMonth,
                    date: date,
                    showDate: showDate
                })

            }
            return {
                year: year,
                month: month,
                days: ret
            };
        }
    };


     window.datepicker = datepicker;//该函数唯一暴露的对象
    
})();

/***** main.js *****/
(function () {
     var datepicker = window.datepicker;

    var $datepicker_wrapper;
    //渲染函数,由于没有使用第三方插件或库,所以使用的是模板拼接的方法
    datepicker.buildUi = function (monthData, sureTime) {
        // monthData = datepicker.getMonthDate(year, month); // year, month, monthData 是面板需要绘画的日期时间集合
        var html = '<div class="ui-datepicker-header">' +
            '<a href="javascript:void(0);" class="ui-datepicker-btn ui-datepicker-prevYear-btn">&#8810;</a>' +
            '<a href="javascript:void(0);" class="ui-datepicker-btn ui-datepicker-prev-btn">&lt;</a>' +
            '<a href="javascript:void(0);" class="ui-datepicker-btn ui-datepicker-nextYear-btn">&#8811;</a>' +
            '<a href="javascript:void(0);" class="ui-datepicker-btn ui-datepicker-next-btn">&gt;</a>' +
            '<span class="datepicker-curr-month">' + monthData.year + '-' + monthData.month + '</span>' +
            '</div>' +
            '<div class="ui-datepicker-body">' +
            '<table>' +
            '<thead>' +
            '<tr>' +
            '<th>\u4e00</th>' +
            '<th>\u4e8c</th>' +
            '<th>\u4e09</th>' +
            '<th>\u56db</th>' +
            '<th>\u4e94</th>' +
            '<th>\u516d</th>' +
            '<th>\u65e5</th>' +
            '</tr>' +
            '</thead>' +
            '<tbody>';

        function coreMonth(coreMonth, month) {
            return coreMonth == month;
        }
        function isToday(year, month, date) {
            const _today = new Date().getFullYear() + '/' + (new Date().getMonth() + 1) + '/' + new Date().getDate();
            return (year + '/' + month + '/' + date) == _today;
        }
        function sureTimeIsToday(year, month, date, sureTime) {
            return (!!sureTime && (sureTime.year === year && sureTime.month === month && sureTime.date === date));
        }


        for (var i = 0; i < monthData.days.length; i++) {
            var date = monthData.days[i];
            if (i % 7 === 0) {
                html += '<tr>';
            }

            html += '<td class="' +
                ((i % 7 === 5 || i % 7 === 6) ? 'weekend' : '') +
                (coreMonth(monthData.month, date.month) ? '' : ' notmonth') +
                (isToday(monthData.year, date.month, date.showDate) ? ' today' : '') +
                (sureTimeIsToday(monthData.year, date.month, date.showDate, sureTime) ? ' active' : '') +

                '" data-date="' + date.date + '">' + date.showDate + '</td>';
            if (i % 7 === 6) {
                html += '</tr>';
            }
        }

        html += '</tbody>' +
            '</table>' +
            '</div>';

        function buildTimeOptions(max) {
            let _s = '';
            for (i = 0; i <= max; i++) {
                let _n = i < 10 ? ('0' + i) : i;
                _s += '<option value="' + _n + '">' + _n + '</option>';
            }
            return _s;
        }

        html += '<div class="ui-datepicker-footer">' +
            '<a href="javascript:void(0);" class="ui-datepicker-btn ui-datepicker-today-btn">\u4eca\u5929</a>';
        if (!!sureTime && (0 <= sureTime.hour && 0 <= sureTime.minute && 0 <= sureTime.second)) {
            html += '<select class="hour">' + buildTimeOptions(23) + '</select>' +
                '<select class="minute">' + buildTimeOptions(59) + '</select>' +
                '<select class="second">' + buildTimeOptions(59) + '</select>';
        }
        html += '<a href="javascript:void(0);" class="ui-datepicker-btn ui-datepicker-ok-btn">\u786e\u5b9a</a>' +
            '</div>';
        return html;
    };
    //日历渲染函数
    datepicker.render = function (paramsDate, direction) {
        var year, month;
        if (!!paramsDate.monthData && 0 < paramsDate.monthData.year) {
            year = paramsDate.monthData.year;
            month = paramsDate.monthData.month;
        }
        else if (!!paramsDate.sureTime && (0 < paramsDate.sureTime.year && 0 < paramsDate.sureTime.month)) {
            // 根据输入框的值初始化确定日期
            year = paramsDate.sureTime.year;
            month = paramsDate.sureTime.month;
        }

        if ('prev' === direction) {
            month--;
            if (month < 1) {
                year--;
                month = 12;
            }
        }
        else if ('next' === direction) {
            month++;
        }
        else if ('prevYear' === direction) {
            year--;
        }
        else if ('nextYear' === direction) {
            year++;
        }
        else if ('today' === direction) {
            let t = new Date();
            year = t.getFullYear();
            month = t.getMonth() + 1;

            paramsDate.sureTime.year = year;
            paramsDate.sureTime.month = month;
            paramsDate.sureTime.date = t.getDate();
            if (0 <= paramsDate.sureTime.hour && 0 <= paramsDate.sureTime.minute && 0 <= paramsDate.sureTime.second) {
                paramsDate.sureTime.hour = t.getHours();
                paramsDate.sureTime.minute = t.getMinutes();
                paramsDate.sureTime.second = t.getSeconds();
            }
        }

        paramsDate.monthData = datepicker.getMonthDate(year, month); // year, month, monthData 是面板需要绘画的日期时间集合
        var html = datepicker.buildUi(paramsDate.monthData, paramsDate.sureTime);

        $datepicker_wrapper = document.querySelector('.ui-datepicker-wrapper');

        if (!$datepicker_wrapper) {
            $datepicker_wrapper = document.createElement('div');
            $datepicker_wrapper.className = 'ui-datepicker-wrapper';
        }

        $datepicker_wrapper.innerHTML = html;

        document.body.appendChild($datepicker_wrapper);
        // 绘画完了,初始化选中时间
        if (!!paramsDate.sureTime && (0 <= paramsDate.sureTime.hour && 0 <= paramsDate.sureTime.minute && 0 <= paramsDate.sureTime.second)) {
            setSelectedByValue('.ui-datepicker-wrapper select.hour', paramsDate.sureTime.hour);
            setSelectedByValue('.ui-datepicker-wrapper select.minute', paramsDate.sureTime.minute);
            setSelectedByValue('.ui-datepicker-wrapper select.second', paramsDate.sureTime.second);
        }

    };
    //初始换函数
    datepicker.main = function (paramsDate) {
        var $targetFormat = paramsDate.targetFormat;
        var $input = paramsDate.inputElement;
        // 根据输入框的值初始化控件的值
        let initInputdate = new Date($input.value);
        if (!!initInputdate && initInputdate.getFullYear() > 0) {
            paramsDate.sureTime.year = initInputdate.getFullYear();
            paramsDate.sureTime.month = initInputdate.getMonth() + 1;
            paramsDate.sureTime.date = initInputdate.getDate();
            if (/([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])/gi.test($input.value)) {
                // 校验时分秒:格式:HH:mm:ss
                paramsDate.sureTime.hour = initInputdate.getHours();
                paramsDate.sureTime.minute = initInputdate.getMinutes();
                paramsDate.sureTime.second = initInputdate.getSeconds();
            }
        }

        if (0 > paramsDate.sureTime.hour || 0 > paramsDate.sureTime.minute || 0 > paramsDate.sureTime.second) {
            if (!!$targetFormat && ($targetFormat.toLocaleLowerCase().includes('hh:mm:ss'))) {
                // 将展示时分秒控件
                paramsDate.sureTime.hour = 0;
                paramsDate.sureTime.minute = 0;
                paramsDate.sureTime.second = 0;
            }
            else {
                // 不展示时分秒控件
                paramsDate.sureTime.hour = -1;
                paramsDate.sureTime.minute = -1;
                paramsDate.sureTime.second = -1;
            }
        }

        // 在初始化控件之前,清理掉以前的日期时间控件
        const divsToRemove = document.querySelectorAll('.ui-datepicker-wrapper');
        divsToRemove.forEach(div => div.remove());

        datepicker.render(paramsDate);

        var isOpen = false;
        if (isOpen) {
            $datepicker_wrapper.classList.remove('ui-datepicker-wrapper-show');
            isOpen = false;
        } else {
            $datepicker_wrapper.classList.add('ui-datepicker-wrapper-show');

            var left = $input.offsetLeft;
            var top = $input.offsetTop;
            var height = $input.offsetHeight;

            $datepicker_wrapper.style.top = top + height + 2 + 'px';
            $datepicker_wrapper.style.left = left + 'px';

            isOpen = true;
        }


        //给按钮添加点击事件
        datepicker.addEventListener($datepicker_wrapper, 'click', function (e) {
            var $target = e.target;
            //上一月,下一月
            if ($target.classList.contains('ui-datepicker-prev-btn')) {
                datepicker.render(paramsDate, 'prev');
            } else if ($target.classList.contains('ui-datepicker-next-btn')) {
                datepicker.render(paramsDate, 'next');
            }
            //上一年,下一年
            else if ($target.classList.contains('ui-datepicker-prevYear-btn')) {
                datepicker.render(paramsDate, 'prevYear');
            } else if ($target.classList.contains('ui-datepicker-nextYear-btn')) {
                datepicker.render(paramsDate, 'nextYear');
            }
            //今天
            else if ($target.classList.contains('ui-datepicker-today-btn')) {
                datepicker.render(paramsDate, 'today');
            }

            if ($target.tagName.toLocaleLowerCase() === 'td') {
                // 移除其他日期选中状态
                document.querySelectorAll('.ui-datepicker-wrapper td').forEach(function (td) {
                    if (td.classList.contains('active')) {
                        td.classList.remove('active');
                    }
                });

                // 通过classname 设置选中日期
                $target.classList.add('active');
            }

            if (!$target.classList.contains('ui-datepicker-ok-btn')) {
                return true;
            }
            // 以下是点击"确定"之后的代码 
            var selected_date;
            var selectedTd = document.querySelector('.ui-datepicker-wrapper td.active');
            if (!!selectedTd) {
                selected_date = selectedTd.dataset.date || 0;
            }

            if (3 === document.querySelectorAll('.ui-datepicker-wrapper select').length) {
                var selectElementHour = document.querySelector('.ui-datepicker-wrapper select.hour');
                paramsDate.sureTime.hour = selectElementHour.options[selectElementHour.selectedIndex].value || 0;

                var selectElementMinute = document.querySelector('.ui-datepicker-wrapper select.minute');
                paramsDate.sureTime.minute = selectElementMinute.options[selectElementMinute.selectedIndex].value || 0;

                var selectElementSecond = document.querySelector('.ui-datepicker-wrapper select.second');
                paramsDate.sureTime.second = selectElementSecond.options[selectElementSecond.selectedIndex].value || 0;
            }

            if (1 <= selected_date && selected_date <= 31) {
                // 至少选中到天
                let date;
                if (0 <= paramsDate.sureTime.hour) {
                    date = new Date(paramsDate.monthData.year, paramsDate.monthData.month - 1, selected_date, paramsDate.sureTime.hour, paramsDate.sureTime.minute, paramsDate.sureTime.second);
                }
                else {
                    date = new Date(paramsDate.monthData.year, paramsDate.monthData.month - 1, selected_date);
                }

                $input.value = dateFormat(date, $targetFormat);
            }

            $datepicker_wrapper.classList.remove('ui-datepicker-wrapper-show');
            isOpen = false;

        }, false);

    };



    /* 定义一个函数,用于添加事件监听器,现代浏览器还是旧版IE浏览器。 */
    datepicker.addEventListener = function (el, eventName, callback, useCapture) {
        if (el.addEventListener) {
            el.addEventListener(eventName, callback, useCapture);
        } else if (el.attachEvent) {
            el.attachEvent('on' + eventName, callback);
        }
    };
    // 给输入框绑定点击事件
    datepicker.init = function (input, targetFormat) {
        this.addEventListener(document.querySelector(input), 'click', function (e) {
            let $paramsDate = new datepicker.paramsDate(e.target, targetFormat);
            datepicker.main($paramsDate);
        });
    };

    // 通过value设置选中项
    function setSelectedByValue(selectors, value) {
        var select = document.querySelector(selectors);
        if (!!!select || !!!select.options) {
            return false;
        }
        for (var i = 0; i < select.options.length; i++) {
            if (parseInt(select.options[i].value) == value) {
                select.options[i].selected = true;
                break;
            }
        }
    };
    /* 日期时间格式化·开始 */
    Date.prototype.Format = function (fmt) {
        if (!this || this.getFullYear() <= 1) return '';
        var o = {
            "M+": this.getMonth() + 1, //月份       
            "d+": this.getDate(), //日      
            "h+": this.getHours() == 0 ? 12 : this.getHours(), //小时       
            "H+": this.getHours(), //小时       
            "m+": this.getMinutes(), //分       
            "s+": this.getSeconds(), //秒       
            "q+": Math.floor((this.getMonth() + 3) / 3), //季度       
            "f": this.getMilliseconds() //毫秒       
        };
        var week = {
            "0": "\u65e5",
            "1": "\u4e00",
            "2": "\u4e8c",
            "3": "\u4e09",
            "4": "\u56db",
            "5": "\u4e94",
            "6": "\u516d"
        };
        const reg_y = /(y+)/;
        if (reg_y.test(fmt)) {
            fmt = fmt.replace(reg_y.exec(fmt)[1], (this.getFullYear() + "").slice(4 - reg_y.exec(fmt)[1].length));
        }
        const reg_E = /(E+)/;
        if (reg_E.test(fmt)) {
            fmt = fmt.replace(reg_E.exec(fmt)[1], ((reg_E.exec(fmt)[1].length > 1) ? (reg_E.exec(fmt)[1].length > 2 ? "\u661f\u671f" : "\u5468") : "") + week[this.getDay() + ""]);
        }
        for (var k in o) {
            const reg_k = new RegExp("(" + k + ")");
            if (reg_k.test(fmt)) {
                const t = reg_k.exec(fmt)[1];
                fmt = fmt.replace(t, (t.length == 1) ? (o[k]) : (("00" + o[k]).slice(("" + o[k]).length)));
            }
        }
        return fmt;
    };
    function dateFormat(date, format) {
        if (!date) return '';
        if (!format) format = 'yyyy/MM/dd HH:mm:ss';
        if ("object" == typeof (date)) return date.Format(format);
        else { return (new Date(date)).Format(format); }
    };
    /* 日期时间格式化·结束 */

})();

datepicker-v1.20250113.css 完整代码如下:
点击查看代码

.datepicker {
    width: 230px;
	padding: 5px;
	line-height: 24px;
    background: url(calendar-icon.png);
    background-repeat: no-repeat;
    background-position: right 3px center;
    padding-right: 20px;
	border: 1px solid #ccc;
	border-radius: 4px;
    -o-border-radius: 4px;
    -ms-border-radius: 4px;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    -khtml-border-radius: 4px;
}
.datepicker:focus {
	outline: none;
	border: 1px solid #1abc9c;
}

/* 最外层区域 */
.ui-datepicker-wrapper {
	display: none; /*添加默认隐藏*/
    position: absolute; /*添加绝对定位*/
    width: 240px;
    font-size: 16px;
    color: #666666;
	background-color: #fff;
    box-shadow: 2px 2px 8px 2px rgba(128, 128, 128, 0.3);
}
/* 头部区域 */
.ui-datepicker-wrapper .ui-datepicker-header,.ui-datepicker-wrapper .ui-datepicker-footer {
    padding: 0 20px;
    height: 50px;
    line-height: 50px;
    text-align: center;
    background: #f0f0f0;
    border-bottom: 1px solid #cccccc;
    font-weight: bold;
}
/* 设置两个按钮 */
.ui-datepicker-wrapper .ui-datepicker-btn {
    font-family: serif;
    font-size: 20px;
    width: 20px;
    height: 50px;
    line-height: 50px;
    color: #1abc9c;
    text-align: center;
    cursor: pointer;
    text-decoration: none;
}
.ui-datepicker-wrapper .ui-datepicker-prev-btn,.ui-datepicker-wrapper .ui-datepicker-prevYear-btn {
    float: left;
}
.ui-datepicker-wrapper .ui-datepicker-next-btn,.ui-datepicker-wrapper .ui-datepicker-nextYear-btn {
    float: right;
}
.ui-datepicker-wrapper .ui-datepicker-footer{
    display: flex;
    line-height: 30px;
    height: 30px;
    padding: 1px 1px;
    background-color: #fff;
}
.ui-datepicker-wrapper .ui-datepicker-footer a,.ui-datepicker-wrapper select,.ui-datepicker-wrapper select option{
    flex: 1 1 auto;
    width: 100%;
    height: 30px;
    line-height: 30px;
    font-size: 12px;
    text-align: center;
    cursor: pointer;
}
.ui-datepicker-wrapper .ui-datepicker-footer .ui-datepicker-btn{
    height: 28px;
    line-height: 28px;
    border:1px solid #c0c0c0;
}
.ui-datepicker-wrapper .ui-datepicker-footer .ui-datepicker-btn:hover,.ui-datepicker-wrapper .ui-datepicker-footer .ui-datepicker-btn:active{
    border:1px solid #1abc9c;
}

/* body区域 */
.ui-datepicker-wrapper .ui-datepicker-body table {
    width: 100%;
	border-collapse: separate;
    border-spacing: 1px;
}
/* 表头和正文 */
.ui-datepicker-wrapper .ui-datepicker-body th,
.ui-datepicker-wrapper .ui-datepicker-body td {
    height: 30px;
    text-align: center;
}
.ui-datepicker-wrapper .ui-datepicker-body th {
    font-size: 14px;
    height: 40px;
    line-height: 40px;
}
/* 表格部分 */
.ui-datepicker-wrapper .ui-datepicker-body td {
    border: 1px solid #f0f0f0;
    font-size: 12px;
    width: 14%;
    cursor: pointer;
}
/* "周末"的日期 */
.ui-datepicker-wrapper .ui-datepicker-body td.weekend{
	color: #FF5722;
}
/* 非"当前展示月份"的日期 */
.ui-datepicker-wrapper .ui-datepicker-body td.notmonth{
	background-color: #f3f3f3;
}
/* "今天"的日期 */
.ui-datepicker-wrapper .ui-datepicker-body td.today {
    border-color:#7cffe5;
}
.ui-datepicker-wrapper .ui-datepicker-body td.today:hover,.ui-datepicker-wrapper .ui-datepicker-body td.today:active,
.ui-datepicker-wrapper .ui-datepicker-body td:hover,.ui-datepicker-wrapper .ui-datepicker-body td:focus {
    border-color: #c0c0c0;
}
/* 选中的日期 */
.ui-datepicker-wrapper .ui-datepicker-body td:active,.ui-datepicker-wrapper .ui-datepicker-body td.active {
    border-color: #1abc9c;
}

.ui-datepicker-wrapper-show {
    display: block;
}

datepicker.html 做的一个简易 demo 完整代码如下:
点击查看代码

<!doctype html>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="MobileOptimized" content="240">
    <meta name="applicable-device" content="mobile">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta name="format-detection" content="telephone=no,email=no,adress=no">

    <link href="datepicker-v1.20250113.css" rel="stylesheet" type="text/css">

    <title>测试demo -datepicker </title>

    <script src="datepicker-v1.20250113.js"></script>
    
</head>

<body>
    支持两种格式的日期时间输入控件。短日期时间格式的:
    <input type="text" class="datepicker" id="t1">
    长日期时间格式的:
    <input type="text" class="datepicker" id="t2">

    <!-- JS脚本 -->
    <script>
        // var monthDate = datepicker.getMonthDate(2019, 2);
        // console.log(monthDate);
        // datepicker.init(document.querySelector('.ui-datepicker-wrapper'))
        document.querySelector('#t1').value = '2008/08/20';
        datepicker.init('#t1', 'yyyy/MM/dd');
        datepicker.init('#t2', 'yyyy/MM/dd HH:mm:ss');
    </script>

    调用示例:
    <code>
<pre style="background-color: #eee;padding: 5px 3px;border: 1px solid #ccc;">
&lt;!-- 引入 日期时间控件样式表文件 --&gt;
&lt;link href="datepicker-v1.20250113.css" rel="stylesheet" type="text/css"&gt;
&lt;!-- 引入 日期时间控件 JavaScript文件 --&gt;
&lt;script src="datepicker-v1.20250113.js"&gt;&lt;/script&gt;


支持两种格式的日期时间输入控件。短日期时间格式的:
&lt;input type="text" class="datepicker"  id="t1"&gt;
长日期时间格式的:
&lt;input type="text" class="datepicker"  id="t2"&gt;

&lt;script&gt;
    document.querySelector('#t1').value = '2008/08/20';
    datepicker.init('#t1', 'yyyy/MM/dd');
    datepicker.init('#t2', 'yyyy/MM/dd HH:mm:ss');
&lt;/script&gt;
</pre>
</code>

</body>

</html>

最后是输入框里的小图标:


完成代码已上传到 GitHub:GitHub 源代码

【完】

相关推荐
姚永强28 分钟前
登录系统网址作业
开发语言·前端·javascript
努力挣钱的小鑫43 分钟前
【Vue】vue3 video 保存视频进度,每次进入加载上次的视频进度
前端·javascript·音视频
明月看潮生1 小时前
青少年编程与数学 02-006 前端开发框架VUE 25课题、UI数据
javascript·vue.js·ui·青少年编程·编程与数学
黄团团1 小时前
Vue2+OpenLayers实现车辆开始、暂停、重置行驶轨迹动画(提供Gitee源码)
前端·javascript·数据库·vue.js·gitee·html
Judy16231 小时前
Vue 实现当前页面刷新的几种方法
前端·javascript·vue.js
芳草萋萋鹦鹉洲哦1 小时前
【element plus】虚拟dom表格中cellRenderer如何使用v-for循环渲染item
前端·javascript·elementui·虚拟dom表格
图扑软件2 小时前
智慧充电桩可视化管理提升能源效率
前端·javascript·人工智能·能源·数字孪生·可视化·充电桩
Lysun0012 小时前
vue3里面,事件触发一次,方法执行多次
javascript·vue.js·elementui·element-plus
♟彦♟2 小时前
web-前端小实验8
开发语言·前端·javascript
秋意钟2 小时前
Vue2实现上传图片到阿里云的OSS对象存储
javascript