如何在计算中访问 $refs
?第一次运行计算属性时它总是未定义。
打算在这里回答我自己的问题,我在其他任何地方都找不到满意的答案。有时您只需要访问 dom 元素即可进行一些计算。希望这对其他人有帮助。
安装组件后,我不得不欺骗 Vue 更新计算属性。
Vue.component('my-component', {
data(){
return {
isMounted: false
}
},
computed:{
property(){
if(!this.isMounted)
return;
// this.$refs is available
}
},
mounted(){
this.isMounted = true;
}
})
我认为引用 Vue js guide 很重要:
$refs 仅在组件被渲染后才被填充,并且它们不是响应式的。它仅作为直接子操作的逃生舱口 - 您应该避免从模板或计算属性中访问 $refs。
因此,这不是您应该做的事情,尽管您总是可以绕过它。
如果您在 v-if
之后需要 $refs
,则可以使用 updated()
挂钩。
<div v-if="myProp"></div>
updated() {
if (!this.myProp) return;
/// this.$refs is available
},
v-if
条件合并到 computed
的逻辑中,以便将它们注册为依赖项。正是对具有 ref
并由 v-if
切换的元素的好奇心的答案
我刚遇到同样的问题,并意识到这是计算属性不起作用的情况。
根据当前文档 (https://v2.vuejs.org/v2/guide/computed.html):
“[...]我们可以将相同的函数定义为方法,而不是计算属性。对于最终结果,这两种方法确实完全相同。但是,不同之处在于计算属性是基于它们的响应式缓存的依赖关系。计算属性只会在其某些反应性依赖关系发生变化时重新评估“
因此,在这些情况下(可能)发生的事情是完成组件的已安装生命周期并设置 refs 并不算作对计算属性的依赖项的反应性更改。
例如,在我的情况下,当我的参考表中没有选定的行时,我有一个需要禁用的按钮。因此,此代码将不起作用:
<button :disabled="!anySelected">Test</button>
computed: {
anySelected () {
if (!this.$refs.table) return false
return this.$refs.table.selected.length > 0
}
}
您可以做的是将计算属性替换为方法,并且应该可以正常工作:
<button :disabled="!anySelected()">Test</button>
methods: {
anySelected () {
if (!this.$refs.table) return false
return this.$refs.table.selected.length > 0
}
}
data()
、updated()
和其他部分。干净简洁。
对于像我这样只需要将一些数据传递给 prop 的其他用户,我使用 data
而不是 computed
Vue.component('my-component', {
data(){
return {
myProp: null
}
},
mounted(){
this.myProp= 'hello'
//$refs is available
// this.myProp is reactive, bind will work to property
}
})
如果需要,请使用属性绑定。 :disabled 道具在这种情况下是被动的
<button :disabled="$refs.email ? $refs.email.$v.$invalid : true">Login</button>
但是要检查两个字段,我发现没有其他方法可以作为虚拟方法:
<button :disabled="$refs.password ? checkIsValid($refs.email.$v.$invalid, $refs.password.$v.$invalid) : true">
{{data.submitButton.value}}
</button>
methods: {
checkIsValid(email, password) {
return email || password;
}
}
我遇到了类似的情况,我用以下方法修复了它:
data: () => {
return {
foo: null,
}, // data
然后你观察变量:
watch: {
foo: function() {
if(this.$refs)
this.myVideo = this.$refs.webcam.$el;
return null;
},
} // watch
请注意评估 this.$refs
是否存在的 if
,当它发生变化时,您将获得数据。
我所做的是将引用存储到数据属性中。然后,我在挂载事件中填充此数据属性。
data() {
return {
childComps: [] // reference to child comps
}
},
methods: {
// method to populate the data array
getChildComponent() {
var listComps = [];
if (this.$refs && this.$refs.childComps) {
this.$refs.childComps.forEach(comp => {
listComps.push(comp);
});
}
return this.childComps = listComps;
}
},
mounted() {
// Populates only when it is mounted
this.getChildComponent();
},
computed: {
propBasedOnComps() {
var total = 0;
// reference not to $refs but to data childComps array
this.childComps.forEach(comp => {
total += comp.compPropOrMethod;
});
return total;
}
}
另一种方法是完全避免 $refs 并且只订阅来自子组件的事件。
它需要子组件中的显式设置器,但它是反应式的,不依赖于挂载时间。
父组件:
<script>
{
data() {
return {
childFoo: null,
}
}
}
</script>
<template>
<div>
<Child @foo="childFoo = $event" />
<!-- reacts to the child foo property -->
{{ childFoo }}
</div>
</template>
子组件:
{
data() {
const data = {
foo: null,
}
this.$emit('foo', data)
return data
},
emits: ['foo'],
methods: {
setFoo(foo) {
this.foo = foo
this.$emit('foo', foo)
}
}
}
<!-- template that calls setFoo e.g. on click -->
不定期副业成功案例分享