【问题标题】:Where should a vue.js script be loaded?应该在哪里加载 vue.js 脚本?
【发布时间】:2017-05-30 06:17:29
【问题描述】:

我正在通过编写一个小脚本来学习 Vue.js,结果遇到了一种 catch 22 的情况。

处理 Vue.js 部分的 JS 脚本 (explorer.js):

var vm = new Vue({
    el: "#root",
    data: {
        posts: {},
        tags: {}
    }
})

qwest.get('/posts.json')
    .then(function (xhr, response) {
        vm.posts = response;
    });

qwest.get('/tags.json')
    .then(function (xhr, response) {
        vm.tags = response;
    });

案例一:提前加载explorer.js

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qwest/4.4.6/qwest.min.js"></script>
<link rel="stylesheet" href="/static/css/explorer.css">
<script src="/static/js/explorer.js"></script>

<div id="root">
    <button v-for="(content, title) in posts" class="l1 btn">
        {{ title }}
        <button v-for="tag in content.tags" class="l2 btn">
            {{ tag }}
            <button v-for="t in tags[tag]" class="l3 btn">
                {{ t }}
            </button>
        </button>
    </button>
</div>

我从 Vue 收到 Cannot find element: #root 错误。 这是可以理解的:当explorer.js 运行时,&lt;div id="root"&gt; 还不知道。

案例2:加载explorer.js延迟:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qwest/4.4.6/qwest.min.js"></script>
<link rel="stylesheet" href="/static/css/explorer.css">

<div id="root">
    <button v-for="(content, title) in posts" class="l1 btn">
        {{ title }}
        <button v-for="tag in content.tags" class="l2 btn">
            {{ tag }}
            <button v-for="t in tags[tag]" class="l3 btn">
                {{ t }}
            </button>
        </button>
    </button>
</div>

<script src="/static/js/explorer.js"></script>

我收到 Property or method "data" is not defined on the instance but referenced during render. 错误(以及其他相同样式的错误)。
这也是可以理解的:v-for 函数尝试访问尚未定义的数据。

我应该如何(或者更确切地说 - 在哪里)加载 explorer.js

【问题讨论】:

    标签: javascript vue.js


    【解决方案1】:

    首先,您应该在文件底部添加explorer.js。您可以将其添加到文件顶部如果您将 Vue 的实例化(new Vue(...) 包装在一个只有 ran when the page was completely loaded 的函数中,但这是标准做法在底部添加脚本。

    您的主要问题是nested buttons are invalid HTML。这是抛出的问题

    属性或方法“内容”未在实例上定义,但 在渲染期间引用。

    这似乎主要是 Vue 抱怨您的无效 HTML。我已将您在下面的模板修改为可以实际呈现的内容,但您需要根据自己的需要对其进行调整。

    <div v-for="(content, title) in posts" class="l1 btn">
      <button>{{ title }}</button>
      <span v-for="tag in content.tags" class="l2 btn" style="margin-left:1em">
         <button>{{ tag }}</button>
         <span v-for="t in tags[tag]" class="l3 btn">
           <button>{{ t }}</button>
         </span>
      </span>
    </div>
    

    这是一个有效的example

    【讨论】:

    • 谢谢。我永远不会发现按钮导致问题的事实。我将它们转换为div,一切都很好(底部有explorer.js
    【解决方案2】:

    我实际上写了一篇解释Vue Cannot Find Element 错误的帖子。如果您尝试提前将 Vue 实例化为 0,您将收到此错误。在我的Vue.js training course 中,所有示例都将 Vue.js 框架加载到文件的end。一般来说,我通过 script 标签加载了 Vue.js 框架,然后是另一个初始化 Vue 实例本身的 script 块。这两项发生在结束 body 标记之前。

    关于案例 #1,只需将您的 script 元素移到您的 &lt;div id="root" ... 元素之后,您应该处于良好状态。

    您可以使用v-cloak 指令来创建流畅的加载体验。我建议最后加载 Vue 的原因是基于 PageSpeed Insights 的建议。不过,这些可能与您的场景相关,也可能不相关。

    【讨论】:

      【解决方案3】:

      Vue.js 应该在开始时加载。

      您无需指定数据属性即可访问其属性,请参见 Hello World 示例:

      https://jsfiddle.net/chrisvfritz/50wL7mdz/

      我不确定您的数据结构是什么,但是您可以尝试类似的方法(没有 data 属性):

      <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/qwest/4.4.6/qwest.min.js"></script>
      
      <div id="root">
          <button v-for="post in posts" class="l1 btn">
              {{ post.title }}
              <button v-for="tag in tags" class="l2 btn">
                  {{ tag }}
              </button>
          </button>
      </div>
      

      只根据你的数据结构工作,但没有data

      另外,对于 Vue.js,您不能动态添加根属性,请参阅 https://vuejs.org/v2/guide/reactivity.html,因此您必须将数据中的根属性指定为初始结构。

      explorer.js 应该在你的 html 模板之后加载(最后),你得到的警告/错误是由于在开始时没有定义你的模型,甚至是嵌套的根!

      除此之外,一切似乎都很好。

      【讨论】:

      • 我不确定我是否理解。我的脚本是问题的最重要部分,具有数据结构。在 HTML 中,(data, title) in posts 允许我获取值(数据,这确实是一个不幸的名称,但与我的 Vue 对象定义中的data结构无关),以及密钥(title ),对于posts 的每个元素。
      • 我更改了变量的名称以使其清楚(data -> content
      • 看我的编辑,你需要在初始数据中声明所有的根元素。我也没有看到您的完整数据结构(作为对象),如果您添加它,它会有所帮助。
      • 我明白,但它们声明(请参阅我的问题中的第一段代码 - 这是管理 Vue 对象及其数据的 JS)跨度>
      • 我重新澄清了问题,在描述中明确调用了JS脚本。希望这有助于澄清问题。
      猜你喜欢
      • 2021-05-07
      • 2021-07-17
      • 2017-11-17
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多