Vue optimization: common cause memory leaks and optimize memory leaks caused vue custom instructions to resolve

  If you develop applications using Vue, then we must be careful memory leak. This issue is particularly important in a one-page application (SPA), because the design of the SPA, the user is not required to use it to refresh your browser, so JavaScript applications need to clean up their own garbage collection components to ensure the entry into force in the expected way. Therefore vue in the development process, you need to be vigilant memory leak, these memory leaks tend to occur in the use of other than the tripartite Vue DOM library operations, ensure that the memory leak test applications and at the right time do the necessary components to clean up.

  Here is what I encountered in the development process, and check the memory leak information summary, we will continue to update

A, vue custom command element is bound to the event, but no unbundling event

  This problem see above blog post, VUE definition instruction from memory leaks caused solve

Two, v-if instruction generation memory leak

  v-if also a place prone to memory leaks. because:

  1, v-if bound to the value false, but in fact dom elements are hidden when there is no real freed

  2, is a very common example, we deleted the parent element by v-if, but did not remove the parent element in the dom fragments. Usually created when using third-party libraries, such as the following example, we have a selection box loaded with so many options, and then we use a show / hide button, through a  v-if  add instruction from the virtual DOM or remove it. The example of the problem is that this  v-if command will remove the parent element from the DOM, but we did not clear the DOM fragment from the Choices.js newly added, resulting in a memory leak.

<link rel="stylesheet prefetch" href="https://joshuajohnson.co.uk/Choices/assets/styles/css/choices.min.css?version=3.0.3">
<script src="https://joshuajohnson.co.uk/Choices/assets/scripts/dist/choices.min.js?version=3.0.3"></script>

<div id="app">
  <button v-if="showChoices" @click="hide">Hide</button>
  <button v-if="!showChoices" @click="show" >Show</button>
  <div v-if="showChoices">
    <select id="choices-single-default"></select>
  </div>
</div>
new new Vue ({ 
  EL: " #app " , 
  Data: function () { 
    return { 
      showChoices: to true 
    } 
  }, 
  Mounted: function () { 
    the this .initializeChoices () 
  }, 
  Methods: { 
    initializeChoices: function () { 
      the let List = []
       // we have to load a lot of options to select box
       // this is the case it will take up a lot of memory 
      for (the let i = 0 ; i < 1000 ; i ++ ) { 
        list.push ({ 
          label: " Item " + i,
          value: i
        })
      }
      new Choices("#choices-single-default", {
        searchEnabled: true,
        removeItemButton: true,
        choices: list
      })
    },
    show: function () {
      this.showChoices = true
      this.$nextTick(() => {
        this.initializeChoices()
      })
    },
    hide: function () {
      this.showChoices = false
    }
  }
})

  解决实例:在上述的示例中,我们可以用 hide() 方法在将选择框从 DOM 中移除之前做一些清理工作,来解决内存泄露问题。为了做到这一点,我们会在 Vue 实例的数据对象中保留一个属性,并会使用 Choices API 中的 destroy() 方法将其清除。

new Vue({
  el: "#app",
  data: function () {
    return {
      showChoices: true,
      choicesSelect: null
    }
  },
  mounted: function () {
    this.initializeChoices()
  },
  methods: {
    initializeChoices: function () {
      let list = []
      for (let i = 0; i < 1000; i++) {
        list.push({
          label: "Item " + i,
          value: i
        })
      }
      // 在我们的 Vue 实例的数据对象中设置一个 `choicesSelect` 的引用
      this.choicesSelect = new Choices("#choices-single-default", {
        searchEnabled: true,
        removeItemButton: true,
        choices: list
      })
    },
    show: function () {
      this.showChoices = true
      this.$nextTick(() => {
        this.initializeChoices()
      })
    },
    hide: function () {
      // 现在我们可以让 Choices 使用这个引用
      // 在从 DOM 中移除这些元素之前进行清理工作
      this.choicesSelect.destroy()
      this.showChoices = false
    }
  }
})

三、vue-router跳转到别的组件导致的内容泄漏

  在上述示例中,我们使用了一个 v-if 指令产生内存泄漏,但是一个更常见的实际的场景是使用 Vue Router 在一个单页应用中路由到不同的组件。

  就像这个 v-if 指令一样,当一个用户在你的应用中导航时,Vue Router 从虚拟 DOM 中移除了元素,并替换为了新的元素。但是其子元素dom片段也并没有销毁。

  Vue 的 beforeDestroy() 生命周期钩子是一个解决基于 Vue Router 的应用中的这类问题的好方法。我们可以将清理工作放入 beforeDestroy() 钩子,像这样:

beforeDestroy: function () {
  this.choicesSelect.destroy()
}

  所以最正确的解决方案就是:首先,v-if置为false前先删除创建的dom片段;其次,路由跳出吃,在beforeDestroy钩子函数里面判断choicesSelect是否销毁,没销毁则销毁。

  还有一个替代方案

  我们已经讨论了移除元素时的内存管理,但是如果你打算在内存中保留状态和元素该怎么做呢?这种情况下,你可以使用内建的 keep-alive 组件。

  当你用 keep-alive 包裹一个组件后,它的状态就会保留,因此就留在了内存里。

<button @click="show = false">Hide</button>
<keep-alive>
    // <my-component> 即便被删除仍会刻意保留在内存里
    <my-component v-if="show"></my-component>
</keep-alive>

  这个技巧可以用来提升用户体验。例如,设想一个用户在一个文本框中输入了评论,之后决定导航离开。如果这个用户之后导航回来,那些评论应该还保留着。

  一旦你使用了 keep-alive,那么你就可以访问另外两个生命周期钩子:activated和 deactivated。如果你想要在一个 keep-alive 组件被移除的时候进行清理或改变数据,可以使用 deactivated 钩子。

deactivated: function () {
  // 移除任何你不想保留的数据,或者销毁可能产生内存泄漏的地方
}

 

Guess you like

Origin www.cnblogs.com/goloving/p/11267124.html