vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
45.58k stars 8k forks source link

Element Attribute is not deleted when you go to another page #11086

Open nonehub opened 3 weeks ago

nonehub commented 3 weeks ago

Vue version

3

Link to minimal reproduction

https://stackblitz.com/edit/github-bfob1d?file=src%2Fpages%2Fhome.vue

Steps to reproduce

There is something strange. It happens when I move from one page to another page that contains a specific component. Within this component, I give a data-Attribute element, and when I return to the first page and then return, I find that the Attribute has not been deleted.

Unlike usual, when you visit a page and, for example, give certain properties to HTML elements, after exiting the page I think they are deleted.

ex : You Have 2 Pages :

function go() { router.push('/about'); }

function setItem() { localStorage.setItem('set', 'set'); }

function removeItem() { localStorage.removeItem('set'); }

- `about.vue`
```vue
<script setup>
import TestComp from '../components/testComp.vue';

function getAttr() {
  if (document.querySelector('.notRemoveAttr').getAttribute('data-setData')) {
    alert('Attribute exists');
  } else {
    alert('Attribute Not exists!!');
  }
}
</script>

<template>
  <div>
    <h1>About Page</h1>
    <TestComp />
    <RouterLink to="/">To Home</RouterLink>
    <button @click="getAttr">getAttribute (data-setData)</button>
  </div>
</template>

in about page have testComp.vue :

<script setup>
import { ref, onMounted } from 'vue';
onMounted(() => {
  if (!localStorage.getItem('set')) {
    alert('Attribute Set Done !!');
    document
      .querySelector('.notRemoveAttr')
      ?.setAttribute('data-setData', 'hi');
  }
});
</script>

<template>
  <div>
    <div class="anyClass">
      <div class="anyClass2">
        <div class="anyClass3"></div>
        <div class="notRemoveAttr">
          <div class="anyClass4"></div>
        </div>
      </div>
    </div>
  </div>
</template>

Now when I go to the about page directly, everything is excellent, but when I go to the index page, then go to the about page, then return to the index page and put set in localStorage, then return to about, I find that the Attribute setData has not been deleted!

try it yourself, https://stackblitz.com/edit/github-bfob1d?file=src%2Fpages%2Fhome.vue 1 - open home page 2 - Go to the about page (click Button) (the element .notRemoveAttr will be given Attribute, which is data-setData) 3 - Go back to index (click Button) 4 - Click on (Local Storage Set) - so that .setAttribute('data-setData', 'hi') does not work when we return to the about page 5 - Go back to the about page (click on getAttribute (data-setData)) and you will find that it brings it to you!!

Make sure when you want to try again, click on Local Storage remove Set

What is expected?

I expect that when I leave the page and return to it, I find everything as if I had reloaded the page.

What is actually happening?

I gave an attribute element, but it is not deleted when you leave the page and return to it...

System Info

https://stackblitz.com/edit/github-bfob1d?file=src%2Fpages%2Fhome.vue

Any additional comments?

No response

LinusBorg commented 3 weeks ago

When you go from home back to about, the About component is mounted again, so it adds the attribute again. Works as you designed it to work.

1. Vue re-uses elements where it can, for performance reasons 3. Vue cannot track any DOM manipulation that you do imperatively through DOM APIs, anyway.

So as a consequence, it will reuse the div when switching the components, but not remove the attribute you added because it's not aware that it exists.

Solutions:

A: Remove the attribute yourself on unmount, or B: add it with Vue in the template instead of using DOM APIs yourself.

nonehub commented 3 weeks ago
  1. Vue re-uses elements where it can, for performance reasons
  2. Vue cannot track any DOM manipulation that you do imperatively through DOM APIs, anyway.

So as a consequence, it will reuse the div when switching the components, but not remove the attribute you added because it's not aware that it exists.

Solutions:

A: Remove the attribute yourself on unmount, or B: add it with Vue in the template instead of using DOM APIs yourself.

Isn't there anything automatic, is there a way to make it re-render

For example, a specific option.. I activate or deactivate it..

LinusBorg commented 3 weeks ago

See my edited comment, misunderstood your problem.

nonehub commented 3 weeks ago

When you go from home back to about, the About component is mounted again, so it adds the attribute again. Works as you designed it to work.

1. Vue re-uses elements where it can, for performance reasons 3. Vue cannot track any DOM manipulation that you do imperatively through DOM APIs, anyway.

So as a consequence, it will reuse the div when switching the components, but not remove the attribute you added because it's not aware that it exists.

Solutions:

A: Remove the attribute yourself on unmount, or B: add it with Vue in the template instead of using DOM APIs yourself.

No, it is not. I mentioned steps for you to try. Read them in the question at the end. The problem is, I set localeStorage so that it will not be executed again... Try that.

I mean how the same attribute is displayed, Also I am sure that the attribute is not put again if you put localeStorage

LinusBorg commented 3 weeks ago

I see. Seems to be related to Suspense. Removing that makes it work.