Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multilayer teleport can not be remove completely #3623

Closed
yunbookf opened this issue Apr 17, 2021 · 3 comments · Fixed by #3629
Closed

Multilayer teleport can not be remove completely #3623

yunbookf opened this issue Apr 17, 2021 · 3 comments · Fixed by #3629
Labels
🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. has workaround A workaround has been found to avoid the problem 🐞 bug Something isn't working scope: teleport

Comments

@yunbookf
Copy link

Version

3.0.11

Reproduction link

https://codepen.io/jsqy/pen/xxgJWdw

Steps to reproduce

This is just one example, the reality will be more complex, but the principle should be the same.

Reproduction link: Click the "change" button to control the alternate display of the two divs, but the teleport in the #pop does not uninstall with the uninstall of the div.

What is expected?

Because I often use teleport in components, and the component's slot may also contain teleport, the elements in the #pop are not completely unmounted.

What is actually happening?

A multi-layered teleport can cause exceptions.

@LinusBorg
Copy link
Member

This seems to be more an issue caused by the element re-use between v-if and v-else. Adding a key can be used as a workaround:

<div id="app">
    <div v-if="mode">
		Mode 1
		<teleport to="#pop" :disabled="dis">
			<div class="port" :key="1">
				Port 1
				<teleport to="#pop" :disabled="dis">
					<div class="port" style="left: 200px;" :key="1">
						Port 2
					</div>
        </teleport>
			</div>
		</teleport>
	</div>
	<div v-else>
		Mode 2
		<teleport to="#pop" :disabled="dis">
			<div class="port" :key="2">
				Port 3
				<teleport to="#pop" :disabled="dis">
					<div class="port" style="left: 200px;" :key="2">
						Port 4
					</div>
				</teleport>
			</div>
		</teleport>
	</div>
	<div>
		<input type="button" @click="mode = !mode" value="Change mode" /> <input type="button" @click="dis = !dis" value="Change disabled" />
	</div>
  <div>Click "Change mode" button multiple times, u can see a lot of "port2" and "port4", which is obviously not right.</div>
</div>
<div id="pop"></div>

@LinusBorg LinusBorg added 🐞 bug Something isn't working 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. scope: teleport has workaround A workaround has been found to avoid the problem labels Apr 18, 2021
@edison1105
Copy link
Member

edison1105 commented Apr 18, 2021

I don't think this has anything to do with element re-use, but rather the nested teleport not being unmounted correctly.

image

When the el of Port1 was removed, Port2 was not removed correctly because it was mounted under pop.
My idea was to set optimized to false on unmount if it contained a nested teleport. this may not be a good solution, so I didn't submit a PR.

Finally, I submitted a PR and didn't think of a better way.

@yunbookf
Copy link
Author

This seems to be more an issue caused by the element re-use between v-if and v-else. Adding a key can be used as a workaround:

<div id="app">
    <div v-if="mode">
		Mode 1
		<teleport to="#pop" :disabled="dis">
			<div class="port" :key="1">
				Port 1
				<teleport to="#pop" :disabled="dis">
					<div class="port" style="left: 200px;" :key="1">
						Port 2
					</div>
        </teleport>
			</div>
		</teleport>
	</div>
	<div v-else>
		Mode 2
		<teleport to="#pop" :disabled="dis">
			<div class="port" :key="2">
				Port 3
				<teleport to="#pop" :disabled="dis">
					<div class="port" style="left: 200px;" :key="2">
						Port 4
					</div>
				</teleport>
			</div>
		</teleport>
	</div>
	<div>
		<input type="button" @click="mode = !mode" value="Change mode" /> <input type="button" @click="dis = !dis" value="Change disabled" />
	</div>
  <div>Click "Change mode" button multiple times, u can see a lot of "port2" and "port4", which is obviously not right.</div>
</div>
<div id="pop"></div>

I also don't think it has an issue with element re-use, I've written a new demo that doesn't involve v-if and v-else, and after clicking "Unmounted", only the first layer of teleport is destroyed.

The new link is: https://codepen.io/jsqy/pen/MWJqWLN

Examples written using v-if in the topic post are simply simplified problem reproduction, which is more complicated when combined with components, and the use of ":key"'s "workaround" does not solve the problem.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. has workaround A workaround has been found to avoid the problem 🐞 bug Something isn't working scope: teleport
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants