使用 templateUrl 中的条件在移动或桌面模板之间切换 (Angular 7)

Switch between mobile or desktop template using condition in templateUrl (Angular 7)

我想根据屏幕宽度在桌面和移动模板之间切换,以确保我的应用程序具有响应能力。我正在尝试执行以下操作:

@Component({
    selector: 'app-root',
    templateUrl: "./" + (window.innerWidth < 768) ? "app.component.html" : "app.component.mobile.html",
    styleUrls: ['./app.component.css']
})

但是,这不起作用。代替模板加载,字符串 "app.component.html" 出现在屏幕上。

更有趣的是,如果我使用以下内容:

@Component({
    selector: 'app-root',
    templateUrl: "./" + (false) ? "app.component.html" : "app.component.mobile.html",
    styleUrls: ['./app.component.css']
})

页面仍然只显示字符串 "app.component.html"

是否不支持使用条件语句作为 @Component 装饰器中 templateUrl 字段的值?

如果不是,我可以使用什么替代解决方案来实现这种响应级别,它仍然是模块化并遵循最佳实践

更新:我通过使用 ng serve --aot 而不是 ng serve 来实现它。但是,我决定不考虑这个想法,因为它不会随着 window 调整大小而切换模板。

我相信你能做到这一点 -

export function getTemplateUrl() {
  if (window.innerWidth < 768)
    return "app.component.html";
  else 
    return "app.component.mobile.html";
}

@Component({
  selector: 'app-root',
  templateUrl: getTemplateUrl(),
  styleUrls:['./app.component.css']
})

然后使用 aot - ng serve --aot 编译您的应用程序。这适用于 angular 的较低版本,我还没有尝试使用 Angular 7,但应该可以。

你这里的方法不对。模板在构建时分配给组件,而不是运行时,并且 Angular 将构建它的所有组件,远早于任何 window 存在的宽度以写出条件。您需要设置逻辑来告诉您的应用程序何时显示哪个组件。

"best practice" (IMO) 在这里,如果你不能做响应式设计(注意:了解你的受众和应用程序的使用方式很重要。我总是尝试先选择移动设备响应式设计,但也认识到这并不总是合适的),是有 2 个组件,并使用路由守卫来强制执行正确的组件。

@Injectable()
export class MobileGuard implements CanActivate {

  constructor(
    private router: Router
  ) { }

  canActivate() {

    if (window.innerWidth >= 768) {
      this.router.navigate(['/']);
      return false;
    }

    return true;
  }
}

@Injectable()
export class DesktopGuard implements CanActivate {

  constructor(
    private router: Router
  ) { }

  canActivate() {

    if (window.innerWidth < 768) {
      this.router.navigate(['/m/']);
      return false;
    }

    return true;
  }
}

然后像这样定义路由结构:

const routes: Routes = [
  {
    path: '',
    component: AppComponent,
    canActivate: [DesktopGuard],
    children: [... desktop routes ...]
  },
  {
    path: 'm',
    component: MobileAppComponent,
    canActivate: [MobileGuard],
    children: [... mobile routes ...]
  }
]

至于组件本身,您的移动组件只是扩展了您的非移动组件并关联了不同的模板/样式。

另一种方法是执行如下操作:

export class WrapperAppComponent {
    isMobile: boolean;

    constructor() {
      this.isMobile = window.innerWidth < 768;
    }
}

模板如下:

<desktop-app *ngIf="!isMobile"></desktop-app>
<mobile-app *ngIf="isMobile>></mobile-app>

但这不是一种可扩展性很强的方法,并且具有相同的 "duplication" 组件。

如果您的应用程序做很多事情,那么您将需要路由到 /mobile,也许使用 navigator.userAgent,然后将用户推送到那里。

您不能使用旧的 'screen width <= 768',因为例如 iPhone XR 在 5.9" 宽屏幕上的屏幕宽度为 1792 像素,所以实际上重要的是像素密度,而您不能访问。