vue js. Удаление элемента из DOM дерева

Как правильно удалить элемент из dom дерева?

мой код:

    <template>
  <div class="cart" >
      
      <a class="a-cart" v-for="technics in cart" :key="technics.title">{{technics.title}}</a>
      <img class="img-cart"  v-for="technics in cart" :key="technics.img" :src="technics.img">
      <div class="counter">
      <button class="button-product-cart" @click="remove" v-for="technics in cart" :key="technics.name">Удалить товар</button>
      <button class="button-product-cart" @click="decrementV" v-for="technics in cart" :key="technics.price"> - </button>
      <a>{{counter}}</a>
      <button class="button-product-cart" @click="incrementV" v-for="technics in cart" :key="technics.id"> + </button>
      </div>
  </div>
</template>


<script>
export default {
  props:['product'],
  data(){
    return{
      counter: 0,
      cart: []
    }
  },
  methods:{
    remove(){
    this.counter = sessionStorage.getItem(`id: ${this.product.id}`)
      sessionStorage.removeItem(`id: ${this.product.id}`)
      this.$el
    },
    incrementV(){
      this.counter ++
      sessionStorage.setItem(`id: ${this.product.id}`, this.counter)
    },
    decrementV(){
      if(sessionStorage.getItem(`id: ${this.product.id}`) > 1){
        this.counter--
        sessionStorage.setItem(`id: ${this.product.id}`, this.counter)
      }else{
        this.counter = 1
        sessionStorage.setItem(`id: ${this.product.id}`, this.counter)
      }
    },
    resetV(){
      this.counter = 0
      sessionStorage.setItem(`id: ${this.product.id}`, this.counter)
    }
  },
  created(){
    this.counter = sessionStorage.getItem(`id: ${this.product.id}`)
    if(sessionStorage.getItem(`id: ${this.product.id}`)){
      this.cart.push(this.product)
      console.log(this.cart)
    }
  },
}
</script>

<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap');
.a-cart{color: black;padding: 20px 0px 20px 0px;font-family: 'Roboto', sans-serif;}
.cart{max-width: 1000px;display: flex;flex-direction: column;text-align: center;background: white;padding: 0px;}
.counter{max-width: 100%;display: flex;justify-content: flex-end;align-items: center;font-family: 'Roboto', sans-serif;}
.img-cart{max-width: 200px; padding: 0 40px;}
.button-product-cart{max-width: 100px;border: none;background: rgb(255, 255, 255);color: rgb(0, 0, 0);padding: 10px 20px;font-family: 'Roboto', sans-serif;}
</style>

Ответы (1 шт):

Автор решения: Vasiliy Rusin

Ответ несколько иной чем вы ожидаете. Вам не нужно удалять элемент из DOM. Vue это data-first фраемворк. Вы изменяете данные, Vue отрисовывает их.

Обратите внимание: Vue следит за DOM самостоятельно, Вы не должны изменять его без крайней необходимости.

В вашем случае всего лишь удалить значение из cart:

   this.cart = this.cart.filter(el => id !== this.product.id);

Хотелось бы так же добавить что Вам не стоить хранить данные в sessionStorage, храните их в Vuex и если Вам необходимо, сохраняйте состояние Vuex в sessionStorage. К тому же как я понимаю в cart всегда хранится одно значение, не совсем понятно зачем Вы в таком случае используете массив, возможно cart должен быть объектом?

Я бы переделал Ваш компонент так, хотя я не гарантирую что логика идентична.

<template>
    <div class="cart">
        <a class="a-cart">
            {{ cart.title }}
        </a>
        <img class="img-cart" :src="cart.img">
        <div class="counter">
            <button class="button-product-cart" @click="remove">
                Удалить товар
            </button>
            <button class="button-product-cart" @click="counter--">
                —
            </button>
            <a>
                {{counter}}
            </a>
            <button class="button-product-cart" @click="counter++">
                +
            </button>
        </div>
    </div>
</template>

<script>
  export default {
    props: {
      product: {
        type: Object,
        required: true
      }
    },

    data() {
      return {
        // используем локальное значение в компоненте
        counter_: 0,
        cart: {}
      }
    },

    computed: {
      counter: {
        // при зпросе компьютеда, отдаем локальное значание
        get() {
          return this.counter_
        },

        // при установке компьютеда, пишем локальное значение и в хранилище
        set(value) {
          this.counter_ = Math.max(1, value)

          sessionStorage.setItem(`id: ${this.product.id}`, this.counter_)
        }
      }
    },

    methods: {
      remove() {
        sessionStorage.removeItem(`id: ${this.product.id}`)

        this.cart = {}
      },

      resetV() {
        this.counter = 0
      }
    },

    created() {
      const sessionStorageValue = sessionStorage.getItem(`id: ${this.product.id}`)

      if (sessionStorageValue != null) {
        this.counter = parseInt(sessionStorageValue, 10)
        this.cart = this.product
      }
    }
  }
</script>

<style>
  @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap');
  .a-cart {
    color: black;
    padding: 20px 0px 20px 0px;
    font-family: 'Roboto', sans-serif;
  }
  
  .cart {
    max-width: 1000px;
    display: flex;
    flex-direction: column;
    text-align: center;
    background: white;
    padding: 0px;
  }
  
  .counter {
    max-width: 100%;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    font-family: 'Roboto', sans-serif;
  }
  
  .img-cart {
    max-width: 200px;
    padding: 0 40px;
  }
  
  .button-product-cart {
    max-width: 100px;
    border: none;
    background: rgb(255, 255, 255);
    color: rgb(0, 0, 0);
    padding: 10px 20px;
    font-family: 'Roboto', sans-serif;
  }
</style>

→ Ссылка