【问题标题】:Ionic 4 ion-content scroll to bottomIonic 4 离子含量滚动到底部
【发布时间】:2019-08-02 15:36:55
【问题描述】:

我正在使用 Ionic 4 创建一个聊天页面,并试图让它自动滚动到页面底部。我这样做了,但它不起作用:

import { IonContent } from "@ionic/angular";

export class ChatroomPage implements OnInit {
    messageForm: FormGroup;
    messages: any[];
    messenger: any;
    @ViewChild(IonContent) content: IonContent;

    constructor(
        private navExtras: NavExtrasService,
        private api: RestApiService,
        private httpNative: HTTP
    ) { }

    ngOnInit() {
        this.content.scrollToBottom(300);
    }
}

在html文件中:

<ion-header>
    <ion-toolbar color="primary">
        <ion-title>Chatroom</ion-title>
            </ion-toolbar>
        </ion-header>

        <!-- display previous message -->
        <ion-content padding id="content"> 

        <ion-list>
            <ion-item *ngFor="let message of messages">
                {{ message.message }}
            </ion-item>
        </ion-list>

        </ion-content>

    <!-- chat message input -->
    <ion-footer>
        <form [formGroup]="messageForm" (submit)="sendMessage()" (keydown.enter)="sendMessage()">
            <ion-input formControlName="message" type="text" placeholder="Enter your message"></ion-input>
            <ion-button type="submit">Send</ion-button>
        </form>
    </ion-footer>

显示的错误是:

ng:///ChatroomPageModule/ChatroomPage_Host.ngfactory.js:5 ERROR TypeError: Cannot read property 'scrollToBottom' of undefined

请赐教我做错了什么。我发现的大多数教程都使用 Ionic 3,他们使用来自ionic-angularContent 而不是来自@ionic/angularIonContent。我似乎无法在 Ionic 4 中使用 Content,因为它没有 scrollToBottom 方法。

【问题讨论】:

  • 嘿!您可以在 ionViewDidEnter() 中调用滚动函数,而不是在 ngOnInit() 方法上调用。

标签: angular typescript ionic-framework ionic4


【解决方案1】:

你可以通过 scrollToBottom()

方法到达内容的底部
scrollToBottom(duration?: number) => Promise<void>

ion-content添加一个ID

<ion-content #content>
</ion-content>

获取 .ts 中的内容 ID 并使用选定的持续时间调用 scrollToBottom 方法

@ViewChild('content') private content: any;

ngOnInit() {
  this.scrollToBottomOnInit();
}

scrollToBottomOnInit() {
  this.content.scrollToBottom(300);
}

https://ionicframework.com/docs/api/content

编辑:

ViewChild 使用提供的内容 ID 获取正确的数据

@ViewChild('content') private content: any;

ngOnInit 与 ionViewDidEnter / ionViewWillEnter

如果您从导航堆栈返回,ngOnInit 不会触发,ionViewWillEnter / ionViewDidEnter 会。所以如果你把函数放在 ngOnInit 中,如果你往回导航,scrollToBottom 就不起作用了。

【讨论】:

  • 所以你的实现是正确的。 IonContent 导入不是必需的,您可以在不导入 IonContent 的情况下获取内容 ID。
  • 我已将代码从导入 IonContent 更改为内容 ID。起初它不起作用,但是我尝试在ionViewDidEnter() 中调用this.scrollToBottomOnInit(),现在它可以正常工作了。我认为这可能是由于在消息加载之前调用this.scrollToBottomOnInit() 引起的
  • 好电话。如果您从导航堆栈返回,ngOnInit 不会触发, ionViewWillEnter / ionViewDidEnter 会。也许您也可以在订阅接收到的数据后调用 scrollToBottom 方法。因此,当您的数据进入时,scrollToBottom 被激活。没试过,只是建议尝试一下;)
  • 啊,是的,我也应该将它用于订阅的数据。感谢您的提醒。我想你可以编辑你的答案,我会接受的。 :D
  • 只是为了说明:添加一些延迟可能会使其工作。例如:setTimeout(()=&gt;{this.scrollToBottomOnInit();},200);
【解决方案2】:

由于最近对 ionic 4 的更改,我发现建议答案中的代码不再适用于我。希望这对所有新人都有帮助。

import { IonContent } from '@ionic/angular';

export class IonicPage implements OnInit {
@ViewChild(IonContent, {read: IonContent, static: false}) myContent: IonContent;

  constructor() {}

  ScrollToBottom(){
    setTimeout(() => {
      this.myContent.scrollToBottom(300);
   }, 1000);

  }
}

.html 文件中没有为 指定 id

官方文档参考ion-content。 发布本文时使用的离子版本如下所示。

Ionic CLI                     : 5.4.13
Ionic Framework               : @ionic/angular 4.11.3
@angular/cli                  : 8.1.3

【讨论】:

  • 作品,2020 年 2 月确认
  • setTimeout 修复了时间问题。我正在向ion-content 添加一个元素,然后向下滚动。但是该元素是在向下滚动事件之后添加的。 setTimeout 修复了它。
【解决方案3】:

您的大部分代码都很好。您只需要在 Ionic 4 中进行 2 处更改,这应该对您有用。以下是更改:

更改 1(HTML 文件):

替换:

<ion-content padding id="content">

与:

<ion-content padding #content>

更改 2(TS 文件):

替换:

scrollToBottomOnInit() {
  this.content.scrollToBottom(300);
}

与:

scrollToBottomOnInit() {
    setTimeout(() => {
        if (this.content.scrollToBottom) {
            this.content.scrollToBottom(400);
        }
    }, 500);
}

注意:

如果你不导入IonContent(类似于你已经做的),代码将无法编译,你会看到如下控制台错误:

ERROR Error: Uncaught (in promise): ReferenceError: Cannot access 'MessagesPageModule' before initialization

其中MessagesPageModule 是与您尝试在其中实现该功能的页面关联的模块。

【讨论】:

    【解决方案4】:

    Tomas Vancoillie 是对的,但是当您添加新文本并添加到列表时,它不会将其推到输入文本之上。因此,要将文本推送到数组并再次将视图更新到底部,请使用 ngZone。

    1.

    import { Component, ViewChild,NgZone } from '@angular/core';
    
    1. 在构造函数中添加
    public _zone: NgZone
    
    1. 调用你的函数
    this._zone.run(() => {
      setTimeout(() => {
        this.contentchat.scrollToBottom(300);
      });
    }); 
    

    【讨论】:

      【解决方案5】:

      这对我来说适用于 2019 年 12 月

      .html

      <ion-content #content>
      
      </ion-content>
      

      .ts

      @ViewChild('content', { static: false }) content: IonContent;
      
      constructor(){}
      
       ngOnInit(): void {
          this.scrollToBottom();
        }
      
      
       scrollToBottom(): void {
          this.content.scrollToBottom(300);
        }
      

      【讨论】:

        【解决方案6】:

        这终于对我有用了。你可以试试看。

        .ts

        import { Component, OnInit, ViewChild, NgZone } from '@angular/core';
        

        /.. 类声明 .../

        @ViewChild('content') content : IonContent;
        
        constructor(public _zone: NgZone){
        }
        
        ngOnInit(): void {
            this.scrollToBottom();
        }
        
        scrollToBottom()
        {
            this._zone.run(() => {
        
              const duration : number = 300;
        
              setTimeout(() => {
                
                this.content.scrollToBottom(duration).then(()=>{
        
                  setTimeout(()=>{
        
                    this.content.getScrollElement().then((element:any)=>{
        
                      if (element.scrollTopMax != element.scrollTop)
                      {
                        // trigger scroll again.
                        this.content.scrollToBottom(duration).then(()=>{
        
                          // loaded... do something
        
                        });
                      }
                      else
                      {
                        // loaded... do something
                      }
                    });
                  });
                });
        
              },20);
            }); 
        }
        

        【讨论】:

        • 这对我来说是最好的解决方案。完美运行谢谢!
        • 谢谢,B 雪。
        【解决方案7】:
        @ViewChild(IonContent) content: IonContent;
        scrollToBottom() {
            setTimeout(() => {
              if (this.content.scrollToBottom) {
                this.content.scrollToBottom();
              }
            }, 400);
          }
        

        函数使用的任何地方:

        this.scrollToBottom();
        

        【讨论】:

          【解决方案8】:

          A mi me funcionó con la implementacion de AfterViewChecked del ciclo de vida de angular en angular 9 con fecha 2020 年 10 月 30 日

          1. 重要

            import { Component, OnInit, ViewChild, AfterViewChecked } from '@angular/core';

            import { IonContent } from '@ionic/angular';

          2. 实现 AfterViewChecked

            export class PublicationsProductPage implements AfterViewChecked {

          3. Cear el metodo scrollToBottom

            scrollToBottom() { this.content.scrollToBottom(); }

          4. Llamar el metodo scrollToBottom desde la implementationación de AfterViewChecked

            ngAfterViewChecked(){ this.scrollToBottom(); }

          con este codigo te aseguras de que siempre se dirija al final del ionconten

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-09-27
            • 1970-01-01
            • 1970-01-01
            • 2019-11-15
            • 1970-01-01
            • 1970-01-01
            • 2021-06-10
            • 1970-01-01
            相关资源
            最近更新 更多