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

使用Rails 7 + Stimulus能否将浏览器屏幕宽度传递至服务器?

当然可行,以下是几种在 Rails 7 + Stimulus 场景下的实用实现方案:

方案1:页面初始加载时传递屏幕宽度

适合只需要在页面首次加载时获取屏幕尺寸并做布局的场景。

  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 })
    });
  }
}
  1. 配置路由
# config/routes.rb
post '/screen-size', to: 'screen_sizes#update'
  1. 服务器端接收并存储尺寸
# app/controllers/screen_sizes_controller.rb
class ScreenSizesController < ApplicationController
  def update
    # 存储到session,供后续页面渲染使用
    session[:viewport_width] = params[:viewport_width].to_i
    head :ok
  end
end
  1. 在视图中使用尺寸做布局判断
# 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 12:20:27