使用Rails 7 + Stimulus能否将浏览器屏幕宽度传递至服务器?
当然可行,以下是几种在 Rails 7 + Stimulus 场景下的实用实现方案:
方案1:页面初始加载时传递屏幕宽度
适合只需要在页面首次加载时获取屏幕尺寸并做布局的场景。
- 创建 Stimulus 控制器
// app/javascript/controllers/screen_size_controller.js import { Controller } from "@hotwired/stimulus" export default class extends Controller { connect() { // 获取浏览器视口宽度(若要设备物理屏幕宽度用screen.width) const viewportWidth = window.innerWidth; this.sendSizeToServer(viewportWidth); } sendSizeToServer(width) { fetch('/screen-size', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content }, body: JSON.stringify({ viewport_width: width }) }); } }
- 配置路由
# config/routes.rb post '/screen-size', to: 'screen_sizes#update'
- 服务器端接收并存储尺寸
# app/controllers/screen_sizes_controller.rb class ScreenSizesController < ApplicationController def update # 存储到session,供后续页面渲染使用 session[:viewport_width] = params[:viewport_width].to_i head :ok end end
- 在视图中使用尺寸做布局判断
# app/views/layouts/application.html.erb <% if session[:viewport_width] && session[:viewport_width] < 768 %> <%= render 'layouts/mobile_header' %> <% else %> <%= render 'layouts/desktop_header' %> <% end %>
方案2:监听窗口 resize 事件,实时更新尺寸
适合需要响应窗口缩放、设备旋转等动态尺寸变化的场景。
修改 Stimulus 控制器,加入防抖逻辑避免频繁请求:
// app/javascript/controllers/screen_size_controller.js import { Controller } from "@hotwired/stimulus" export default class extends Controller { connect() { this.sendSizeToServer(window.innerWidth); // 防抖处理resize事件,300ms内仅触发一次 this.resizeHandler = this.debounce(() => { this.sendSizeToServer(window.innerWidth); }, 300); window.addEventListener('resize', this.resizeHandler); } disconnect() { // 销毁监听,避免内存泄漏 window.removeEventListener('resize', this.resizeHandler); } sendSizeToServer(width) { fetch('/screen-size', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content }, body: JSON.stringify({ viewport_width: width }) }); } debounce(func, wait) { let timeout; return function() { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, arguments), wait); }; } }
方案3:结合 Turbo 处理页面导航
由于 Rails 7 默认集成 Turbo,页面导航会由 Turbo 接管,此时只需保证 Stimulus 控制器在每次页面加载时都执行 connect 逻辑即可(Turbo 会自动重新初始化控制器),无需额外修改。
关键注意事项
- 区分
window.innerWidth(浏览器视口宽度,含滚动条)和screen.width(设备物理屏幕宽度),根据布局需求选择 - 始终对 resize 事件做防抖处理,避免过多无效请求
- 考虑 JavaScript 禁用场景:用 CSS 媒体查询做降级布局,服务器端逻辑作为增强
- 不要依赖该值做权限等关键逻辑,客户端参数可被篡改,仅用于布局展示类需求
内容的提问来源于stack exchange,提问作者mksys
相关产品推荐
相关产品推荐

