gpt4 book ai didi

vue.js - 为什么vue在循环中找不到变量?

转载 作者:行者123 更新时间:2023-12-03 06:45:59 26 4
gpt4 key购买 nike

我正在努力开发一个简单的组件并在循环中使用它:

<template id="measurement">
<tr class="d-flex">
</tr>
</template>

Vue.component('measurement', {
template: '#measurement',
props: {
name: String,
data: Object,
val: String,
},
});

这显然还没有功能,但已经失败:

<table v-for="(m, idx) in sortedMeters">
<measurement v-bind:data="m"></measurement>
</table>

ReferenceError: Can't find variable: m内部 View 。出于一个奇怪的原因,同样的事情在一段中起作用,即没有错误:

<p v-for="(m, idx) in sortedMeters">
<measurement v-bind:data="m"></measurement>
</p>

什么原因导致找不到变量?

PS.:这是一个 fiddle : https://jsfiddle.net/andig2/u47gh3w1/ .一旦 table 出现,它就会显示一个不同的错误。已经包括了。

更新 该循环旨在生成多个表。每个表的行将由多个 measurement 创建s

最佳答案

TLDR:在 Vue 传递 DOM 模板之前,浏览器正在提升 <measurement v-bind:name="i" v-bind:data="m"><table> (在 v-for 上下文之外),导致 Vue.js 中的错误。这是一个已知的 caveat of DOM template parsing .

HTML spec requires the <table> contain only specific child elements :

  • <caption>
  • <colgroup>
  • <thead>
  • <tbody>
  • <tr>
  • <tfoot>
  • <script><template>与以上混合

  • 同样, content model of <tr> 是:
  • <td>
  • <th>
  • <script><template>与以上混合

  • 兼容浏览器的 DOM 解析器会自动提升不允许的元素 - 例如 <measurement> ——在 table 外面。这发生在脚本阶段之前(甚至在 Vue 看到它之前)。

    例如,这个标记:

    <table>
    <tr v-for="(m,i) in obj">
    <measurement v-bind:name="i" v-bind:data="m"></measurement>
    </tr>
    </table>

    ...在 DOM 解析之后(在任何脚本之前)变成这样:

    <measurement v-bind:name="i" v-bind:data="m"></measurement> <!-- hoisted outside v-for -->
    <table>
    <tr v-for="(m,i) in obj">
    </tr>
    </table>

    注意 im然后在 v-for 的上下文之外循环,这会导致有关 i 的 Vue 运行时错误和 m未定义(除非您的组件碰巧已经声明了它们)。 m旨在绑定(bind)到 <measurement>data Prop ,但由于失败了, data只是它的初始值(也是 undefined ),导致 {{data.value}} 的呈现以 Error in render: "TypeError: Cannot read property 'value' of undefined" 失败.

    要演示没有这些运行时错误且没有 Vue 的提升,请运行以下代码片段:

    <table style="border: solid green">
    <tr>
    <div>1. hoisted outside</div>
    <td>3. inside table</td>
    2. also hoisted outside
    </tr>
    </table>


    ...然后在浏览器的 DevTools 中检查结果,应该如下所示:

    <div>1. hoisted outside</div>
    2. also hoisted outside
    <table style="border: solid green">
    <tr>
    <td>3. inside table</td>
    </tr>
    </table>

    解决方案一:使用 <tr is="measurement">
    如果你喜欢 DOM 模板,你可以使用 is <tr> 上的属性指定 measurement作为类型(由 Vue docs 和另一个 answer 建议)。这首先需要 <measurement>模板使用 <td><th>作为 <tr> 内的容器元素成为有效的 HTML:

    <template id="measurement">
    <tr>
    <td>{{name}} -> {{data.value}}</td>
    </tr>
    </template>

    <div id="app">
    <table v-for="(m,i) in sortedMeters">
    <tr is="measurement" v-bind:name="i" v-bind:data="m" v-bind:key="i"></tr>
    </table>
    </div>

    Vue.component('measurement', {
    template: '#measurement',
    props: {
    name: String,
    data: Object
    }
    })

    new Vue({
    el: '#app',
    data: {
    sortedMeters: {
    apple: {value: 100},
    banana: {value: 200}
    },
    }
    })
    <script src="https://unpkg.com/vue@2.6.11"></script>
    <template id="measurement">
    <tr>
    <td>{{name}} -> {{data.value}}</td>
    </tr>
    </template>

    <div id="app">
    <table v-for="(m,i) in sortedMeters">
    <tr is="measurement" v-bind:name="i" v-bind:data="m" v-bind:key="i"></tr>
    </table>
    </div>


    解决方案2:包裹 <table>在组件中

    如果您更喜欢 DOM 模板,您可以为 <table> 使用包装器组件。 ,它可以包含 <measurement>没有吊装警告。

    Vue.component('my-table', {
    template: `<table><slot/></table>`
    })

    <div id="app">
    <my-table v-for="(m, i) in sortedMeters">
    <measurement v-bind:name="i" v-bind:data="m"></measurement>
    </my-table>
    </div>

    Vue.component('measurement', {
    template: '#measurement',
    props: {
    name: String,
    data: Object
    }
    })

    Vue.component('my-table', {
    template: `<table><slot/></table>`
    })

    new Vue({
    el: '#app',
    data: {
    sortedMeters: {
    apple: {value: 100},
    banana: {value: 200}
    },
    }
    })
    <script src="https://unpkg.com/vue@2.6.11"></script>
    <template id="measurement">
    <tr>
    <td>{{name}} -> {{data.value}}</td>
    </tr>
    </template>

    <div id="app">
    <my-table v-for="(m, i) in sortedMeters">
    <measurement v-bind:name="i" v-bind:data="m"></measurement>
    </my-table>
    </div>


    解决方案3:移动 <table>标记为模板字符串

    您可以移动整个 <table>到组件的模板字符串中,可以避免 DOM 模板警告。同样,您可以移动 <table>变成 single file component ,但我假设您对 DOM 模板有很大的需求。

    Vue.component('my-table', {
    template: `<div>
    <table v-for="(m, idx) in sortedMeters">
    <measurement v-bind:data="m"></measurement>
    </table>
    </div>`,
    props: {
    sortedMeters: Object
    }
    })

    <div id="app">
    <my-table v-bind:sorted-meters="sortedMeters"></my-table>
    </div>

    Vue.component('measurement', {
    template: '#measurement',
    props: {
    name: String,
    data: Object
    }
    })

    Vue.component('my-table', {
    template: `<div>
    <table v-for="(m,i) in sortedMeters">
    <measurement v-bind:name="i" v-bind:data="m" v-bind:key="i"></measurement>
    </table>
    </div>`,
    props: {
    sortedMeters: Object
    }
    })

    new Vue({
    el: '#app',
    data: {
    sortedMeters: {
    apple: {value: 100},
    banana: {value: 200}
    },
    }
    })
    <script src="https://unpkg.com/vue@2.6.11"></script>
    <template id="measurement">
    <tr>
    <td>{{name}} -> {{data.value}}</td>
    </tr>
    </template>

    <div id="app">
    <my-table :sorted-meters="sortedMeters"></my-table>
    </div>

    关于vue.js - 为什么vue在循环中找不到变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59697740/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com