0

我正在尝试构建一个简单的页面构建器,它有一个行元素、它的子列元素和我需要调用的最后一个组件。为此,我设计了一个架构,其中我将数据集定义到根组件并通过道具将数据推送到其子元素。所以假设我有一个根组件:

<template>
    <div>
        <button @click.prevent="addRowField"></button>
        <row-element v-if="elements.length" v-for="(row, index) in elements" :key="'row_index_'+index" :attrs="row.attrs" :child_components="row.child_components" :row_index="index"></row-element>
    </div>
</template>

<script>
    import RowElement from "../../Components/Builder/RowElement";

    export default {
        name: "edit",
        data(){
            return{
                elements: [],
            }
        },
        created() {
            this.listenToEvents();
        },
        components: {
            RowElement,
        },
        methods:{
            addRowField() {
                const row_element = {
                    component: 'row',
                    attrs: {},
                    child_components: [

                    ]
                }
                this.elements.push(row_element)
            }
        },
    }
</script>

在这里你可以看到我有一个按钮,我正在尝试推送元素,并且它的元素正在通过道具传递给它的子元素,所以这个RowElement组件有以下代码:

<template>
    <div>
        <column-element v-if="child_components.length" v-for="(column,index) in child_components" :key="'column_index_'+index"  :attrs="column.attrs" :child_components="column.child_components" :row_index="row_index" :column_index="index"></column-element>
    </div>
    <button @click="addColumn"></button>
</template>

<script>
    import ColumnElement from "./ColumnElement";
    export default {
        name: "RowElement",
        components: {ColumnElement},
        props: {
            attrs: Object,
            child_components: Array,
            row_index: Number
        },
        methods:{
            addColumn(type, index) {
                this.selectColumn= false
                let column_element = {
                    component: 'column',
                    child_components: []
                };
                let component = {}

                //Some logic here then we are emitting event so that it goes to parent element and there it can push the columns

                eventBus.$emit('add-columns', {column: column_element, index: index});
            }
        }
    }
</script>

所以现在我必须在根页面上监听事件,所以我有:

eventBus.$on('add-columns', (data) => {
    if(typeof this.elements[data.index] !== 'undefined')
        this.elements[data.index].child_components.push(data.column)
});

现在我需要再次访问这些数据,ColumnComponent所以在 columnComponent 文件中我有:

<template>
    //some extra div to have extended features
    <builder-element
        v-if="!loading"
        v-for="(item, index) in child_components"
        :key="'element_index_'+index" :column_index="column_index"
        :element_index="index" class="border bg-white"
        :element="item" :row_index="row_index"
    >
    </builder-element>
</template>

<script>
    export default {
        name: "ColumnElement",
        props: {
            attrs: Object,
            child_components: Array,
            row_index: Number,
            column_index: Number
        },
    }
</script>

还有我的决赛BuilderElement

<template>
    <div v-if="typeof element.component !== 'undefined'" class="h-10 w-10 mt-1 mb-2 mr-3 cursor-pointer  font-bold text-white rounded-lg">
        <div>{{element.component}}</div>
        <img class="h-10 w-10 mr-3" :src="getDetails(item.component, 'icon')">
    </div>
    <div v-if="typeof element.component !== 'undefined'" class="flex-col text-left">
        <h5 class="text-blue-500 font-bold">{{getDetails(item.component, 'title')}}</h5>
        <p class="text-xs text-gray-600 mt-1">{{getDetails(item.component, 'desc')}}</p>
    </div>
</template>

<script>
    export default {
        name: "BuilderElement",
        data(){
            return{
                components:[
                    {id: 1, title:'Row', icon:'/project-assets/images/row.png', desc:'Place content elements inside the row', component_name: 'row'},
                    //list of rest all the components available
                ]
            }
        },
        props: {
            element: Object,
            row_index: Number,
            column_index: Number,
            element_index: Number,
        },
        methods:{
            addElement(item,index){
                //Some logic to find out details
                let component_element = {
                    component: item.component_name,
                    attrs: {},
                    child_components: [
                    ]
                }

                eventBus.$emit('add-component', {component: component_element, row_index: this.row_index, column_index: this.column_index, element_index: this.element_index});

            },
            getDetails(component, data) {
                let index = _.findIndex(this.components, (a) => {
                    return a.component_name === component;
                })
                console.log('Component'+ component);
                console.log('Index '+index);
                if(index > -1) {
                    let component_details = this.components[index];
                    return component_details[data];
                }
                else
                    return null;
            },
        },
    }
</script>

如您所见,我再次发出名为的事件,该事件add-component再次在根组件中进行侦听,因此在以下侦听器中进行了侦听:

eventBus.$on('add-component', (data) => {
    this.elements[data.row_index].child_components[data.column_index].child_components[data.element_index] = data.component
});

它显示了我的数据集,vue-devtools但它没有出现在构建器元素中:

图片 FYR:

这是我的根组件:

根元素

这是我的行组件:

行组件

这是我的列组件:

列组件

这是我的构建器元素:

最后一个构建器元素

我不知道为什么这些数据没有传递给它的子组件,我的意思是最后一个组件对道具没有反应,任何更好的想法都非常感谢。

谢谢

4

1 回答 1

2

问题在于您在方法中设置数据的addComponent方式。

当您通过直接修改数组的索引来更改数组时,Vue 无法获取更改,例如,

arr[0] = 10

正如他们在阵列突变的变化检测指南中所定义的,

Vue 包装了观察到的数组的变异方法,因此它们也会触发视图更新。包装的方法是:

  1. 推()
  2. 流行音乐()
  3. 转移()
  4. 取消移位()
  5. 拼接()
  6. 种类()
  7. 撤销()

所以你可以改变。

this.elements[data.row_index].child_components[data.column_index].child_components[data.element_index] = data.component

至,

this.elements[data.row_index].child_components[data.column_index].child_components.splice(data.element_index, 1, data.component);
于 2020-07-25T09:18:09.140 回答