前军教程网

中小站长与DIV+CSS网页布局开发技术人员的首选CSS学习平台

Stimulus 如何用加载和插入远程HTML片段来异步填充页面

前一篇文章Stimulus 状态管理,幻灯片显示讲述了Stimulus的状态管理,接下来我们看看如何跟踪外部资源的状态。

有时候我们的controllers需要跟踪外部的资源的状态,这里的外部指的是不在DOM或不在Stimulus中的任何东西。例如,我们可能需要发出HTTP请求,并在请求状态变化时进行响应。或者我们希望启动一个定时器,然后当controller断开连接时停止定时器。在本文,我们将解决这些问题。


接下来,我们学习一下,如何通过加载和插入远程HTML片段,来异步填充页面的各个部分。


我们要创建一个通用的用于加载内容的controller,所有的HTML内容都是从服务器获取的。然后我们将用它来加载一系列未读的消息,就像你在邮箱里看到的那样。


打开public/index.html:

<div data-controller="content-loader"
    data-content-loader-url-value="/messages.html"></div>

然后创建一个public/messages.html

<ol>
    <li>New Message: Stimulus Launch Party</li>
    <li>Overdue: Finish Stimulus 1.0</li>
</ol>

在真实应用中,这个内容是服务器动态生成的,但是这里出于示范的目的,我们就用一个静态文件。


现在我们实现一下我们的controller:

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
    static values = { url: String }

    connect() {
        this.load()
    }

    load() {
        fetch(this.urlValue)
            .then(response => response.text())
            .then(html => this.element.innerHTML = html)
    }
}

当controller连接元素时,会根据data-content-loader-url-value属性值设置的url,发起请求。然后把请求得到的HTML内容,赋值给连接元素的innerHTML。


打开浏览器的开发者工具,点开网络查看tab页,然后刷新页面。您将看到一个表示初始页面加载的请求,随后是controller对messages.html的后续请求。


我们继续优化一下controller,隔段时间就刷新div内的内容,让它一直显示最新的内容。


我们使用data-content-loader-refresh-interval-value属性值来设定刷新的时间间隔,单位是毫秒,

<div data-controller="content-loader"
    data-content-loader-url-value="/messages.html"
    data-content-loader-refresh-interval-value="5000"></div>

现在我们修改一下controller,检查间隔,如果间隔值存在,就启动一个定时器来刷新。


在controller里添加一个static values,然后定义一个新方法startRefreshing():

export default class extends Controller {
    static values = { url: String, refreshInterval: Number }
    
    startRefreshing() {
        setInterval(() => {
            this.load()
        }, this.refreshIntervalValue)
    }

    // …
}

然后修改connect()方法,如果refreshInterval值存在的话,就调用startRefreshing()方法。

connect() {
    this.load()

    if (this.hasRefreshIntervalValue) {
        this.startRefreshing()
    }
}

刷新页面,然后通过开发者工具,观察一下,是不是每5秒钟就会有一个新请求。然后可以尝试修改public/messages.html,所有的改变都会出现在div内。



当controller连接元素时,我们启动了定时器,但是我们没有停止它。这意味着,如果我们的controller连接的元素消失的话,controller将在后台继续发起HTTP请求。


我们修复这个问题,修改startRefreshing()方法,保存一个对定时器的引用:

startRefreshing() {
    this.refreshTimer = setInterval(() => {
        this.load()
    }, this.refreshIntervalValue)
}

然后添加一个对应的stopRefreshing()方法,来取消定时器:

stopRefreshing() {
    if (this.refreshTimer) {
        clearInterval(this.refreshTimer)
    }
}

最终,我们告诉Stimulus当controller失去连接时,取消定时器,好,我们添加一个disconnect()方法:

disconnect() {
    this.stopRefreshing()
}

现在我们可以确定,内容加载器controller只会在连接到DOM时才会发出请求。


我们来看一下最终的controller类:

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
    static values = { url: String, refreshInterval: Number }

    connect() {
        this.load()

        if (this.hasRefreshIntervalValue) {
            this.startRefreshing()
        }
    }

    disconnect() {
        this.stopRefreshing()
    }

    load() {
        fetch(this.urlValue)
            .then(response => response.text())
            .then(html => this.element.innerHTML = html)
    }

    startRefreshing() {
        this.refreshTimer = setInterval(() => {
            this.load()
        }, this.refreshIntervalValue)
    }

    stopRefreshing() {
        if (this.refreshTimer) {
            clearInterval(this.refreshTimer)
        }
    }
}

本文介绍了如何使用Stimulus生命周期回调来获取和释放外部资源。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言