首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Gridstack.js + Vue 3组件

Gridstack.js + Vue 3组件
EN

Stack Overflow用户
提问于 2022-06-30 09:28:13
回答 2查看 375关注 0票数 0

我试图用Vue 3创建一个gridstack.js仪表板,我希望网格堆栈项包含反应性vue 3组件。

问题是这些网格堆栈项只能传递HTML。文档声明您应该能够将Vue组件作为内容添加,但是示例是针对Vue 2的,我正努力在Vue 3中实现这一点。

我有以下代码:

代码语言:javascript
运行
复制
<template>
    <div class="p-6 h-full flex flex-col">

        <header class="flex flex-row items-center justify-between mb-6">
            <div>
                <h1 class="text-3xl font-bold">
                    Workbench
                </h1>
                <p class="leading-6 text-gray-600 text-sm mt-2">
                    {{ info }}
                </p>
            </div>
            <div class="flex flex-row items-center">
                <button type="button" @click="addPanel()">Add Panel</button>
            </div>
        </header>

        <div class="flex-1">
            <section class="grid-stack"></section>
        </div>

    </div>
</template>

<script setup>

    import { ref, onMounted, defineComponent, createApp } from "vue"

    import TestPanel from "./../components/panels/TestPanel.vue"

    let grid = null;

    const items = [
        { x: 0, y: 0, h: 4, w: 6 },
        { x: 7, y: 0, h: 4, w: 6 },
        { x: 0, y: 5, h: 4, w: 4 },
        { x: 4, y: 5, h: 4, w: 4 },
        { x: 8, y: 5, h: 4, w: 4 },
    ];

    onMounted(() => {

        grid = GridStack.init({
            // float: true,
            cellHeight: "70px",
            minRow: 1,
        });

        grid.load(items)

    });

    function addPanel() {

        const div = document.createElement("div")
        div.id = Math.random().toString(24).substring(8)

        const componentInstance = defineComponent({
            extends: TestPanel, data() {
                return {
                    test: "this is a test"
                }
            }
        })

        const app = createApp(componentInstance)

        app.mount(div)

        let widget = grid.addWidget({
            x: 0,
            y: 0,
            w: 6,
            h: 3,
            content: div.outerHTML,
        })

        app.mount(div.id)
    }

</script>

<style>
    .grid-stack-item-content {
        background-color: #18BC9C;
    }
</style>

这将在堆栈网格项中加载vue组件,但组件不再是反应性的。

任何帮助都将不胜感激,谢谢!

EN

回答 2

Stack Overflow用户

发布于 2022-09-30 19:29:14

这可能并不是网格堆栈创建者所想的那样,但您可以这样做:

代码语言:javascript
运行
复制
<template>
  <button @click="addNewWidget()">Add Widget</button> {{ info }}

  <section class="grid-stack">
    <div 
      v-for="(component, key, index) in components" 
      :key="'component'+index" 
      :gs-id="key" 
      class="grid-stack-item"
      :gs-x="component.gridPos.x" 
      :gs-y="component.gridPos.y" 
      :gs-h="component.gridPos.h" 
      :gs-w="component.gridPos.w"
      gs-auto-position="true"
    >
      <div class="grid-stack-item-content">
        <component :is="component.name" v-bind="component.props" />
      </div>
    </div>
  </section>
</template>

<script>
import { ref, onMounted, reactive, nextTick } from 'vue';
import 'gridstack/dist/gridstack.min.css';
import { GridStack } from 'gridstack';
import YourRandomComponent1 from '../YourRandomComponent1.vue';
import YourRandomComponent2 from '../YourRandomComponent2.vue';
import YourRandomComponent3 from '../YourRandomComponent3.vue';

export default {
  name: "WidgetGrid",
  setup() {
    let info = ref("");
    let grid = null;

    let components = reactive({
      yourRandomComponent1: {
        name: "YourRandomComponent1", props: {}, gridPos: { x: 0, y: 1, w: 4, h: 5 }
      },
      yourRandomComponent2: {
        name: "YourRandomComponent2", props: {}, gridPos: { x: 0, y: 1, w: 2, h: 5 }
      },
    });

    onMounted(() => {
      grid = GridStack.init({
        float: true,
        cellHeight: "70px",
        minRow: 1,
      });

      grid.on("dragstop", (event, element) => {
        console.log("move event!", event, element);
        const node = element.gridstackNode;
        info.value = `you just dragged node #${node.id} to ${node.x},${node.y} – good job!`;
      });
    });

    // this will of course only work once because of the object-key
    function addNewWidget() {
      components.yourRandomComponent3= {
        name: "YourRandomComponent3", props: {}, gridPos: { x: 0, y: 1, w: 2, h: 5 }
      };
      // we have to wait for vue to update v-for, 
      // until then the querySelector wont find the element
      nextTick(() => {
        console.log(grid);
        let compEl = document.querySelector('[gs-id="yourRandomComponent3"]');
        console.log(compEl);
        grid.makeWidget(compEl);
      });
      console.warn("i will only work once, fix my inputs to reuse me");
    }

    return {
      info,
      components,
    };
  },
  components: {
    // eslint-disable-next-line vue/no-unused-components
    YourRandomComponent1,
    // eslint-disable-next-line vue/no-unused-components
    YourRandomComponent2,
  },
}
</script>

<style>
.grid-stack {
  background-color: #FAFAFF;
  border-style: dashed;
}

.grid-stack-item {
  color: #2c3e50;
  text-align: center;
  border-style: solid;
  overflow: auto;
  z-index: 50;
}
</style>

在我的例子中,缺少一个包含组件的grid-stack-item-content-class的div使小部件不可移动。我还添加了一个新增小部件函数,演示如何向网格中添加新小部件。关键是使用reactive(),以便Vue将重新呈现页面。重新呈现后,需要使用grid.makeWidget将组件注册为网格元素.为此,我们需要组件的Dom元素,这是在Vue用nextTick重新呈现之后得到的。

票数 0
EN

Stack Overflow用户

发布于 2022-12-02 11:01:26

您可以像这样在Vue3中使用自己的组件

代码语言:javascript
运行
复制
<div class="grid-stack" :style="{ 'background-color': hex }"  >
    <widget v-for="widget in widgets" :widget="widget" :key="widget" />
</div>

导入组件

代码语言:javascript
运行
复制
import Widget from "src/components/GridStackComponent.vue";

将组件添加到导出

代码语言:javascript
运行
复制
export default {
  name: 'GridStack',
  components: {
    Widget
  },
  data() {
   ...
  },
  ...
}

仅此而已。结果可能是这样的

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72813397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档