Данные совместно используются одним и тем же компонентом, который используется несколько раз - PullRequest
0 голосов
/ 08 ноября 2019

У меня есть следующие компоненты:

//wrapper component
<template>
    <div class="form-group form-group-text">
        <label v-if="label" :for="fieldId()">{{ label }}</label>
        <tiny-wrapper :key="pk"
            class="form-control builderEditor"
            :id="id"
            :name="fieldName()"
            v-model="form[field.key]"
            :init="editorSettings"
            :content="field.content"
        ></tiny-wrapper>
    </div>
</template>

<script>
    import Vue from 'vue'
    import BuilderHelper from './builder-helper'
    import TinyWrapper from '../tiny-wrapper'

    export default Vue.extend({
        props: [
            'pk',
            'title',
            'fieldKey',
            'field',
            'databaseName',
            'required',
            'disabled',
            'options',
            'label',
            'locale',
            'hidden',
        ],

        mixins: [BuilderHelper],

        components: {
            'tiny-wrapper': TinyWrapper,
        },

        computed: {
            editorSettings() {
                return {
                    // editor_selector: '.builderEditor',
                    selector: '#' + this.id,
                    menubar: '',
                    toolbar: 'bold italic | link',
                    height: 150,
                    contextmenu: 'bold italic | link',
                    forced_root_block: false,
                    invalid_elements: 'script',
                    statusbar: false,
                    resize: false,
                    browser_spellcheck: true,
                }
            }
        },
    })
</script>

и

// child component
<template>
    <textarea :id="id" ref="editor" class="form-control" :class="classList" :value="content"></textarea>
</template>

<script>
    import Vue from 'vue'
    import 'tinymce/tinymce'

    export default Vue.extend({
        props: {
            init: {
                type: Object,
            },
            id: {
                type: String,
                required: true,
            },
            classList: {
                type: String,
            },
            value: {
                type: String,
            }
        },

        data: function () {
            return {
                content: '',
                tinyOptions: {},
            }
        },

        mounted() {
            // this.content = this.value

            this.tinyOptions = Object.assign(window.tinyMCESettings, {
                selector: '#' + this.id,
                init_instance_callback: this.initInstanceCallback,
            }, this.init)

            tinymce.init(this.tinyOptions)
        },

        methods: {
            initInstanceCallback(editor) {
                editor.setContent(this.value)

                editor.on('change', e => {
                    this.update(editor)
                })

                editor.on('keyup', e => {
                    this.update(editor)
                })

                this.$parent.$on('reset', () => editor.setContent(''))
            },

            update(editor) {
                this.content = editor.getContent()
                this.$emit('input', this.content)
            },
        }
    })
</script>

Я использую компонент обертки, как 10 раз в моем документе.

Данные в дочернем компоненте одинаковы для каждого компонента-оболочки, состояние разделяется / перезаписывается данными в последнем созданном дочернем компоненте. Что я делаю не так?

1 Ответ

1 голос
/ 08 ноября 2019

Я не могу сказать из вопроса, является ли это проблемой , с которой вы сталкиваетесь, но это проблема.

Когда вы впервые создаете tinyOptions в функции data вы назначаете ему новый пустой объект. Это хорошо. Каждый экземпляр вашего компонента будет иметь свой отдельный объект для этого свойства. Ничего не передается.

Однако затем мы нажимаем на это:

this.tinyOptions = Object.assign(window.tinyMCESettings, {
    selector: '#' + this.id,
    init_instance_callback: this.initInstanceCallback,
}, this.init)

Это назначает другой объект свойству tinyOptions, поэтому исходный пустой объект отбрасывается. Это само по себе не будет проблемой. Но давайте посмотрим, что здесь происходит. Приведенный выше код примерно эквивалентен следующему:

window.tinyMCESettings.selector = '#' + this.id
window.tinyMCESettings.init_instance_callback = this.initInstanceCallback,

for (const prop in this.init) {
    window.tinyMCESettings[prop] = this.init[prop]
}

this.tinyOptions = window.tinyMCESettings

Итак, он обновляет свойства объекта window.tinyMCESettings, а затем присваивает этот объект свойству tinyOptions.

Все ваши компоненты будут захватывать тот же самый window.tinyMCESettings объект и изменять его свойства. Хотя каждый компонент имеет свое отдельное свойство tinyOptions, все эти свойства будут указывать на один и тот же объект.

Одним из решений будет копирование всего в новый пустой объект:

this.tinyOptions = Object.assign({}, window.tinyMCESettings, {
    selector: '#' + this.id,
    init_instance_callback: this.initInstanceCallback,
}, this.init)

Лично я бы использовал синтаксис ... вместо:

this.tinyOptions = {
    ...window.tinyMCESettings,
    selector: '#' + this.id,
    init_instance_callback: this.initInstanceCallback,
    ...this.init
}

Выбор за вами.

Ключевым моментом, который стоит отметить, является то, что свойства window.tinyMCESettings теперь используютсяскопировать в новый объект, а не просто использовать этот объект напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...