Импортировать/требовать файл JSON как клон в свойство данных Vue

У меня возникла проблема с использованием внешних данных в свойстве Vue data.

Рассмотрим следующий фрагмент из моего компонента:

export default {

    data() {
        return {
            gallery: require('core-js/support/some-page-gallery.json')
        }
    },

    created() {

        // Prepare the images for the gallery
        this._buildImageURLs();

    },

    methods: {

        /**
         * Build the image urls for the gallery.
         *
         * @return void
         */
        _buildImageURLs() {

            this.gallery.forEach(image => {
                Object.entries(image.images).forEach(([key, source]) => {
                    image.images[key] = this.$staticAsset(`/assets/images/misc/${source}`);
                });
            });

        }

    }

}

Проблема с вышеизложенным заключается в том, что изменение this.gallery, по-видимому, изменяет исходно импортированный массив.

Это приводит к следующему:

  • При загрузке страницы image.images[0] равно example.com/assets/images/misc/example.jpg
  • При переходе на другую страницу, а затем обратно на нее image.images[0] равно example.com/assets/images/misc/example.com/assets/images/misc/example.jpg.

Каков наилучший способ require моего файла JSON в качестве клона, а не в качестве эталона? Предположим, что здесь что-то не так...

В качестве альтернативы, есть ли лучший способ импортировать данные в мой компонент?

Что я пробовал?

Я также пытался использовать import, но это приводит к точно такому же результату.

Кроме того, я думал о передаче this.gallery в качестве параметра this._buildImageURLs(), и я вполне уверен, что смогу заставить это работать, но я сомневаюсь, так как это не похоже на правильный способ сделать это.

Обновлять

На всякий случай вышеизложенное не ясно; проблема, с которой я столкнулся, заключается в том, что this.gallery действует как ссылка на импортированный файл. В результате импортированные данные сохраняют свое отредактированное состояние во всем моем приложении.

Когда я последний раз на странице, метод _buildImageURLs корректно изменяет данные. Но если я уйду, а затем вернусь на страницу, измененные данные будут изменены снова, что приведет к дублированию изменений.


person Ben Carey    schedule 19.11.2019    source источник
comment
Вы не можете обновлять фактический файл json с кодом, который у вас есть, с учетом сказанного, я не уверен, чего вы пытаетесь достичь, не могли бы вы уточнить, пожалуйста?   -  person David Porcel    schedule 19.11.2019
comment
@DavidPorcel - я знаю, что вы не можете обновить файл json, это не то, чего я пытаюсь добиться. Я пытаюсь импортировать клон данных в файл json. Кажется, что когда файл json импортируется, он сохраняет его состояние во всем моем приложении. Другими словами, если я внесу изменения в импортированный объект, эти изменения все еще будут присутствовать, когда я вернусь на страницу, на которой были внесены изменения....   -  person Ben Carey    schedule 19.11.2019


Ответы (2)


Вам нужно скопировать JSON, прежде чем делать какие-либо изменения в операторе forEach:

const GALLERY = require('core-js/support/some-page-gallery.json');

export default {

    data(){
        retrun {
            gallery: JSON.parse(JSON.stringify(GALLERY)); 
        }
    }

    //rest of your code...
}

Проверьте этот вопрос: Как создать и клонировать объект JSON?

person The.Bear    schedule 19.11.2019
comment
Изначально у меня было вычисляемое свойство, но я отошел от него только потому, что это приводило к той же проблеме. Это интересный способ сделать это в отношении разбора JSON. Однако я бы внес одно изменение в ваш ответ; наличие gallery и getGallery не нужно. Лучше просто создать gallery вычисляемое свойство и проанализировать там импортированный json. - person Ben Carey; 19.11.2019
comment
А? Вычисляемое свойство разрешается при создании, а затем впоследствии обновляется, если какие-либо используемые свойства изменяются... Это не имеет ничего общего с реквизитами. - person Ben Carey; 19.11.2019
comment
Для справки в будущем, это неправда. Если вы создаете вычисляемое свойство, которое просто мутирует статический объект (не связанный с какими-либо реквизитами/значениями данных), оно запускается при создании компонента. Я делаю именно это в данный момент, и это работает :-D - person Ben Carey; 19.11.2019

Вы можете сделать копию gallery с помощью Object.assign следующим образом:

`экспорт по умолчанию {

data() {
    return {
        gallery: require('core-js/support/some-page-gallery.json'),
        galleryClone: {}
    }
},

created() {

    // Prepare the images for the gallery
    this._buildImageURLs();

},

methods: {

    /**
     * Build the image urls for the gallery.
     *
     * @return void
     */
    _buildImageURLs() {
        this.galleryClone = Object.assign({}, ...this.gallery);
        Object.entries(this.galleryClone).forEach(([key, value]) => 
        {
            Object.entries(this.galleryClone[key].images).forEach(([key, source]) => {
                this.galleryClone[key].images[key] = this.$staticAsset(`/assets/images/misc/${source}`);
            });
        });

    }

}

}`

что это делает, так это передает значение gallery в galleryClone по значению, а не по ссылке. Затем вы можете использовать переменную galleryClone в своем компоненте вместо gallery всякий раз, когда вам нужно обновить его содержимое.

person David Porcel    schedule 19.11.2019
comment
Это очень грязное решение... Я не буду голосовать за него, поскольку он технически отвечает на вопрос, но я настоятельно рекомендую вам не писать код таким образом, если нет другого решения - person Ben Carey; 19.11.2019
comment
Я искал решение, которое включало бы наименьшее количество изменений в опубликованном вами коде, но я полностью согласен с тем, что это не элегантное решение, использование вычисляемого свойства или наблюдателя вместо того, что есть в созданном методе, может выполнить то же самое вещь в более чистом виде - person David Porcel; 20.11.2019