[英]Gridstack.js + Vue 3 components
我正在嘗試使用 Vue 3 創建一個 gridstack.js 儀表板,我希望網格堆棧項目包含反應性 vue 3 組件。
問題是這些網格堆棧項只能傳遞 HTML。文檔指出您應該能夠將 Vue 組件添加為內容,但示例是針對 Vue 2 的,我正在努力在 Vue 3 中實現它。
我有以下代碼:
<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 組件加載到堆棧網格項中,但該組件不再是反應式的。
任何幫助將不勝感激,在此先感謝!
這可能不是 gridstack-creators 所想的,但這里是 go:
<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>
在我的例子中,一個缺少的 div 與grid-stack-item-content
-class 包裝組件使小部件無法移動。 我還添加了一個 add-new-widget function 來演示如何向網格添加新的小部件。 關鍵是使用reactive()
以便 Vue 重新渲染頁面。 重新渲染后,需要使用grid.makeWidget
將組件注冊為網格元素。 為此,我們需要組件的 Dom 元素,這是在 Vue 使用nextTick
重新渲染后獲得的。
你可以像這樣在 Vue3 中使用自己的組件
<div class="grid-stack" :style="{ 'background-color': hex }" >
<widget v-for="widget in widgets" :widget="widget" :key="widget" />
</div>
導入你的組件
import Widget from "src/components/GridStackComponent.vue";
添加要導出的組件
export default {
name: 'GridStack',
components: {
Widget
},
data() {
...
},
...
}
就這樣。 結果看起來像這樣
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.