将计算属性嵌套在一个对象中以进行代码维护 (Vue)
Posted
技术标签:
【中文标题】将计算属性嵌套在一个对象中以进行代码维护 (Vue)【英文标题】:Nesting computed properties in one object for code maintenance (Vue) 【发布时间】:2021-07-19 16:50:45 【问题描述】:就清洁逻辑和维护而言,以下场景的最佳做法是什么?
我的用例是有一个查询对象,它的参数是一堆text
和之前查询的结果。
我最初认为代码结构如下(见伪代码):
data()
return
queries :
q1 : data: `$this.text + $this.formerResults`
// q2, q3...
,
formerResults : ''
,
methods :
makeQuery : function()
let vm = this;
axios( /* param of the query, data : this.queries.q1 */ )
.then((response) => vm.formerResults += /* add the results */ )
这个问题是formerResults
确实被附加了,但在下一个查询q1
中注入时结果为undefined
。我不知道为什么,但通过将查询 q1
构造为计算属性解决了这个问题。
您能说出为什么在使用属性时逻辑会失败,并且可以使用计算属性吗?
computed:
q1()
return
// same as above
// q2, q3 ...
并在我的方法中调用它:
axios( /* param of the query, data : this.q1 */ );
可以看到text
和formerResults
这两个参数都通过了。
但是,我想将查询(q1、q2、q3..)分组在同一个对象 queries
下,就像在 data()
中一样:这是为了代码清晰,因为所有这些查询都是针对相同的url,我可能还有其他的。
但是尝试:
computed:
computedQueries :
q1()
return
// same as above
,
// q2, q3 ...
并在我的方法中这样称呼它:
axios( /* param of the query, data : this.computedQueries.q1 */ )
会导致vue报错:
Error in v-on handler: "TypeError: Cannot read property 'q1' of undefined"
您能否说明如何将计算属性分组(或嵌套)到一个对象中?
我是否真的需要在我的示例中使用计算属性,以避免在下一个查询中未定义 formerResults
?你能建议如何保持代码干净吗?
【问题讨论】:
【参考方案1】:有几件事情需要考虑。
第一个问题:你能说出为什么在使用属性时逻辑会失败,并且可以使用计算属性吗?
data()
生命周期方法返回的属性在某种意义上是反应性的,每次更改它们时,Vue 都会触发新的渲染周期。但这并不意味着每个反应属性都会自动更新。你仍然需要更新它。所以,当你这样做时:
data()
return
queries :
q1 :
data: `$this.text + $this.formerResults`
,
formerResults : ''
,
Vue.js 尚未将这些反应属性添加到 this
实例。当然,此时this.formerResults
将是未定义的,this.queries.q1
会将其视为未定义。
为什么以及何时使用计算属性?
你是正确的使用计算属性。如果您需要自动建立依赖关系并且您不需要为某些属性设置setter(即自己设置值),那么您必须使用计算属性。
在您的情况下,查询 - q1
、q2
等必须在 formerResults
更改时自动更新。为此,您将使用计算属性。
如何将计算属性分组(或嵌套)到一个对象中?
您声明计算属性的方式是错误的,因此您会看到错误。 嵌套计算属性本身没有概念,但您可以创建一个单个复杂对象,它是多次计算的结果,并生成包含所有数据的单个值你需要:
computed:
queries: function ()
return
q1: data: `$this.text + $this.formerResults`,
q2: /* Some other stuff */,
//... q3, q4, etc.
;
每次 text
和 formerResults
被代码的某些部分更改时,您的 queries
对象将被重新计算。这样不会有任何性能损失。
我真的需要在我的示例中使用计算属性,以避免在下一个查询中未定义 formerResults
吗?你能建议如何保持代码干净吗?
使用计算属性是实现反应性的最简洁方式。在我看来,其他所有选择都很麻烦。例如,您可以使用 watchers 执行相同的操作,但它并不干净。
data()
return
queries:
q1: data: '' ,
// q2, q3, ...
,
formerResults: ''
,
watch:
formerResults: function()
this.queries =
q1: data: `$this.text + $this.formerResults`
// q2, q3, ...
;
,
text: function()
this.queries =
q1: data: `$this.text + $this.formerResults`
// q2, q3, ...
;
【讨论】:
非常感谢 Harshal 的简洁回答并展示了如何“嵌套”计算属性。只有一件事还不清楚:为什么formerResults
没有反应?我在time_1传递的参数text
和formerResults
分别是一个字符串(作为prop传递)和一个空字符串''
。查询结果存储在formerResults (vm.formerResults += /* add the results */
),我想在time_2 和text
一起传递。那么为什么在 time_2 formerResults
被传递为 undefined
呢?你能澄清一下吗?
@user305883 在评估q1
时,formerResults
本身是未定义的,当您开始累积结果时,undefined
会结转。此外,仅在 data
函数中定义依赖于 formerResults
的 q1
不会使 q1
反应。你仍然需要设置观察者。当 Vue.js 说它是响应式的时,这意味着每当 q1
或 formerResults
发生变化时,模板都会再次呈现。这并不意味着当formerResults
更改时,会自动更新q1
。为此,使用了计算属性。以上是关于将计算属性嵌套在一个对象中以进行代码维护 (Vue)的主要内容,如果未能解决你的问题,请参考以下文章