Как правильно лениво загрузить файл json в Vue. js, чтобы уменьшить размер пакета? - PullRequest
0 голосов
/ 10 февраля 2020

Я использую Vue. js и Laravel для своего проекта и недавно добавил две анимации, используя плагин с именем Lott ie. Каждая анимация является компонентом, и они оба используют отдельный файл JSON для анимации группы изображений PNG (аналогично последовательности PNG). Эти два JSON файла хранятся локально в папке проекта по пути / public / data / .

. Во-первых, файлы JSON не читаются, пока я не введу абсолютную путь ( / users / username / documents / projectname / public / data / filename. json), нет ли способа заставить это работать, просто используя / data / filename. json?

Во-вторых, когда я добавляю приведенный ниже код в свой компонент, мои JS файлы компилируются в отдельные фрагменты, как и ожидалось:

const animationData = () =>
  import("/users/username/documents/projectname/public/data/filename.json");

Я получаю следующее ошибка при попытке запуска анимации:

Invalid prop: type check failed for prop "data". Expected Object, got Function 

found in

---> <VueLottie>

Однако, когда я импортирую свой файл json, используя обычный импорт в моем компоненте, как показано ниже, он работает нормально и показывает анимацию:

import animationData from "/users/username/documents/projectname/public/data/filename.json";

Мои компоненты анимации настроены так:

<template>
        <vue-lottie ref="lottie" loop autoplay :data="animationData" :height="400" :width="400"></vue-lottie>
</template>

<script>
    import vueLottie from "vue-lottie-ssr";
    import animationData from '/users/username/documents/projectname/public/data/filename.json'

    export default {
        name: 'animation',
        components: {
            vueLottie
        },
        data () {
            return {
                speed: 1,
                animationData
            }
        },
        computed: {
            lottie () {
                return this.$refs.lottie
            }
        }

    }
</script>

Я также пытался получить файл JSON через вызов ax ios, когда компонент монтируется, но возникает та же ошибка.

Обновление

Я обновил свой код, чтобы каждый компонент Вместо файла JSON загружается ленивый файл. Вот так:

components: {
  WinAnimation: () => import("./WinAnimation.vue");

  LoseAnimation: () => import("./LoseAnimation.vue");
}

Однако теперь я получаю следующую ошибку:

Unknown custom element: <win-animation> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

Обновление 2

Я понял, почему я был получить сообщение об ошибке. Правильным способом было добавить следующее в начало моего скрипта внутри родительского файла vue.

const winAnimation = () => import("./WinAnimation.vue");
const loseAnimation = () => import("./LoseAnimation.vue");

, а затем внутри экспорта по умолчанию {...} Я забыл добавить имена, поэтому:

components: { winAnimation, loseAnimation }

Теперь мой код разделен и мое приложение. js размер файла уменьшился почти вдвое! :)

Ответы [ 2 ]

1 голос
/ 10 февраля 2020

1-й - не используйте библиотеку vue -lott ie. Если вы посмотрите на исходный код, основной и единственной вещью, которая должна быть предоставлена ​​этой библиотекой, является компонент src/lottie.vue (+ это зависимость lott ie -web ), но по какой-то причине * Пакет 1057 * также содержит целое демонстрационное приложение , включая файл демо JSON (src/assets/pinjump.json)

Если вы посмотрите на компонент lottie.vue, он очень маленький и очень простой Обертка для lottie-web, которая обеспечивает основные функции. Избавившись от vue-lottie, вы получите следующие преимущества:

  1. vue-lottie полностью игнорирует один из параметров lottie-web, который использует path вместо animationData - документация здесь не очень понятна, но я предполагаю, что, предоставив path, библиотека попытается загрузить данные анимации ad-ho c, поэтому вам не нужно включать их в свой пакет. Стоит попробовать imho ...

  2. Загрузка данных анимации по требованию

    • Почему вы используете динамический c импорт в файл JSON вместо динамического импорта весь компонент? Делая отдельный чанк на уровне компонентов, динамический чанк c будет включать в себя не только ваши json данные, но также lottie-web, что тоже не мало. И Vue будет обрабатывать загрузку компонента без каких-либо дополнительных изменений кода ...
    • Если вы по-прежнему хотите загружать по требованию только ваши JSON данные, вы должны понимать, что Webpack dynamici c import ( import(".....")) возвращает Promise, а lottie-web (и, в свою очередь, vue-lottie) ожидает объект. Поэтому вы должны сделать что-то вроде этого:
<script>
    import lottie from 'lottie-web';

    const animationData = () =>
       import("/users/username/documents/projectname/public/data/filename.json");

    export default {
      mounted () {
        animationData().then(function(data) {
          this.anim = lottie.loadAnimation({
            // other options 
            animationData: data
          })
        });
      }
    }
</script>

Обновление

Вы всегда должны быть очень осторожны при рассмотрении добавления сторонних компонентов в ваш проект. Еще одна вещь, которую я заметил, состоит в том, что lottie-web имеет метод destroy() в своем API. Это указывает на то, что он создает некоторые ресурсы (вероятно, элементы DOM), которые необходимо очистить. Этот компонент vue-lottie вообще не обрабатывается и может привести к неприятным утечкам памяти в вашем приложении. Вы можете прочитать о проблеме здесь

0 голосов
/ 10 февраля 2020

Когда установлено свойство animationData, это функция, отсюда и строка:

Ожидаемый объект, получивший функцию

Требуется объект, а не объект function.
Функция:

const animationData = () =>
  import("/users/username/documents/projectname/public/data/filename.json");

При определении свойства animationData вам необходимо установить объект в качестве его значения. Затем при монтировании fetch данных (или используйте Ax ios, если хотите) для обновления свойства animationData компонента.

NB Я никогда не использовал Vue, поэтому я надеюсь, что то, что я говорю, правильно.

export default {
    name: 'animation',
    components: {
        vueLottie
    },
    data () {
        return {
           speed: 1,
           animationData: {}
        }
    },
    computed: {
        lottie () {
            return this.$refs.lottie
        }
    },
    mounted() {
        fetch('/users/username/documents/projectname/public/data/filename.json')
            .then(response => response.json())
            .then(json => this.animationData = json;);
        )
    }
}
...