Nueve consejos de optimización del rendimiento para Vue.js

1, componentes funcionales

Para el primer truco, componentes funcionales, puede consultar este ejemplo en vivo .

El código del componente antes de la optimización es el siguiente:

<template>
  <div class="cell">
    <div v-if="value" class="on"></div>
    <section v-else class="off"></section>
  </div>
</template>

<script>
export default {
  props: ['value'],
}
</script>

El código del componente optimizado es el siguiente:

<template functional>
  <div class="cell">
    <div v-if="props.value" class="on"></div>
    <section v-else class="off"></section>
  </div>
</template>

Luego, renderizamos 800 componentes antes y después de la optimización en cada componente principal y activamos las actualizaciones de los componentes modificando los datos dentro de cada marco, abrimos el panel Rendimiento de Chrome para registrar su rendimiento y obtenemos los siguientes resultados.

Antes de la optimización:

Optimizado:

Al comparar estas dos cifras, podemos ver que el tiempo scriptde ejecución es más largo que después de la optimización, y sabemos que el motor JS es un mecanismo operativo de un solo subproceso, y el subproceso JS bloqueará el subproceso de la interfaz de usuario, por lo que cuando el script el tiempo de ejecución es demasiado largo, bloqueará el procesamiento y la página se congelará. Y el tiempo scriptde ejecución es corto, por lo que su rendimiento es mejor.

Entonces, ¿por qué el tiempo de ejecución es más corto con el componente funcional JS? Esto comienza con el principio de implementación de los componentes funcionales. Puede entenderlo como una función que puede representar y generar una parte de DOM de acuerdo con los datos de contexto que pasa.

Los componentes funcionales son diferentes de los componentes ordinarios de tipo objeto. No se considerarán como un componente real. Sabemos que en patchel proceso si un nodo es un componente vnode, ejecutará recursivamente el proceso de inicialización de los subcomponentes; mientras que los componentes funcionales Lo rendergenerado es normal vnode, no habrá proceso de subcomponentes recursivos, por lo que la sobrecarga de representación será mucho menor.

Por lo tanto, los componentes funcionales tampoco tendrán estado, datos de respuesta y funciones de enlace de ciclo de vida. Puede pensar en ello como quitar parte del DOM de la plantilla de componente común y representarlo a través de una función, que es una especie de reutilización a nivel de DOM.

2, división de componentes secundarios

Para el segundo truco, la división de subcomponentes, puede consultar este ejemplo en línea .

El código del componente antes de la optimización es el siguiente:

<template>
  <div :style="{ opacity: number / 300 }">
    <div>{
   
   { heavy() }}</div>
  </div>
</template>

<script>
export default {
  props: ['number'],
  methods: {
    heavy () {
      const n = 100000
      let result = 0
      for (let i = 0; i < n; i++) {
        result += Math.sqrt(Math.cos(Math.sin(42)))
      }
      return result
    }
  }
}
</script>

El código del componente optimizado es el siguiente:

<template>
  <div :style="{ opacity: number / 300 }">
    <ChildComp/>
  </div>
</template>

<script>
export default {
  components: {
    ChildComp: {
      methods: {
        heavy () {
          const n = 100000
          let result = 0
          for (let i = 0; i < n; i++) {
            result += Math.sqrt(Math.cos(Math.sin(42)))
          }
          return result
        },
      },
      render (h) {
        return h('div', this.heavy())
      }
    }
  },
  props: ['number']
}
</script>

Luego, renderizamos 300 componentes antes y después de la optimización en cada componente principal y activamos las actualizaciones de los componentes modificando los datos dentro de cada marco, abrimos el panel Rendimiento de Chrome para registrar su rendimiento y obtenemos los siguientes resultados.

Antes de la optimización:

Optimizado:

Comparando estas dos cifras, podemos ver que el tiempo scriptde ejecución es significativamente menor que antes de la optimización, por lo que la experiencia de rendimiento es mejor.

Entonces, ¿por qué hay una diferencia? Veamos el componente antes de la optimización. El ejemplo simula una tarea que requiere mucho tiempo a través de una heavyfunción , y esta función se ejecutará cada vez que se renderice, por lo que cada renderizado del componente consumirá mucho tiempo. hora de ejecutar JavaScript.

La forma optimizada heavyes ChildCompencapsular la lógica de ejecución de esta función de tarea que consume mucho tiempo con subcomponentes. Dado que la actualización de Vue se realiza en la granularidad de los componentes, aunque cada cuadro provocará la re-renderización del componente principal a través de la modificación de datos ChildComp, se vuelve a renderizar porque tampoco tiene ningún cambio de datos de respuesta interna. Por lo tanto, el componente optimizado no realizará tareas que consumen mucho tiempo cada vez que se renderice y, naturalmente, se reducirá el tiempo de ejecución de JavaScript.

Sin embargo, he presentado algunas opiniones diferentes sobre este método de optimización. Para más detalles, puede hacer clic en este problema . Creo que calcular las propiedades para la optimización en este escenario es mejor que dividir los subcomponentes. Gracias a la función de almacenamiento en caché de las propiedades calculadas, la lógica que consume mucho tiempo solo se ejecutará en la primera representación, y no hay sobrecarga adicional para la representación de subcomponentes cuando se utilizan propiedades calculadas.

En el trabajo real, hay muchos escenarios donde las propiedades informáticas se utilizan para optimizar el rendimiento.Después de todo, también refleja una idea de optimización de intercambiar espacio por tiempo.

3, Variables locales

El tercer truco, las variables locales, puede consultar este ejemplo en línea .

El código del componente antes de la optimización es el siguiente:

<template>
  <div :style="{ opacity: start / 300 }">{
   
   { result }}</div>
</template>

<script>
export default {
  props: ['start'],
  computed: {
    base () {
      return 42
    },
    result () {
      let result = this.start
      for (let i = 0; i < 1000; i++) {
        result += Math.sqrt(Math.cos(Math.sin(this.base))) + this.base * this.base + this.base + this.base * 2 + this.base * 3
      }
      return result
    },
  },
}
</script>

El código del componente optimizado es el siguiente:

<template>
  <div :style="{ opacity: start / 300 }">{
   
   { result }}</div>
</template>

<script>
export default {
  props: ['start'],
  computed: {
    base () {
      return 42
    },
    result ({ base, start }) {
      let result = start
      for (let i = 0; i < 1000; i++) {
        result += Math.sqrt(Math.cos(Math.sin(base))) + base * base + base + base * 2 + base * 3
      }
      return result
    },
  },
}
</script>

Luego, renderizamos 300 componentes antes y después de la optimización en cada componente principal y activamos las actualizaciones de los componentes modificando los datos dentro de cada marco, abrimos el panel Rendimiento de Chrome para registrar su rendimiento y obtenemos los siguientes resultados.

Antes de la optimización:

Optimizado:

Comparando estas dos cifras, podemos ver que el tiempo scriptde ejecución es significativamente menor que antes de la optimización, por lo que la experiencia de rendimiento es mejor.

Esto se debe principalmente a la diferencia en la implementación resultde . Se accede muchas veces a los componentes antes de la optimización durante el proceso de cálculo this.base, mientras que los componentes optimizados utilizarán variables locales antes del cálculo base, caché this.basey luego acceder directamente a ellos más tarde base.

Entonces, ¿por qué esta diferencia causa una diferencia en el rendimiento? La razón es que cada vez que this.basevisita , dado que this.basees un objeto receptivo, se activará gettery luego se ejecutará el código lógico relacionado con la recopilación de dependencias. Si se ejecuta demasiada lógica similar, como en el ejemplo, cientos de ciclos actualizan cientos de componentes, cada componente activa computedel recálculo y luego ejecuta la lógica relacionada con la recopilación de dependencias varias veces, el rendimiento caerá naturalmente.

En términos de requisitos, this.basebasta con ejecutar la recopilación de dependencias una vez y devolver su resultado getterde evaluación a una variable local. No se activará cuando se vuelvabase a acceder más tarde, y no se seguirá la lógica de la recopilación de dependencias, y el rendimiento naturalmente se mejorará. .basegetter

Esta es una técnica de optimización del rendimiento muy útil. Porque cuando muchas personas desarrollan proyectos Vue.js, habitualmente this.xxxescriben , porque la mayoría de la gente no se da cuenta this.xxxde lo que se hace detrás del acceso. Cuando la cantidad de visitas es pequeña, el problema de rendimiento no es importante, pero una vez que aumenta la cantidad de visitas, como varias visitas en un bucle grande, similar al escenario de ejemplo, se producirán problemas de rendimiento.

Cuando estaba optimizando el rendimiento del componente Table de ZoomUI, render table bodyutilicé técnicas de optimización de variables locales y escribí un punto de referencia para la comparación del rendimiento: al renderizar una tabla de 1000 * 10, el rendimiento de volver a renderizar los datos actualizados de la tabla de ZoomUI debería ser Ha casi duplicó el rendimiento de la tabla de ElementUI.

4、Reutilizar DOM con v-show

El cuarto truco, usando v-showReuse DOM, puede consultar este ejemplo en línea .

El código del componente antes de la optimización es el siguiente:

<template functional>
  <div class="cell">
    <div v-if="props.value" class="on">
      <Heavy :n="10000"/>
    </div>
    <section v-else class="off">
      <Heavy :n="10000"/>
    </section>
  </div>
</template>

El código del componente optimizado es el siguiente:

<template functional>
  <div class="cell">
    <div v-show="props.value" class="on">
      <Heavy :n="10000"/>
    </div>
    <section v-show="!props.value" class="off">
      <Heavy :n="10000"/>
    </section>
  </div>
</template>

Luego, renderizamos 200 componentes antes y después de la optimización en cada componente principal y activamos las actualizaciones de los componentes modificando los datos dentro de cada marco, y abrimos el panel Rendimiento de Chrome para registrar su rendimiento y obtener los siguientes resultados.

Antes de la optimización:

Optimizado:

Comparando estas dos cifras, podemos ver que el tiempo scriptde ejecución es significativamente menor que antes de la optimización, por lo que la experiencia de rendimiento es mejor.

La principal diferencia antes y después de la optimización es que v-showel comando en lugar v-ifdel comando para reemplazar la claridad del componente. Aunque es similarv-show en términos de rendimiento, controla la claridad del componente, pero todavía hay una gran brecha. en la implementación interna.v-if

v-ifLas instrucciones se compilarán en un operador ternario y una representación condicional durante la fase de compilación. Por ejemplo, la plantilla del componente antes de la optimización se compila para generar la siguiente función de representación:

function render() {
  with(this) {
    return _c('div', {
      staticClass: "cell"
    }, [(props.value) ? _c('div', {
      staticClass: "on"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1) : _c('section', {
      staticClass: "off"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1)])
  }
}

Cuando el valor props.valuede cambia, activará la actualización del componente correspondiente. Para v-ifel nodo renderizado, debido a que los nodos antiguo y nuevo vnodeson inconsistentes , durante el proceso de comparación del algoritmo de diferencia central, el vnodenodo antiguo se eliminará y se se creará un nuevo vnodenodo El nuevo Heavycomponente pasará por el proceso de Heavyinicialización del componente, renderizado vnode, patchetc.

Por lo tanto, v-ifcada vez que se actualice un componente, Heavyse creará un nuevo subcomponente. Cuando hay muchos componentes actualizados, naturalmente causará presión en el rendimiento.

Y cuando usamos v-showla directiva , la plantilla del componente optimizado se compila para generar la siguiente función de representación:

function render() {
  with(this) {
    return _c('div', {
      staticClass: "cell"
    }, [_c('div', {
      directives: [{
        name: "show",
        rawName: "v-show",
        value: (props.value),
        expression: "props.value"
      }],
      staticClass: "on"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1), _c('section', {
      directives: [{
        name: "show",
        rawName: "v-show",
        value: (!props.value),
        expression: "!props.value"
      }],
      staticClass: "off"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1)])
  }
}

Cuando el valor props.valuede cambia, activará la actualización del componente correspondiente. Para v-showlos nodos renderizados, dado que el antiguo y el nuevo vnodeson consistentes , solo necesitan patchVnodeserlo todo el tiempo. Entonces, ¿cómo hace que se muestren los nodos DOM? y ocultar?

Resulta que en patchVnodeel proceso , v-showla función de enlace correspondiente a la instrucción se ejecutará internamente update, y luego v-showestablecerá style.displayel valor del elemento DOM sobre el que actúa para controlar la visualización y la ocultación de acuerdo con el valor vinculado por la instrucción.

Por lo tanto, en comparación con la eliminación v-ifconstante y la creación de nuevas funciones DOM, v-showsolo actualiza los valores explícitos e implícitos del DOM existente, por lo que v-showla sobrecarga v-ifde es mucho menor que la de , y cuanto más compleja es la estructura DOM interna, mayor. la diferencia de rendimiento será.

Pero v-showen comparación con v-ifla ventaja de rendimiento de está en la fase de actualización del componente, si solo está en la fase de inicialización, v-ifel rendimiento es mayor que v-showeso, porque solo representa una rama, v-showrepresenta ambas ramas y style.displaycontrola la correspondencia a través de The visibilidad del DOM.

Al v-showusar , se renderizarán todos los componentes internos de la rama y v-ifse ejecutarán las funciones de enlace del ciclo de vida correspondientes, mientras que al usar , los componentes dentro de la rama no afectada no se renderizarán y las funciones de enlace del ciclo de vida correspondientes no se ejecutarán .

Por lo tanto, debe comprender sus principios y diferencias para utilizar las instrucciones adecuadas en diferentes escenarios.

5, mantener vivo

El quinto truco, usar KeepAlivecomponentes para almacenar en caché el DOM, puede consultar este ejemplo en línea .

El código del componente antes de la optimización es el siguiente:

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

El código del componente optimizado es el siguiente:

<template>
  <div id="app">
    <keep-alive>
      <router-view/>
    </keep-alive>
  </div>
</template>

Cuando hacemos clic en el botón para cambiar entre la página simple y la página pesada, se renderizarán diferentes vistas, y la renderización de la página pesada requiere mucho tiempo. Abrimos el panel Rendimiento de Chrome para registrar su rendimiento y luego realizamos las operaciones anteriores antes y después de la optimización, y obtendremos los siguientes resultados.

Antes de la optimización:

Optimizado:

Comparando estas dos cifras, podemos ver que el tiempo scriptde ejecución es significativamente menor que antes de la optimización, por lo que la experiencia de rendimiento es mejor.

En el escenario no optimizado, cada vez que hagamos clic en el botón para cambiar la vista de enrutamiento, el componente se volverá a procesar y el componente procesado pasará por la inicialización del componente y otros procesos. Si el componente es más rendercomplicado patcho anidado profundamente, todo el tiempo de renderizado se reducirá será muy largo.

KeepAliveDespués de usar , KeepAlivedespués de la primera representación del componente envuelto, vnodeel DOM se almacenará en caché, y luego, cuando el componente se vuelva a representar la próxima vez, el vnodeDOM correspondiente se obtendrá directamente del caché y luego se procesará. No es necesario. pasar por una serie de procesos como la inicialización de componentes render, patchetc. , lo que reduce scriptel tiempo de ejecución y mejora el rendimiento.

Pero el uso KeepAlivede componentes no está libre de costos, ya que requerirá más memoria para el almacenamiento en caché, que es una aplicación típica de las ideas de optimización de espacio por tiempo.

6, Funciones diferidas

La sexta técnica, usar Deferredcomponentes para renderizar componentes en lotes de manera retrasada, puede consultar este ejemplo en línea .

El código del componente antes de la optimización es el siguiente:

<template>
  <div class="deferred-off">
    <VueIcon icon="fitness_center" class="gigantic"/>

    <h2>I'm an heavy page</h2>

    <Heavy v-for="n in 8" :key="n"/>

    <Heavy class="super-heavy" :n="9999999"/>
  </div>
</template>

El código del componente optimizado es el siguiente:

<template>
  <div class="deferred-on">
    <VueIcon icon="fitness_center" class="gigantic"/>

    <h2>I'm an heavy page</h2>

    <template v-if="defer(2)">
      <Heavy v-for="n in 8" :key="n"/>
    </template>

    <Heavy v-if="defer(3)" class="super-heavy" :n="9999999"/>
  </div>
</template>

<script>
import Defer from '@/mixins/Defer'

export default {
  mixins: [
    Defer(),
  ],
}
</script>

Cuando hacemos clic en el botón para cambiar entre la página simple y la página pesada, se renderizarán diferentes vistas, y la renderización de la página pesada requiere mucho tiempo. Abrimos el panel Rendimiento de Chrome para registrar su rendimiento y luego realizamos las operaciones anteriores antes y después de la optimización, y obtendremos los siguientes resultados.

Antes de la optimización:

Optimizado:

Al comparar estas dos imágenes, podemos encontrar que cuando cambiamos de Página simple a Página pesada antes de la optimización, cuando un Render está cerca del final, la página aún se muestra como Página simple, lo que dará a las personas una sensación de congelación de página. Después de la optimización, cuando cambiamos de la página simple a la página pesada, la página pesada ya se ha renderizado una vez al frente del renderizado, y la página pesada se renderiza progresivamente.

La diferencia antes y después de la optimización se debe principalmente a que esta última usa Deferthis mixin, entonces, ¿cómo funciona? Averigüemos:

export default function (count = 10) {
  return {
    data () {
      return {
        displayPriority: 0
      }
    },

    mounted () {
      this.runDisplayPriority()
    },

    methods: {
      runDisplayPriority () {
        const step = () => {
          requestAnimationFrame(() => {
            this.displayPriority++
            if (this.displayPriority < count) {
              step()
            }
          })
        }
        step()
      },

      defer (priority) {
        return this.displayPriority >= priority
      }
    }
  }
}

DeferLa idea principal de es dividir una renderización de un componente en varias veces. Mantiene displayPrioritylas variables y luego requestAnimationFramese incrementa al renderizar cada cuadro, hasta count. Luego Defer mixinuse el interior del componente v-if="defer(xxx)"para displayPrioritycontrolar xxxla representación de ciertos bloques cuando se agreguen a .

Cuando tiene componentes que tardan en renderizarse, es una buena idea Deferredutilizar el renderizado progresivo para evitar renderque el renderizado se atasque debido al largo tiempo de ejecución de JS.

7, división de tiempo

La séptima técnica, utilizando Time slicingla técnica de corte de tiempo , puede consultar este ejemplo en línea .

El código antes de la optimización es el siguiente:

fetchItems ({ commit }, { items }) {
  commit('clearItems')
  commit('addItems', items)
}

El código optimizado es el siguiente:

fetchItems ({ commit }, { items, splitCount }) {
  commit('clearItems')
  const queue = new JobQueue()
  splitArray(items, splitCount).forEach(
    chunk => queue.addJob(done => {
      // 分时间片提交数据
      requestAnimationFrame(() => {
        commit('addItems', chunk)
        done()
      })
    })
  )
  await queue.start()
}

Primero creamos 10,000 piezas de datos falsos haciendo clic Genterate itemsen el botón y luego Time-slicinghacemos clic en Commit itemsel botón para enviar los datos cuando se enciende y apaga, y abrimos el panel Rendimiento de Chrome para registrar su rendimiento, y se obtendrán los siguientes resultados.

Antes de la optimización:

Optimizado:

Al comparar estas dos cifras, podemos encontrar que el scripttiempo total de ejecución antes de la optimización es menor que después de la optimización, pero desde la apariencia real, haga clic en el botón Enviar antes de la optimización, la página se congelará durante aproximadamente 1,2 segundos, después de la optimización, el la página no se atascará por completo, pero aún habrá una sensación de retraso en el procesamiento.

Entonces, ¿por qué la página se bloquea antes de la optimización? Debido a que se envían demasiados datos a la vez, el tiempo de ejecución interno de JS es demasiado largo, lo que bloquea el subproceso de la interfaz de usuario y hace que la página se congele.

Después de la optimización, la página aún se congela porque la granularidad de los datos que dividimos es 1000. En este caso, todavía hay presión para volver a renderizar el componente. Observamos que los fps son solo una docena, y habrá una sensación de congelar. Por lo general, siempre que los fps de la página alcancen los 60, la página será muy fluida. Si cambiamos la granularidad de división de datos a 100, básicamente los fps pueden llegar a más de 50. Aunque la representación de la página se vuelve más fluida, el envío total de Se han completado 10.000 datos. El tiempo sigue siendo más largo.

El uso Time slicing de la tecnología puede evitar que la página se atasque, por lo general agregaremos un efecto de carga al procesar esta tarea que requiere mucho tiempo, en este ejemplo, podemos abrirla loading animationy luego enviar los datos. La comparación encontró que antes de la optimización, debido a que se enviaron demasiados datos a la vez, JS se ha estado ejecutando durante mucho tiempo, bloqueando el subproceso de la interfaz de usuario, esta animación de carga no se mostrará, pero después de la optimización, porque la dividimos en varias veces cortes para enviar datos, un solo El tiempo de ejecución de JS se acorta para que la animación de carga tenga la oportunidad de mostrarse.

Una cosa a tener en cuenta aquí es que, aunque usamos requestAnimationFramela API para dividir el intervalo de tiempo, el uso requestAnimationFrameen sí mismo no puede garantizar el funcionamiento de fotograma completo. requestAnimationFrameLo que se garantiza es que la función de devolución de llamada entrante correspondiente se ejecutará después de cada redibujado del navegador. Si quiere asegurarse de que los marcos completos solo puedan hacer que el tiempo de ejecución de JS dentro de un Tick no supere los 17 ms.

8, datos no reactivos

El octavo consejo, utilizando datos Non-reactive dataque no responden, puede consultar este ejemplo en línea .

El código antes de la optimización es el siguiente:

const data = items.map(
  item => ({
    id: uid++,
    data: item,
    vote: 0
  })
)

El código optimizado es el siguiente:

const data = items.map(
  item => optimizeItem(item)
)

function optimizeItem (item) {
  const itemData = {
    id: uid++,
    vote: 0
  }
  Object.defineProperty(itemData, 'data', {
    // Mark as non-reactive
    configurable: false,
    value: item
  })
  return itemData
}

Aún en el ejemplo anterior, primero creamos 10,000 piezas de datos falsos haciendo clic Genterate itemsen el botón y luego Partial reactivityhacemos clic en Commit itemsel botón encendido y apagado respectivamente, y abrimos el panel Rendimiento de Chrome para registrar su rendimiento, y los siguientes resultados serán Ser obtenido.

Antes de la optimización:

Optimizado:

Comparando estas dos cifras, podemos ver que el tiempo scriptde ejecución es significativamente menor que antes de la optimización, por lo que la experiencia de rendimiento es mejor.

El motivo de esta diferencia es que cuando los datos se envían internamente, los nuevos datos enviados también se definirán como sensibles de forma predeterminada.Si el subatributo de los datos tiene la forma de un objeto, recursivamente hará que el sub- El atributo también se vuelve receptivo. Por lo tanto, al enviar una gran cantidad de datos, este proceso se convierte en un proceso que consume mucho tiempo.

Después de la optimización, cambiamos datamanualmente configurablepara que sea , de modo que la matriz de atributos del objeto obtenida falseinternamente walkhasta cuándo se ignorará y no será este atributo , porque apunta a un objeto, por lo que también será be Reducir la lógica de la capacidad de respuesta recursiva es equivalente a reducir la pérdida de rendimiento de esta parte. Cuanto mayor sea la cantidad de datos, más evidente será el efecto de esta optimización.Object.keys(obj)datadatadefineReactivedata

De hecho, hay muchos otros métodos de optimización como este, por ejemplo, algunos datos que definimos en componentes pueden no estar necesariamente definidos dataen . No usamos algunos datos en la plantilla, y no necesitamos monitorear sus cambios. Solo queremos compartir estos datos en el contexto del componente. En este momento, solo podemos montar los datos thisen

export default {
  created() {
    this.scroll = null
  },
  mounted() {
    this.scroll = new BScroll(this.$el)
  }
}

De esta manera podemos compartir scrollel objeto , aunque no sea un objeto reactivo.

9, Desplazamiento virtual

Para el noveno consejo, utilizando el componente de desplazamiento Virtual scrollingvirtual , puede consultar este ejemplo en vivo .

El código del componente antes de la optimización es el siguiente:

<div class="items no-v">
  <FetchItemViewFunctional
    v-for="item of items"
    :key="item.id"
    :item="item"
    @vote="voteItem(item)"
  />
</div>

El código optimizado es el siguiente:

<recycle-scroller
  class="items"
  :items="items"
  :item-size="24"
>
  <template v-slot="{ item }">
    <FetchItemView
      :item="item"
      @vote="voteItem(item)"
    />
  </template>
</recycle-scroller>

Aún en el ejemplo anterior, debemos abrirlo View listy luego hacer clic en Genterate itemsel botón para crear 10000 datos falsos (tenga en cuenta que el ejemplo en línea solo puede crear hasta 1000 datos, de hecho, 1000 datos no reflejan bien el efecto de optimización, así que Se modificó la limitación del código fuente, se ejecutó localmente, se crearon 10 000 piezas de datos y Unoptimizedluego RecycleScrollerhizo clic en Commit itemsel botón para enviar los datos y, respectivamente, se desplazó por la página, se abrió el panel Rendimiento de Chrome para registrar su rendimiento y se obtendrán los siguientes resultados.

Antes de la optimización:

Optimizado:

Al comparar estas dos imágenes, encontramos que en el caso de no optimización, los fps de 10,000 piezas de datos son solo dígitos individuales en el caso de desplazamiento, y solo una docena en el caso de no desplazamiento. hay demasiados DOM renderizados en la escena no optimizada. La presión en sí es muy alta. Después de la optimización, incluso con 10.000 datos, los fps pueden ser más de 30 en el caso de desplazamiento y pueden llegar a 60 fotogramas completos en el caso de no rodar.

El motivo de esta diferencia es que la implementación del desplazamiento virtual es solo para renderizar el DOM en la ventana gráfica, de modo que la cantidad total de DOM renderizado es muy pequeña y el rendimiento natural será mucho mejor.

El componente de desplazamiento virtual también está escrito por Guillaume Chau , los estudiantes interesados ​​pueden estudiar su implementación de código fuente . Su principio básico es monitorear eventos de desplazamiento, actualizar dinámicamente los elementos DOM que se mostrarán y calcular su desplazamiento en la vista.

El componente de desplazamiento virtual no está exento de costes, ya que debe calcularse en tiempo real durante el proceso de desplazamiento, por lo que habrá un cierto coste scriptde ejecución . Por lo tanto, si la cantidad de datos en la lista no es muy grande, nos basta con usar el desplazamiento ordinario.

Resumir

A través de este artículo, espero que pueda comprender las nueve técnicas de optimización del rendimiento de Vue.js y aplicarlas a proyectos de desarrollo reales. Además de las técnicas anteriores, también existen métodos de optimización del rendimiento de uso común, como la carga diferida de imágenes, la carga diferida de componentes y los componentes asincrónicos.

Antes de realizar la optimización del rendimiento, debemos analizar dónde está el cuello de botella del rendimiento para que podamos adaptarnos a las condiciones locales. Además, la optimización del rendimiento requiere soporte de datos. Antes de realizar cualquier optimización del rendimiento, debe recopilar los datos antes de la optimización, de modo que pueda ver el efecto de la optimización a través de la comparación de datos después de la optimización.

Espero que en el proceso de desarrollo futuro, no solo esté satisfecho con los requisitos de implementación, sino que también piense en el impacto que puede tener en el rendimiento al escribir cada línea de código.

Este artículo se publicó por primera vez en la cuenta pública "Cocina privada frontal de Lao Huang" , bienvenido a prestar atención.

Autor: Huang Yi
Enlace: https://juejin.cn/post/6922641008106668045
Fuente: Rare Earth Nuggets
Los derechos de autor pertenecen al autor. Para reimpresión comercial, comuníquese con el autor para obtener autorización, para reimpresión no comercial, indique la fuente.

Supongo que te gusta

Origin blog.csdn.net/maxue20161025/article/details/128100068
Recomendado
Clasificación