Flask项目实现长按按钮重复触发执行指定函数的问题求助
后端调整
首先新增一个独立的异步接口处理动作执行请求,避免页面刷新:
from flask import ( Blueprint, render_template, request, jsonify ) from webapp.Utilities.utilities import SerialHandler from webapp.blueprints.decorators import login_required bp = Blueprint('main', __name__) serial_scheduler = SerialHandler() # 原页面路由保留 @bp.route('/', methods=('GET',)) @login_required def index(): return render_template('index.html', title="Index") # 新增动作执行接口 @bp.route('/run-action', methods=('POST',)) @login_required def run_action(): button_action = request.form.get('action') # 这里可以根据button_action的值执行对应的逻辑,调用serial_scheduler的方法 foo() return jsonify({"status": "success"})
前端调整
修改原有表单和按钮逻辑,用JS处理长短按事件,异步调用后端接口:
{% extends "layout.html" %} {% block stylesheet %} <link rel="stylesheet" href="{{ url_for('static', filename='index.css') }}"> {% endblock %} {% block content %} <div class="container new_container"> <div class="card" style="width: 18rem;"> <div class="card-header"> Featured </div> <ul class="list-group list-group-flush"> <li class="list-group-item">An item</li> <li class="list-group-item">A second item</li> <li class="list-group-item">A third item</li> </ul> </div> </div> <div class="container"> <img src="{{ url_for('video.video') }}" alt=""> </div> <!-- 去掉原有form的默认提交逻辑,给按钮加标识 --> <div class="btn-group" style="width:100%"> <button class="action-btn" data-action="Apple" style="width:33.3%">Apple</button> <button class="action-btn" data-action="Samsung" style="width:33.3%">Samsung</button> <button class="action-btn" data-action="Sony" style="width:33.3%">Sony</button> </div> <div class="container new_container"> <div class="col-md-12 text-center"> <button onclick="switch_theme()" class="btn btn-light shadow-none" id="switch_button" style="width: 15%;">Dark Mode</button> </div> </div> <script> function switch_theme() { const theme = document.getElementById('switch_theme').className; if(theme === "dark-theme") { document.getElementById('switch_theme').className = "light-theme"; document.getElementById('switch_button').className = "btn btn-dark shadow-none"; document.getElementById('switch_button').innerHTML = "Light Mode"; } else { document.getElementById('switch_theme').className = "dark-theme"; document.getElementById('switch_button').className = "btn btn-light shadow-none"; document.getElementById('switch_button').innerHTML = "Dark Mode"; } } // 长短按逻辑 let pressTimer = null; let repeatTimer = null; let pressStartTime = 0; const LONG_PRESS_THRESHOLD = 200; // 长按判定阈值,单位ms const REPEAT_INTERVAL = 150; // 长按后重复执行的间隔,单位ms // 发送请求的公共方法 function sendActionRequest(action) { const formData = new FormData(); formData.append('action', action); fetch('/run-action', { method: 'POST', body: formData, headers: { 'X-CSRFToken': '{{ csrf_token() }}' // 如果你的Flask开启了CSRF保护需要加这行 } }); } // 给所有动作按钮绑定事件 document.querySelectorAll('.action-btn').forEach(btn => { const action = btn.dataset.action; // 按下事件 btn.addEventListener('mousedown', (e) => { e.preventDefault(); pressStartTime = Date.now(); // 长按判定定时器 pressTimer = setTimeout(() => { // 长按触发重复执行 repeatTimer = setInterval(() => { sendActionRequest(action); }, REPEAT_INTERVAL); }, LONG_PRESS_THRESHOLD); }); // 松开/移出按钮事件 ['mouseup', 'mouseleave', 'touchend', 'touchcancel'].forEach(eventName => { btn.addEventListener(eventName, (e) => { e.preventDefault(); // 清除所有定时器 clearTimeout(pressTimer); clearInterval(repeatTimer); pressTimer = null; repeatTimer = null; // 判断是否为短按 if (Date.now() - pressStartTime < LONG_PRESS_THRESHOLD) { sendActionRequest(action); } }); }); }); </script> {% endblock %}
说明
- 短按按钮会触发1次后端动作执行,长按按钮超过200ms后会每隔150ms触发一次,松开就停止
- 所有请求都是异步发起,不会刷新当前页面
- 如果你的Flask项目开启了CSRF保护,需要保留代码里CSRFToken的配置
内容的提问来源于stack exchange,提问作者std124_lf
相关产品推荐
相关产品推荐

