Vue - 组件重新渲染的两种方式

Vue - 组件重新渲染的两种方式

一. 组件上进行 key 值更改

最简单,推荐使用

  • Vue是通过diffing算法比较虚拟DOM和真实DOM,来判断新旧 DOM 的变化。key是虚拟DOM对象的标识,在更新显示时key表示着DOM的唯一性。
  • DOM是否变化的核心是通过判断新旧DOM的key值是否变化,如果key发生改变,则重新渲染该DOM,如果key没变,则不会重新DOM。

如果想让组件重新渲染,只需要给组件加上key属性,然后在需要重新渲染的时候,将组件绑定的key值更改就可以。

父组件:

<template>
  <div class="home">
    <h2>父组件</h2>
    <button @click="rerender">改变组件绑定的key值,重新渲染组件</button>
    <div class="item" v-for="(item, index) of 3" :key="index">
      <child :id="item" :key="key"></child>
    </div>
  </div>
</template>

<script>
import Child from "./child.vue";
export default {
  components: {
    Child
  },
  data() {
    return {
      key: Date.now()
    };
  },
  methods: {
    rerender() {
      this.key = Date.now();
    }
  }
};
</script>

<style scoped>
.home {
  padding: 20px;
  box-sizing: border-box;
}
.item {
  background: #e2e2e2;
  padding: 10px;
  margin: 10px 0;
  box-sizing: border-box;
}
</style>

子组件:

<template>
  <div>子组件</div>
</template>

<script>
export default {
  props: ["id"],
  data() {
    return {};
  },
  mounted() {
    this.getDataById();
  },
  methods: {
    getDataById() {
      console.log("子组件方法执行了,获取父组件的id:" + this.id);
    }
  }
};
</script>

二. v-if 指令

  • 当DOM设置为false的时候,当前条件块中的DOM会被销毁。如果条件块包含的是组件,则组件对应的生命周期函数(beforeDestroydestroyed等)会执行。
  • 当DOM设置为true的时候,当前条件块中的DOM会被重建。如果条件块包含的是组件,则组件对应的生命周期函数(createdmounted等),计算属性,watch等都会执行,相当于重新渲染。

父组件:

<template>
  <div class="home">
    <h2>父组件</h2>
    <button @click="rerender">改变组件v-if的值,重新渲染组件</button>
    <div class="item" v-for="(item, index) of 3" :key="index">
      <child :id="item" v-if="isShow"></child>
    </div>
  </div>
</template>

<script>
import Child from "./child.vue";
export default {
  components: {
    Child
  },
  data() {
    return {
      isShow: true
    };
  },
  methods: {
    rerender() {
      // 从 DOM 中删除 child 组件
      this.isShow = false;
      this.$nextTick(() => {
        // 在 DOM 中添加 child 组件
        this.isShow = true;
      });
    }
  }
};
</script>

<style scoped>
.home {
  padding: 20px;
  box-sizing: border-box;
}
.item {
  background: #e2e2e2;
  padding: 10px;
  margin: 10px 0;
  box-sizing: border-box;
}
</style>

子组件:

<template>
  <div>子组件</div>
</template>

<script>
export default {
  props: ["id"],
  data() {
    return {};
  },
  mounted() {
    this.getDataById();
  },
  methods: {
    getDataById() {
      console.log("子组件方法执行了,获取父组件的id:" + this.id);
    }
  },
};
</script>