【问题标题】:VueJS; wait for element before running local JavaScript FileVueJS;在运行本地 JavaScript 文件之前等待元素
【发布时间】:2020-07-18 02:36:48
【问题描述】:

我有一些组件、javascript 和元素需要按特定顺序运行。

1st - opensheetmusicdisplay.min.js 在我的 index.html 文件中。这不是问题。

第二个 - <div id="xml">

3rd - xml-loader.js 取决于“xml” div 和 opensheetmusicdisplay.min,js

这是 index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script rel="preload" src="<%= BASE_URL %>js/osmd/opensheetmusicdisplay.min.js"></script>    
  </head>

  <body>
    <div id="xml2">words go here</div>
    <div id="app"></div>   
  </body>
</html>

这是我正在尝试测试的 JavaScript 部分:

window.onload = function() {
    alert("xx == ", document.getElementById("xml2"));
}

alert("xx2 == ", document.getElementById("xml2"));

alert(JSON.stringify(opensheetmusicdisplay, null, 1));

当我运行它时,"xml2" 的两个实例都显示空白。 opensheetmusicdisplay 确实显示数据,这意味着它正在从head 部分中的源读取index.html

在 cmets 中向我指出 alert 只接受一个参数。这是一个错误,我暂时搁置一下。控制台中的错误是 TypeError: document.getElementById(...) is null。

现在,这是 main.js。由于我的各种想法,出现了很多cmet:

// vue 导入和配置 从 'vue' 导入 Vue 从“@/App”导入应用 从'vue-router'导入VueRouter

Vue.use(VueRouter) Vue.config.productionTip = false

// page imports
import Notation from '@/components/Notation'
import HomePage from '@/components/HomePage'
// component imports and registration
import { FoundationCSS } from  '@/../node_modules/foundation-sites/dist/css/foundation.min.css'
Vue.component('foundation-css', FoundationCSS)

import SideNav from '@/components/SideNav'
Vue.component('side-nav', SideNav);

// import * as Osmd from '@/../public/js/osmd/opensheetmusicdisplay.min.js'
// Vue.component('osmd-js', Osmd)
// import { OsmdJs } from '@/components/Osmd'

import * as XmlJs from '@/../public/js/osmd/xml-loader.js'
Vue.component('xml-js', XmlJs)
// import XLoad from '@/components/XmlLoader'

const router =  new VueRouter({
    mode: 'history',
    routes: [
        { path: '/',
          components: {
              maininfo: HomePage
          }
        },
        { path: '/chromatic-scales/c-chromatic-scale',
          components: {
              maininfo: Notation// ,
              // xmlloader: XLoad
          }
        }
    ]
})


new Vue({
    el: '#app',
    router,
    template: '<App/>',
    components: { App }
})

我将XmlJs 注册为全局,因为这是 100 种实际有效的方法中唯一的方法。然后我将它嵌入到Notation.vue 中,如下所示:

<template>
<div>

  <div id="xml">
    {{ notation.data }}
  </div>
  <xml-js />
</div>
</template>

<script>
import axios from 'axios'


export default ({
data () {
return {
notation: null,
}
},
mounted () {
axios
    .get('http://localhost:3000/chromatic-scales/c-chromatic-scale')
    .then(result => (this.notation = result))
}})


</script>

<style scoped></style>

最后一个文件是我正在尝试做的肉和土豆。 xml-loader.js&lt;div id="xml"&gt; 中获取数据,并执行程序所做的任何魔术以呈现我想要的输出。问题是似乎无论如何都没有等待{{ notation.data }} 中的内容。

我是一般使用 vuejs 和前端 javascript 框架的新手。我确实认识到此时代码可能不是最佳的。

【问题讨论】:

  • alert 接受一个参数 - 所以alert("xx == ", document.getElementById("xml2")); 只会显示xx == ...您是否考虑过使用浏览器中存在的调试工具...例如console.log
  • @JaromandaX 是的,你是对的。但是,“xml” div 没有返回任何内容。那仍然显示为空。我有一个网站,这些东西可以在没有 VueJS 的情况下工作,所以我知道在这个版本上尝试 VueJS 之前它确实有效。让任何本地 js 文件运行似乎非常困难,而且让事物互相看到就更难了。这些是我在这里处理的主要问题。
  • 从“xml”div返回是什么意思?你到底在尝试什么?请提供一种方法来复制问题。只要你运行div下面的脚本,document.getElementById("xml2")就会输出元素而不是null。
  • @EstusFlask -> TypeError: document.getElementById(...) 为空。那是控制台中的错误。
  • 请提供一种复制问题的方法。 Codesandbox 什么的。见stackoverflow.com/help/mcve

标签: javascript vue.js vuejs2 vuejs3


【解决方案1】:

您可以将 xml-loader.js 作为函数导入 Notation.vue。然后你可以简单地做这样的事情:

mounted () {
  axios.get(PATH).then(result => {
    this.notation = result
    let xmlResult = loadXML(result)
    doSomethingWithResult(xmlResult)
  }
},
methods: {
  doSomethingWithResult (result) {
    // do something
  }
}

【讨论】:

    【解决方案2】:

    存在竞争条件,即 DOM 元素在被访问时不可用。解决方案是不访问由 Vue 在其外部创建的 DOM 元素。 DOM 元素只有在异步请求后才可以使用:

    <template>
    <div>
      <div ref="xml" id="xml">
        {{ notation.data }}
      </div>
      <xml-js />
    </div>
    </template>
    
    <script>
    import axios from 'axios'
    
    export default ({
    data () {
    return {
    notation: null,
    }
    },
    async mounted () {
      const result = await axios
        .get('http://localhost:3000/chromatic-scales/c-chromatic-scale')
      this.notation = result;
      this.$nextTick(); // wait for re-render
      renderXml(this.$ref.xml); // pass DOM element to third-party renderer
    }})
    

    【讨论】:

    • 我不得不使用Vue.nextTick 而不是this.nextTick
    • 这是this.$nextTick,而不是nextTick。可用,只要this正确,vuejs.org/v2/api/#vm-nextTick
    猜你喜欢
    • 2021-06-27
    • 2021-12-21
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    • 2014-10-31
    • 2019-09-30
    相关资源
    最近更新 更多