带图像的模态对话框仅在用户第一次加载页面时显示

Modal dialog with image show only the first time a user loads the page

我正在为一个项目使用 Angular 11、Angular material 和 Bootstrap,我的问题是我想在用户第一次加载时显示一个弹出窗口和广告主页,模态对话框是在 angular material 中制作的,我在广告组件中有模态对话框,然后在 ngOnInit 的主页组件中调用它,这样对话框就会在用户加载主页时显示页面,我找到了一些使用 JS 的解决方案,但没有使它们对我有用,请问我如何解决这个问题?

我的广告组件html,我只显示图片,没有关闭模式的按钮,但如果我需要为解决方案添加按钮,我可以添加按钮。

<mat-dialog-content id="myModal" class="gradient-border">
  <img style="max-width: 100%" src="../../../assets/img/modal-ad.jpg" />
</mat-dialog-content>

广告组件 ts

import { Component, OnInit } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';

@Component({
  selector: 'app-anuncios',
  templateUrl: './anuncios.component.html',
  styleUrls: ['./anuncios.component.css'],
})
export class AnunciosComponent implements OnInit {
  constructor(public dialogRef: MatDialogRef<AnunciosComponent>) {}

  ngOnInit(): void {}
}

主页组件 ts

import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { AnunciosComponent } from '../anuncios/anuncios.component';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit {
  constructor(public dialog: MatDialog) {}

  ngOnInit(): void {
    this.showDialog();
  }

  showDialog() {
    const dialogRef = this.dialog.open(AnunciosComponent, {
      maxWidth: '100vw',
      maxHeight: '150vw',
      panelClass: ['animate__animated', 'animate__bounceInDown'],
    });
  }
}

所以这段代码让模态对话框总是在主页加载时显示,我需要在用户第一次加载主页时显示它,我看到一些使用cookies或JS函数的解决方案但没有制作正如我所说,它们对我有用,我是新手,我认为我没有在我的项目中正确使用这些解决方案,我们将不胜感激。

如果为了实现您的意思,您需要“记住”用户是否已经看过该对话框。

现在我有另一个问题要问你:

  1. 用户是否需要在每次加载页面时都看到这个?
  2. 一次又一次?
  3. 每次他在您的网站上发起会话? (打开浏览器浏览您的站点)

如果您的用例类似于选项 1,那么您可能只有一个内部变量。您可以将 static 变量与布尔值一起使用,也可以使用来自 Angular.

的单例服务
@Component({...})
export class MyComponent {
  public static hasAdvertBeenShown = false

  ngOnInit() {
     if(!MyComponent.hasAdvertBeenShown) {
        this.matRef.showDialog()
        MyComponent.hasAdvertBeenShown = true
     }
  }

}

如果您的用例是在用户第一次浏览您的网站时显示广告,那么您的变量将存储在 localStorage 中,并且它会在打开和关闭浏览器时继续存在。

@Component({...})
export class MyComponent {
  public static hasAdvertBeenShown = MyComponent.hasAdvertBeenShownBefore()

  ngOnInit() {
     if(!MyComponent.hasAdvertBeenShown) {
        this.matRef.showDialog()
        MyComponent.markAsSeen()
     }
  }

  public static boolean hasAdvertBeenShownBefore() {
    return JSON.parse(localStorage.getItem('advert'))
  }
  public static boolean markAsSeen() {
    localStorage.setItem('advert', true)
  }

}

如果您的用例是后者,那么使用 sessionStoragelocalStorage 类似,但它的寿命较短(每个会话)

@Component({...})
export class MyComponent {
  public static hasAdvertBeenShown = MyComponent.hasAdvertBeenShownBefore()

  ngOnInit() {
     if(!MyComponent.hasAdvertBeenShown) {
        this.matRef.showDialog()
        MyComponent.markAsSeen()
     }
  }

  public static boolean hasAdvertBeenShownBefore() {
    return JSON.parse(sessionStorage.getItem('advert'))
  }
  public static boolean markAsSeen() {
    sessionStorage.setItem('advert', true)
  }

}

如果您想了解有关本地和会话存储的更多信息,可以take a read over here

这是我通常在我的应用程序中做的事情

每当我需要将某些内容存储到 localStorage 中时,将其作为首选项(用户设置、暗模式等),并且我希望它在浏览器重新启动后仍然存在,我需要使用 localStorage。

由于使用原始 localStorage 很容易变得混乱,我所做的只是创建一个包装“低级”本地存储逻辑的单例“UserSettingsService”,以便我可以在代码库中共享它:

@Inject({providedIn: 'root'})
export class SettingsService {
  private storage: Storage = localStorage // Change this based on your use-case

  public markAdvertisementAsShown() {
    this.storage.setItem('advert', true)
  }

  public boolean hasAdvertisementBeenShown() {
    const safeBoolean = this.storage.getItem('advert') ?? 'false' // defaulting to false in case it didnt exist
    return JSON.parse(safeBoolean)
  }

}

然后在我的另一个 类:

@Component({...})
export class SomeComponent {
   hasAdvertBeenShown = this.adverts.hasAdvertisementBeenShown()
  constructor(private matRef: Mat..., private adverts: AdvertService){}

  ngOnInit() {
    if(!this.hasAdvertBeenShown) {
      // do something like showing the advert
      this.adverts.markAdverisementAsShown()
    }
  }
}

布尔值似乎有点矫枉过正,但应用程序往往会变得越来越复杂。就像您稍后想要展示 3 个不同的广告一样,您需要确定展示的是哪一个。现在您不会序列化布尔值,而是序列化已显示的广告对象。逻辑变得更加复杂,但因为它在服务中,您只需在那里更改它,它就会在您的应用程序中再次运行!