属性 或方法“_”未在实例上定义但在渲染期间被引用
Property or method "_" is not defined on the instance but referenced during render
我是一个有能力的 React 开发人员,但是从另一个开发人员那里继承了一个 vue.js 项目并且已经维护了几年,不幸的是我没有像我应该的那样通过个人努力来学习 vue。
我在使用 lodash 时抛出了一个奇怪的错误,我相信它不喜欢我的 _.debounce
调用
组件:
<script>
import _ from 'lodash'
import CostCodeField from '@/components/workdays/CostCodeField'
// ...
</script>
<template lang='html'>
<!-- relevant code snippet -->
<!-- ... -->
<b-table class="charges-table is-fullwidth" :data="workday.charges" :striped="true" :mobile-cards="false" :row-class="chargeClass">
<b-table-column label="Cost Code" width="260">
<b-field expanded="expanded">
<cost-code-field
:value="props.row.cost_code.number" :disabled="timecard.is_submitted || locked || isLoading(props)"
:job="props.row.job"
@input="set($event, props.index, 'cost_code')"
@change="_.debounce(submit(props.row, props.index), 100)"
></cost-code-field>
<p class="control">
<a
class="button"
@click="triggerCostCode(props.row, props.index)" :disabled="props.row.job.jd_job_number_id === undefined || timecard.is_submitted || isLoading(props)"
>
<b-icon icon="magnify"></b-icon>
</a>
</p>
</b-field>
</b-table-column>
<!-- ... -->
</b-table>
</template>
console.error
[Vue warn]: Property or method "_" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
found in
---> <ChargesTable> at src/components/workdays/ChargesTable.vue
<BTabItem>
<BTabs>
<WorkdayListItem> at src/components/workdays/WorkdayListItem.vue
<Timecard> at src/components/timecards/Timecard.vue
<App> at src/App.vue
<Root> vue.esm.js:628
VueJS 3
change ChargesTable.vue:127
VueJS 4
setCode CostCodeField.vue:108
VueJS 12
mutations timecards.js:322
mutations timecards.js:319
wrappedMutationHandler vuex.esm.js:844
commitIterator vuex.esm.js:466
commit vuex.esm.js:465
_withCommit vuex.esm.js:624
commit vuex.esm.js:464
boundCommit vuex.esm.js:409
submit CostCodeLookup.vue:134
submit CostCodeLookup.vue:16
VueJS 33
[Vue warn]: Error in v-on handler: "TypeError: _vm._ is undefined"
found in
---> <CostCodeField> at src/components/workdays/CostCodeField.vue
<BField>
<BTableColumn>
<BTable>
<ChargesTable> at src/components/workdays/ChargesTable.vue
<BTabItem>
<BTabs>
<WorkdayListItem> at src/components/workdays/WorkdayListItem.vue
<Timecard> at src/components/timecards/Timecard.vue
<App> at src/App.vue
<Root> vue.esm.js:628
TypeError: _vm._ is undefined
change ChargesTable.vue:127
VueJS 4
setCode CostCodeField.vue:108
VueJS 12
mutations timecards.js:322
mutations timecards.js:319
wrappedMutationHandler vuex.esm.js:844
commitIterator vuex.esm.js:466
commit vuex.esm.js:465
_withCommit vuex.esm.js:624
commit vuex.esm.js:464
boundCommit vuex.esm.js:409
submit CostCodeLookup.vue:134
submit CostCodeLookup.vue:16
VueJS 33
模板中引用的任何 var 在后台都带有 this
前缀。这意味着您不能在模板中引用全局变量,除非它们在其上下文中明确声明。
简单来说,模板上下文就是一个对象。如果你没有定义一个特定的键,也没有给它分配一个特定的值,它将是 undefined
.
将全局变量暴露给模板的最简洁的方法可能是使用 computed
:
// ...
computed: {
_: () => _
}
// ...
在 Composition API 中,公开全局变量的最简单方法是将它们添加到 setup
返回的对象中:
export default {
// ...
setup() {
//...
return {
_,
//...
}
}
}
在模板中访问 _
假设您正在使用选项 API,导入 _
不会自动使其对模板可用(正如@tao 在 ). The template can only access fields exposed via the component options (e.g., data
, props
, methods
, computed
, etc.) in addition to a few allow-listed globals (Vue 2 allowed globals, Vue 3 allowed globals 中指出的那样)。
使用_.debounce
_.debounce
的第一个参数是 函数引用:
_.debounce(submit(props.row, props.index), 100) // ❌ calls `submit()`, and passes the result to _.debounce()
要创建去抖动的 submit
,请将 submit
引用作为参数传递给 _.debounce
,如下所示:
_.debounce(submit, 100)
从技术上讲,您可以立即调用去抖函数:
_.debounce(submit, 100)(props.row, props.index)
...但是不要在模板中这样做(原因见下文)。
为 v-on
使用去抖事件处理程序
当 v-on
指令(@
for shorthand)的值是一个表达式(如您的情况)时,模板编译器会自动将表达式包装在一个函数中,所以这个:
@change="_.debounce(submit, 100)"
...本质上变成:
@change="($event) => _.debounce(submit, 100)"
...这不会有任何效果,因为 debounce
不会调用包装函数本身。
您可能想在以下位置立即调用该函数:
@change="_.debounce(submit, 100)(props.row, props.index)"
...但这会在每个事件上创建一个 new 去抖动函数,这会破坏去抖动。
解决方案
在 SFC 的 <script>
部分创建一个去抖函数,然后可以将其用作 v-on
值:
选项API:
<script>
import { debounce } from 'lodash'
export default {
created() {
this.debouncedSubmit = debounce(this.submit, 100)
},
methods: {
submit(row, index) {/*...*/}
}
}
</script>
setup()
选项中的组合 API:
<script>
import { debounce } from 'lodash'
export default {
setup() {
const submit = (row, index) => {/*...*/}
return {
debouncedSubmit: debounce(submit, 100),
}
}
}
</script>
在<script setup>
中的组合API:
<script setup>
import { debounce } from 'lodash'
const submit = (row, index) => {/*...*/}
const debouncedSubmit = debounce(submit, 100)
</script>
模板:
<cost-code-field @change="debouncedSubmit(props.row, props.index)" />
我是一个有能力的 React 开发人员,但是从另一个开发人员那里继承了一个 vue.js 项目并且已经维护了几年,不幸的是我没有像我应该的那样通过个人努力来学习 vue。
我在使用 lodash 时抛出了一个奇怪的错误,我相信它不喜欢我的 _.debounce
调用
组件:
<script>
import _ from 'lodash'
import CostCodeField from '@/components/workdays/CostCodeField'
// ...
</script>
<template lang='html'>
<!-- relevant code snippet -->
<!-- ... -->
<b-table class="charges-table is-fullwidth" :data="workday.charges" :striped="true" :mobile-cards="false" :row-class="chargeClass">
<b-table-column label="Cost Code" width="260">
<b-field expanded="expanded">
<cost-code-field
:value="props.row.cost_code.number" :disabled="timecard.is_submitted || locked || isLoading(props)"
:job="props.row.job"
@input="set($event, props.index, 'cost_code')"
@change="_.debounce(submit(props.row, props.index), 100)"
></cost-code-field>
<p class="control">
<a
class="button"
@click="triggerCostCode(props.row, props.index)" :disabled="props.row.job.jd_job_number_id === undefined || timecard.is_submitted || isLoading(props)"
>
<b-icon icon="magnify"></b-icon>
</a>
</p>
</b-field>
</b-table-column>
<!-- ... -->
</b-table>
</template>
console.error
[Vue warn]: Property or method "_" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
found in
---> <ChargesTable> at src/components/workdays/ChargesTable.vue
<BTabItem>
<BTabs>
<WorkdayListItem> at src/components/workdays/WorkdayListItem.vue
<Timecard> at src/components/timecards/Timecard.vue
<App> at src/App.vue
<Root> vue.esm.js:628
VueJS 3
change ChargesTable.vue:127
VueJS 4
setCode CostCodeField.vue:108
VueJS 12
mutations timecards.js:322
mutations timecards.js:319
wrappedMutationHandler vuex.esm.js:844
commitIterator vuex.esm.js:466
commit vuex.esm.js:465
_withCommit vuex.esm.js:624
commit vuex.esm.js:464
boundCommit vuex.esm.js:409
submit CostCodeLookup.vue:134
submit CostCodeLookup.vue:16
VueJS 33
[Vue warn]: Error in v-on handler: "TypeError: _vm._ is undefined"
found in
---> <CostCodeField> at src/components/workdays/CostCodeField.vue
<BField>
<BTableColumn>
<BTable>
<ChargesTable> at src/components/workdays/ChargesTable.vue
<BTabItem>
<BTabs>
<WorkdayListItem> at src/components/workdays/WorkdayListItem.vue
<Timecard> at src/components/timecards/Timecard.vue
<App> at src/App.vue
<Root> vue.esm.js:628
TypeError: _vm._ is undefined
change ChargesTable.vue:127
VueJS 4
setCode CostCodeField.vue:108
VueJS 12
mutations timecards.js:322
mutations timecards.js:319
wrappedMutationHandler vuex.esm.js:844
commitIterator vuex.esm.js:466
commit vuex.esm.js:465
_withCommit vuex.esm.js:624
commit vuex.esm.js:464
boundCommit vuex.esm.js:409
submit CostCodeLookup.vue:134
submit CostCodeLookup.vue:16
VueJS 33
模板中引用的任何 var 在后台都带有 this
前缀。这意味着您不能在模板中引用全局变量,除非它们在其上下文中明确声明。
简单来说,模板上下文就是一个对象。如果你没有定义一个特定的键,也没有给它分配一个特定的值,它将是 undefined
.
将全局变量暴露给模板的最简洁的方法可能是使用 computed
:
// ...
computed: {
_: () => _
}
// ...
在 Composition API 中,公开全局变量的最简单方法是将它们添加到 setup
返回的对象中:
export default {
// ...
setup() {
//...
return {
_,
//...
}
}
}
在模板中访问 _
假设您正在使用选项 API,导入 _
不会自动使其对模板可用(正如@tao 在 data
, props
, methods
, computed
, etc.) in addition to a few allow-listed globals (Vue 2 allowed globals, Vue 3 allowed globals 中指出的那样)。
使用_.debounce
_.debounce
的第一个参数是 函数引用:
_.debounce(submit(props.row, props.index), 100) // ❌ calls `submit()`, and passes the result to _.debounce()
要创建去抖动的 submit
,请将 submit
引用作为参数传递给 _.debounce
,如下所示:
_.debounce(submit, 100)
从技术上讲,您可以立即调用去抖函数:
_.debounce(submit, 100)(props.row, props.index)
...但是不要在模板中这样做(原因见下文)。
为 v-on
使用去抖事件处理程序
当 v-on
指令(@
for shorthand)的值是一个表达式(如您的情况)时,模板编译器会自动将表达式包装在一个函数中,所以这个:
@change="_.debounce(submit, 100)"
...本质上变成:
@change="($event) => _.debounce(submit, 100)"
...这不会有任何效果,因为 debounce
不会调用包装函数本身。
您可能想在以下位置立即调用该函数:
@change="_.debounce(submit, 100)(props.row, props.index)"
...但这会在每个事件上创建一个 new 去抖动函数,这会破坏去抖动。
解决方案
在 SFC 的 <script>
部分创建一个去抖函数,然后可以将其用作 v-on
值:
选项API:
<script>
import { debounce } from 'lodash'
export default {
created() {
this.debouncedSubmit = debounce(this.submit, 100)
},
methods: {
submit(row, index) {/*...*/}
}
}
</script>
setup()
选项中的组合 API:
<script>
import { debounce } from 'lodash'
export default {
setup() {
const submit = (row, index) => {/*...*/}
return {
debouncedSubmit: debounce(submit, 100),
}
}
}
</script>
在<script setup>
中的组合API:
<script setup>
import { debounce } from 'lodash'
const submit = (row, index) => {/*...*/}
const debouncedSubmit = debounce(submit, 100)
</script>
模板:
<cost-code-field @change="debouncedSubmit(props.row, props.index)" />