具有工厂功能的Vue组件v-for

时间:2020-04-23 15:31:04

标签: javascript vue.js factory v-for

我正在创建一个Table组件,并将工厂函数用于所有逻辑。在v-for中,为每行的每个项目创建一个单元格。

工厂

这是我在需要的vue页面中导入的实际工厂。我只在这里添加了相关代码。

const TableData = (data) => {

    const methods = {
        'getRows': () => {
            const result = []
            for(let i = 0, end = data.length; i < end; i++) {
                result.push(TableRow(methods, i))
            }
            return result 
        }
    }
    return methods
}


const TableRow = (parent, rowIndex) => {

    const methods = {
        'getCells': () => {
            const result = []
            for(let colIndex = 0, end = parent.getColumnCount(); colIndex < end; colIndex++) {
                result.push(TableCell(parent, rowIndex, colIndex))
            }
            return result
        }
    }
    return methods
}

const TableCell = (parent, rowIndex, columnIndex) => {

    let active = false

    const methods = {
        'hover': () => {
            active = !active
        },
        'isActive': () => {
            return active
        }
    }
    return methods
}

组件

因此在组件下方

<template>
    <div class="table-container">
        <table class="table" v-if="table">
            <thead>
                 <tr> 
                    <th class="index-col"></ths>
                    <th v-for="(col, index) in columns">{{col}}</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="row in rows">
                    <td class="cell" v-for="cell in row.getCells()" @mouseenter="cell.hover" @mouseleave="cell.hover" :class="{active: cell.isActive()}">{{cell.getValue()}}</td>
                </tr>
            </tbody>

        </table>
    </div>
</template>

<script>
import { mapActions, mapGetters } from "vuex";

/* Table Data Factory */
import TableData from "~/plugins/library/table/data_new.js";

export default {
    data() {
        return {
            table: null
        };
    },
    methods: {
        async fetch() {

            /* Here I fetch data from API (fetchedData is an array) */ 
            this.data = fetchedData

            if(this.data) {
                this.table = TableData(this.data)
            } else {
                console.error('Got no data')
            }
        }
    },
    computed: {
        columns() {
            return this.table.getColumns()
        },
        rows() {
            return this.table.getRows()
        }
    },
    mounted() {
        this.fetch()
    }
};
</script>

我想要发生的是,当我将鼠标悬停在表中的一个单元格上(将单元格的活动状态设置为true)时,该类也会切换。

:class="{active: cell.isActive()"

类道具不会监视单元工厂中的更改。据我了解,但我不知道如何使其具有反应性。我尝试并搜索了一段时间以找到解决方案,但没有成功。

希望有人能进一步帮助我,在此先感谢!

1 个答案:

答案 0 :(得分:1)

在我看来,问题出在这里=> Stream

因为您要返回的是函数而不是反应式变量,所以没有任何迹象表明有更改。现在您可以使用import ImageTools from './resize_javascript'; // <-- import as default upload = (image) => { ImageTools.resize(image, { width: 320, // maximum width height: 240 // maximum height }, function(blob, didItResize) { document.getElementById('preview').src = window.URL.createObjectURL(blob); const uploadTask = storage.ref(`images/${image.name}`).put(blob); /*...*/ 强制进行更新,但是随后您将重新绘制所有单元格,这是非常低效的。如果可能的话,您应该尽量不要使用函数作为渲染的一部分,尤其是在循环中,因为函数会在每次绘制时触发。

我的首选方式是不让各个组件管理自己的状态,而是使用嵌套的对象/数组状态来处理列,行和/或单元格的数据。但我假设这不是您想要的。

如果可以使用计算机,则可以实现反应性而无需调用函数。如果您使用的是vue 2.6+,则可以通过DIY方式添加。从Vue 2.6开始,该功能可以定义独立的可观察对象,可用于存储和改变状态以及生成计算字段。

您还应该将此方法应用于其他工厂,例如cell.isActive()将重新生成所有数据,因为它不保存任何状态。

未经测试的代码:

forceUpdate()

有了这个,您应该能够使用row.getCells()并使它对更改做出反应。

顺便说一句,如果您希望以这种方式使用Vue,您可能会受益于Vue 3(最近在beta中发布)的变化,即API组成,它提供了组件组成。