我正在填充一个空列表对象
<ul id="results"></ul>
通过涡轮流请求
# myaction.turbo_stream.erb
<%= turbo_stream.append "results" do %>
<li data-mystimulus_target="item">HELLO WORLD</li>
<% end %>
我通过从刺激控制器获取api发出请求,并且我想与新的item
目标进行交互,一旦它们被附加到DOM。
// mystimulus_controller.js
static targets = ["item"]
connect() {
fetch(this.myRequest())
.then(response => {
if (response.ok) {
return response.text()
}
throw response.status
})
.then(html => {
Turbo.renderStreamMessage(html)
// immediate
console.log("immediate has items check", this.hasItemTarget))
// delayed
this.delay(1000).
then(() => console.log("delayed has items check", this.hasItemTarget))
})
.catch(error => console.warn(error))
}
myRequest() {
return new Request("myurl", {
method: "GET",
headers: {
Accept: "text/vnd.turbo-stream.html"
},
redirect: "manual"
});
}
delay(milliseconds){
return new Promise(resolve => {
setTimeout(resolve, milliseconds);
});
}
console.log("immediate has items check", this.hasItemTarget))
返回false
console.log("delayed has items check", this.hasItemTarget))
返回true
Turbo.renderStreamMessage
似乎是异步的,但是在挖掘之后,我没有发现这个函数暴露的任何回调或承诺。
我忽略了什么吗?是否有更好的方法来确保Turbo.renderStreamMessage
在继续之前已经完成(我想摆脱我的delay()
函数)。
Turbo stream在这里只做一个简单的append
,如果你想做一些比这更复杂的事情,也许一个自定义的Turbo stream动作将是一个更好的选择:
https://turbo.hotwired.dev/handbook/streams自定义动作
您可以使用刺激目标回调来知道元素何时插入:
<li data-mystimulus-target="item">HELLO WORLD</li>
^
添加到刺激控制器:
itemTargetConnected(target) {
console.log(target);
}
https://stimulus.hotwired.dev/reference/targets connected-and-disconnected-callbacks
你可以添加自己的观察者:
connect() {
this.observer = new MutationObserver((mutationList) => {
mutationList.forEach((mutation) => {
if (mutation.type == "childList") {
mutation.addedNodes.forEach((node) => {
if (node instanceof Element) {
console.log(node);
}
});
}
});
});
this.observer.observe(this.element, { childList: true });
}
disconnect() {
this.observer.disconnect();
}
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
另外,不要低估涡轮框架,它可以为你做一些工作:
<%= turbo_frame_tag :results, data: {controller: :mystimulus} %>
最好在请求位置有一个匹配的turbo-frame
,但这也可以:
connect() {
this.element.src = "/myurl.turbo_stream"
}
别做过头了:
connect() {
this.element.loaded
.then(() => {
this.element.src = "/items/1.turbo_stream";
return this.element.loaded;
})
.then(() => {
this.element.src = "/items/2.turbo_stream";
return this.element.loaded;
})
.then(() => {
this.element.src = "/items/3.turbo_stream";
});
}
<<p>https://turbo.hotwired.dev/reference/frames属性/em>