0

我正在尝试以编程方式将导入的 vue 添加到新的 Golden Layout 窗格。我使用拖放示例进行构建,但它只是将 HTML 添加到窗格,而不是需要传递给它的道具的 vue,例如窗格的宽度和高度。 https://golden-layout.com/tutorials/dynamically-adding-components.html

我一直在尝试通过添加它layout.registerComponent()containter.on("open", funtion, ect.但找不到:

  1. 要安装 vue 的元素。
  2. 新的拖放窗格宽度和高度。

据文档所说,on "open"应该在创建新窗格/容器后触发。 https://golden-layout.com/docs/Container.html#Events

但是,正如我(错误地?)实现它时,窗格/容器尚未添加on "open"

相同的 vue 在没有问题的情况下添加到默认布局中layout.init();并且可以完美运行。

但是通过拖放方法(当前实现)添加相同的 vue 不起作用,并最终得到以下结果:

[Vue warn]: Cannot find element: #priceChart2

我一直在做我的研究,到目前为止,无法找出解决方案。

import "./goldenlayout-base.css";
import "./goldenlayout-dark-theme.css";
// required for dynamic component instantiation from the config
import Vue from "vue";
import $ from "jquery";
import GoldenLayout from "./goldenlayout.js";

// import a price chart
import PriceChart from "src/components/TradingVueJs/Chart.vue"

let chartCnt = 1

export default {
  name: "Trader",
  props: {},
  components: {},
  computed: {},
  data() {
    return {};
  },
  mounted() {
    var config = {
      content: [
        {
          type: "column",
          isClosable: true,
          reorderEnabled: true,
          title: "",
          content: [
            {
              type: "stack",
              width: 100,
              height: 50,
              isClosable: true,
              reorderEnabled: true,
              title: "",
              activeItemIndex: 0,
              content: [
                {
                  type: "component",
                  componentName: "priceChart",
                  componentState: {
                    text: "Price Chart",
                  },
                  isClosable: true,
                  reorderEnabled: true,
                  title: "Chart",
                  id: "Chart1"
                },
              ],
            },
            {
              type: "stack",
              header: {},
              isClosable: true,
              reorderEnabled: true,
              title: "",
              activeItemIndex: 0,
              height: 50,
              content: [
                {
                  type: "component",
                  componentName: "example",
                  componentState: {
                    text: "Some message",
                  },
                  isClosable: false,
                  reorderEnabled: true,
                  title: "Example",
                  id: "Example",
                },
              ],
            },
          ],
        },
      ],
    };

    var layout = new GoldenLayout(config, $("#layoutContainer"));

    layout.registerComponent("example", function(container, state) {
      container.getElement().html("<h2>" + state.text + "</h2>");
    });


   layout.registerComponent("priceChart", function(container, state) {
      
      let id = "priceChart"+chartCnt++
      container.on("open", () => {
        container.getElement().html("<div id='"+id+"' class='chartComponent'></div>");
        // mount price chart component
        const chart = Vue.extend(PriceChart);
        const Chart = new chart({ 
          propsData: { 
            id: id,
            width: container.width, 
            height: container.height 
            } 
        });
        Chart.$mount('#'+id)
      })
    });

    //  Update GL on window resize
    window.addEventListener("resize", () => {
      layout.updateSize();
    });

    // attach the state change listener
    layout.on("stateChanged", () => {
      this.onLayoutStateChanged(layout.toConfig());
    });

    layout.init();

    var addMenuItem = function(component, title, text) {
      var element = $("<li>" + text + "</li>");
      $("#menuContainer").append(element);

      var newItemConfig = {
        title: title,
        type: "component",
        componentName: component,
        componentState: { text: text },
      };

      layout.createDragSource(element, newItemConfig);
    };

    addMenuItem("priceChart", "BTC/USDT", "Price Chart");
    addMenuItem("example", "Add me!", "You've added me!");
    addMenuItem("example", "Me too!", "You've added me too!");
  },

  methods: {
    resetLayout() {
      window.location.reload(true);
    },
    onLayoutStateChanged(state) {
      var layoutState = JSON.stringify(state, null, 2);
      // eslint-disable-next-line no-console
      console.log("changed state", layoutState);
    }
  }
};
<template>
  <!--  this is the golden-layout container where all the vue components will be contained -->
  <div id="wrapper">
    <ul id="menuContainer"></ul>
    <div id="layoutContainer"></div>
  </div>
</template>

4

1 回答 1

0

最后我不得不使用 asetInterval()来等待元素出现在 DOM 中。

我在这里找到了一个很好的解决方案:

https://gist.github.com/chrisjhoughton/7890303#gistcomment-2638757

/**
 * Wait for the specified element to appear in the DOM. When the element appears,
 * provide it to the callback. If waiting times out, send null to the callback.
 *
 * @param selector a jQuery selector (eg, 'div.container img')
 * @param callback function that takes selected element (null if timeout)
 * @param maxtries number of times to try (return null after maxtries, false to disable, if 0 will still try once)
 * @param interval ms wait between each try
 */
waitForEl(selector, callback, maxtries = false, interval = 100) {
  const poller = setInterval(() => {
    const el = jQuery(selector)
    const retry = maxtries === false || maxtries-- > 0
    if (retry && el.length < 1) return // will try again
    clearInterval(poller)
    callback(el || null)
  }, interval)
}

于 2021-06-13T09:23:38.277 回答