如何在不预先知道设备屏幕尺寸的情况下为响应式应用程序执行 s-s-r?

Posted

技术标签:

【中文标题】如何在不预先知道设备屏幕尺寸的情况下为响应式应用程序执行 s-s-r?【英文标题】:How to do s-s-r for responsive apps without knowing the device's screen size upfront? 【发布时间】:2020-08-23 22:59:14 【问题描述】:

我想为我的用户 s-s-r 我的应用。

但我的应用代码使用useEffect 来检测用户屏幕宽度的大小,然后才呈现应用。

类似:

App.js

  // THE LAYOUT INITIAL STATE IS NULL

  useEffect(() => 
    // CHECK FOR window.innerWidth AND DECIDE LAYOUT
    // UPDATE LAYOUT STATE
  );

  return(
    layout && <AppComponents>   // IF THERE IS NO LAYOUT, NOTHING IS RENDERED
  );

Component.js

 // I SERVE THE LAYOUT THROUGH CONTEXT AND I ACCESS IT INSIDE OF THE COMPONENTS

 const layout = useLayout();

 return(
   layout === "MOBILE" ? ComponentMobile : ComponentDesktop
 );

问题

我不能依赖 useEffect 中的代码在服务器上渲染内容。所以,不知何故,我需要“决定”第一次使用哪种布局,并且只在服务器上渲染。

所以我的选择,至少我目前为止的选择是:

选项 #1

尝试猜测用户的设备屏幕尺寸,并渲染一些可能不是最适合他们屏幕尺寸的东西。

因为现在,我渲染的 CSS 样式取决于用户的屏幕尺寸。

选项 #2

完全移至媒体查询来处理响应性,因此 CSS 将始终相同,并且会自动适应所使用的任何屏幕尺寸。

到目前为止,我还没有使用过媒体查询。我所有的布局决策都是在渲染期间做出的,所有组件都根据 App.js 状态决定的布局来渲染样式。


处理此问题的最佳方法是什么?有这方面的最佳做法吗?

注意:

我正在使用styled-components,所以这基本上就是我所做的:

这是一个粗略的例子,但这就是想法。


// THIS IS MUCH EASIER TO WRITE THAN A BUNCH OF MEDIA QUERIES (IMO)

const Styled_DIV = styled.div`
  font-size: $props => 
    props.layout === "MOBILE" ? "16px" 
    : props.layout === "TABLET" ? "18px" 
    : "20px"
  ;
`;

【问题讨论】:

似乎没有简单的解决方案。根据布局的不同,可能首选媒体查询。在我们的项目中,这很乏味,但可能更可靠。如果布局完全不同,那么检测设备大小并提供完全不同版本的应用程序可能有意义吗? 我还没有完全解决这个问题,因为我只是为机器人爬虫做s-s-r,我可以预先知道那些爬虫的移动设备。例如,Googlebot mobile 使用 Nexus 5x。所以我在此基础上进行渲染。对于用户,我肯定会尝试仅媒体查询。但是如果你在客户端上水化,可能首先显示一个加载器,水化你的 JS 并获取屏幕宽度,然后才渲染页面的其余部分。你怎么看? 是的,如果 s-s-r 仅适用于标准着陆页或加载程序,那会更容易。如果您希望 s-s-r 可用于整个应用程序,例如深度链接的子页面,这将变得很棘手。可能无法逃避媒体查询/不同的应用程序。 【参考方案1】:

太好了,您已经在使用styled-components。添加媒体查询现在变得微不足道,实际上比您建议的方法更直接 (IMO)。

一般来说,使用 CSS 配置布局比使用 JS 更好。而使用s-s-r,就像你说的,服务器还不能用JS和useEffect确定屏幕大小。

如果您首先使用移动设备,则可以使用以下媒体查询编写上述逻辑:

const Styled_DIV = styled.div`
  font-size: 16px;

  @media (min-width: 768px) 
    font-size: 18px;
  

  @media (min-width: 1024px) 
    font-size: 20px;
  
`

我编写了一个辅助对象导出,因此我不必记住像素大小甚至媒体查询的语法:

export const size = 
  tablet: 768,
  desktop: 1024,


export const device = 
  tablet: `@media (min-width: $size.tabletpx)`,
  desktop: `@media (min-width: $size.desktoppx)`,

所以现在我只需要写:

const Styled_DIV = styled.div`
  font-size: 16px;

  $device.tablet 
    font-size: 18px;
  

  $device.desktop 
    font-size: 20px;
  
`

由于device 是一个导出对象,我的 VSCode 编辑器会在我开始输入时自动帮助我导入它。

【讨论】:

以上是关于如何在不预先知道设备屏幕尺寸的情况下为响应式应用程序执行 s-s-r?的主要内容,如果未能解决你的问题,请参考以下文章

在不使用自动布局的情况下调整 iPhone 5 屏幕尺寸

如何在不放弃主线程的情况下为 Python 使用 CoreBluetooth

不同设备尺寸的 iOS 自动布局约束值

我想为不同的屏幕尺寸制作 Android 应用响应式布局

响应式设计与自适应设计有何区别?

响应式设计:不要过度依赖屏幕尺寸