问题
I was working on a custom component and stumbled upon this strange behavior. Basically, it is possible to play a video file without adding a <video>
element to the DOM at all.
const video = document.createElement('video');
video.src = "https://upload.wikimedia.org/wikipedia/commons/transcoded/c/c6/Video_2017-03-19_23-01-33.webm/Video_2017-03-19_23-01-33.webm.480p.webm";
function start()
{
if (video.paused)
{
video.play();
console.log('paused', video.paused);
}
}
<div><button onclick='start()'>Start</button></div>
Anyway, if at some point the element is added to the DOM tree and subsequently removed, then the video pauses automatically (!)
const video = document.createElement('video');
video.src = "https://upload.wikimedia.org/wikipedia/commons/transcoded/c/c6/Video_2017-03-19_23-01-33.webm/Video_2017-03-19_23-01-33.webm.480p.webm";
function start()
{
if (video.paused)
{
video.play().then(
() =>
setTimeout(
() =>
{
document.body.removeChild(video);
setTimeout(() => console.log('paused after', video.paused), 0);
},
3000
)
);
document.body.appendChild(video);
console.log('paused before', video.paused);
}
}
<div><button onclick='start()'>Start</button></div>
The same considerations apply to <audio>
elements, too.
I have two questions here:
What part of the specification indicates that when a video element is removed from the DOM then it should stop playing?
What is the rationale for allowing detached videos to play but stopping videos when they are removed from the DOM tree? This is the part that surprises me most. If there is a use case for playing detached videos on a page, then why would subsequently detaching a video stop playback? On the other hand, if a detached video is stopped because there is no reason to keep playing it, then why allow it to start detached in first place?
回答1:
The specification is confusing. First it says:
Media elements that are potentially playing while not in a document must not play any video, but should play any audio component. Media elements must not stop playing just because all references to them have been removed; only once a media element is in a state where no further audio could ever be played by that element may the element be garbage collected.
If I understand this correctly, removing the element from the DOM should stop the video, but the audio should continue.
But later it says:
When a media element is removed from a Document, the user agent must run the following steps:
Await a stable state, allowing the task that removed the media element from the Document to continue. The synchronous section consists of all the remaining steps of this algorithm. (Steps in the synchronous section are marked with ⌛.)
⌛ If the media element is in a document, return.
⌛ Run the internal pause steps for the media element.
Step 3 says to pause the media.
Step 2 seems redundant -- how can the element be in a document if it's being removed from the document? But step 1 could add it back to the document (or a different document). That's why it requires waiting for a stable state (which is why you needed to use setTimeout()
in your example).
I think the second quote takes precedence, because when the pause steps are run, the element is no longer "potentially playing".
来源:https://stackoverflow.com/questions/50937026/why-does-a-video-stop-playing-when-removed-from-the-dom-while-it-can-still-pl