与多次使用同一组件共享数据

时间:2019-11-08 12:15:36

标签: vuejs2 vue-component

我具有以下组成部分:

//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 个答案:

答案 0 :(得分:1)

我无法从问题中看出这是否是您面临的问题,但这是 a 问题。

首次在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的属性现在正在复制到新对象,而不仅仅是直接使用该对象。