基于React.js与Node.js的待办清单当日任务提醒实现(附代码)
当日任务提醒功能实现方案
一、服务端(Node.js):任务筛选与触发逻辑
核心是从数据库筛选当日待提醒任务,再通过定时任务或实时推送触发提醒,这里以MongoDB为例实现。
1. 依赖安装
npm install node-schedule moment mongoose
2. 任务数据模型
先定义待办任务的Schema,存储日期和提醒状态:
// models/Todo.js const mongoose = require('mongoose'); const todoSchema = new mongoose.Schema({ title: String, content: String, dueDate: Date, // 客户端传入的任务截止日期 userId: String, // 关联用户ID,用于定向推送 isReminded: { type: Boolean, default: false } // 标记是否已发送提醒 }); module.exports = mongoose.model('Todo', todoSchema);
3. 当日任务筛选函数
筛选出当日未发送提醒的任务:
// services/reminderService.js const moment = require('moment'); const Todo = require('../models/Todo'); async function getTodayUnremindedTodos() { const startOfDay = moment().startOf('day').toDate(); const endOfDay = moment().endOf('day').toDate(); return await Todo.find({ dueDate: { $gte: startOfDay, $lte: endOfDay }, isReminded: false }); }
4. 定时触发提醒
用node-schedule设置每日固定时间(比如早9点)执行提醒任务,同时标记任务为已提醒:
// server.js const schedule = require('node-schedule'); const { getTodayUnremindedTodos } = require('./services/reminderService'); const Todo = require('./models/Todo'); const { Server } = require('socket.io'); const http = require('http'); const app = require('./app'); const server = http.createServer(app); const io = new Server(server); // 每日9点执行提醒 const reminderJob = schedule.scheduleJob('0 9 * * *', async () => { const todayTodos = await getTodayUnremindedTodos(); if (todayTodos.length === 0) return; // 标记任务为已提醒 await Todo.updateMany( { _id: { $in: todayTodos.map(todo => todo._id) } }, { isReminded: true } ); // 通过Socket.io推送给对应在线用户 todayTodos.forEach(todo => { io.to(todo.userId).emit('today-reminder', { message: `你有当日任务待完成:${todo.title}`, todo: todo }); }); }); server.listen(3001, () => console.log('服务启动'));
5. 客户端拉取接口
提供接口让客户端主动获取当日任务:
// routes/todos.js const express = require('express'); const router = express.Router(); const { getTodayUnremindedTodos } = require('../services/reminderService'); router.get('/today', async (req, res) => { try { const todos = await getTodayUnremindedTodos(); res.json(todos); } catch (err) { res.status(500).json({ message: '获取任务失败' }); } }); module.exports = router;
二、客户端(React):提醒接收与本地通知
支持两种方式获取提醒:主动定时拉取、Socket.io实时推送,同时利用浏览器Notification API弹出本地提醒。
1. 主动拉取实现
组件挂载后定时请求服务端接口,有任务则触发本地通知:
// components/Reminder.js import { useEffect, useState } from 'react'; import axios from 'axios'; const Reminder = () => { const [todayTodos, setTodayTodos] = useState([]); const fetchTodayTodos = async () => { try { const res = await axios.get('/api/todos/today'); setTodayTodos(res.data); if (res.data.length > 0) triggerNotification(res.data); } catch (err) { console.error('获取当日任务失败', err); } }; const requestNotificationPermission = async () => { if ('Notification' in window) { const permission = await Notification.requestPermission(); if (permission !== 'granted') alert('请开启浏览器通知权限以接收提醒'); } }; const triggerNotification = (todos) => { if (Notification.permission !== 'granted') return; todos.forEach(todo => { new Notification('待办清单提醒', { body: `今日任务:${todo.title}`, icon: '/todo-icon.png' // 自定义通知图标 }); }); }; useEffect(() => { requestNotificationPermission(); fetchTodayTodos(); // 每小时拉取一次 const interval = setInterval(fetchTodayTodos, 3600000); return () => clearInterval(interval); }, []); return ( <div className="reminder"> {todayTodos.length > 0 && ( <div className="alert"> <h3>今日待办</h3> <ul> {todayTodos.map(todo => ( <li key={todo._id}>{todo.title}</li> ))} </ul> </div> )} </div> ); }; export default Reminder;
2. Socket.io实时接收
监听服务端推送的提醒事件,实时弹出通知:
// components/SocketReminder.js import { useEffect } from 'react'; import io from 'socket.io-client'; const socket = io('http://localhost:3001'); const SocketReminder = () => { useEffect(() => { const requestPermission = async () => { if ('Notification' in window) await Notification.requestPermission(); }; requestPermission(); socket.on('today-reminder', (data) => { if (Notification.permission === 'granted') { new Notification('待办清单提醒', { body: data.message, icon: '/todo-icon.png' }); } }); return () => socket.off('today-reminder'); }, []); return null; }; export default SocketReminder;
三、注意事项
- 浏览器通知必须用户授权,需先调用
requestPermission - 服务端定时任务依赖进程存活,部署时用PM2等工具守护Node进程
- 若为React Native应用,替换浏览器Notification API为
react-native-push-notification - 可调整提醒触发逻辑,比如任务截止前1小时推送,而非固定每日9点
内容的提问来源于stack exchange,提问作者sina pouladrag
相关产品推荐
相关产品推荐

