从Composable访问引用值(第2部分)
这是我之前问题的后续问题: Accessing ref values from composable
以下是我的应用程序代码:
<template>
{{ reversed_names }}
</template>
<script>
import { ref, watchEffect } from "@vue/runtime-core";
import getData from "./composables/getData";
import reverseNames from "./composables/reverseNames";
export default {
name: "App",
setup() {
var filenames = ["test1.json", "test2.json"];
const { names_data, error, load_data } = getData(filenames);
load_data();
const reversed_names = ref({});
watchEffect(() => {
const reversed_names = reverseNames(names_data.value);
console.log("revnames inside watchEffect", reversed_names.value);
});
console.log("revnames outside watchEffect", reversed_names);
return { names_data, reversed_names };
},
};
</script>
下面是reverseNames
函数:
import { ref } from "@vue/runtime-core";
const reverseNames = (names_data) => {
const reverse_names = ref({})
var filenames = Object.keys(names_data)
for (let f in filenames) {
var filename = filenames[f]
reverse_names.value[filename] = {}
var members = names_data[filename]["members"]
for (let n in members) {
let name = members[n];
var reverseName = name.split("").reverse().join("");
reverse_names.value[filename][name] = reverseName
}
}
return reverse_names
};
export default reverseNames
watchEffect
存在,因此一旦从文件加载数据(请参阅上面的链接问题),我就可以使用names_data
。
在调用reverseNames
之前,代码运行得很好。
names_data.value
包含以下内容:
{ "test1.json":
{ "members":
{ "0": "Alice",
"1": "Bob",
"2": "Charlie"
}
},
"test2.json":
{ "members":
{ "0": "David",
"1": "Elizabeth",
"2": "Fred"
}
}
}
这里是令人困惑的部分:
在watchEffect
函数中,控制台显示该函数的正确返回词典。
但是,在watchEffect
函数外部,控制台仅显示在watchEffect()
调用之前定义的空ref({})
。
setup()
返回并显示在模板中的空词典。
如何才能使setup()
从watchEffect
内部返回reversed_names
?
解决方案
const reversed_names
函数作用域外部和内部watchEffect
是不同且无关的变量。reversed_names
函数作用域内部隐藏了父作用域中的另一个函数。
value
属性。
reverseNames
不是通用的助手函数,但特定于Vue,因此可以接受ref。reverse_names
没有起到很好的作用,因为它不会传递到任何地方,因此不会从使用ref模式中受益。可能是:
const reverseNames = (namesDataRef) => {
const reverse_names = {} // not a ref
var filenames = Object.keys(namesDataRef.value)
reverse_names[filename] = {}
...
reverse_names[filename][name] = reverseName
}
}
namesDataRef.value = reverse_names;
// doesn't need to return anything because it uses refs
}
和
const reversed_names = ref({});
watchEffect(() => {
reverseNames(reversed_names);
console.log("revnames inside watchEffect", reversed_names.value);
});
这是反模式。如果reverseNames
使用的是异步副作用或任何可能触发在reverseNames
调用期间无法跟踪的更改的内容,这将是有意义的,类似于another question。但它是同步的,只影响一个裁判,所以它没有理由使用反应性。相反,可以将反应性提升到调用方:
const reverseNames = (namesData) => {
const reverse_names = {} // not a ref
...
return reverse_names
}
和
const reversed_names = ref({});
watchEffect(() => {
reversed_names.value = reverseNames(names_data.value);
console.log("revnames inside watchEffect", reversed_names.value);
});
没有副作用(console.log
),将不需要watchEffect
,它可以是计算的ref:
const reversed_names = computed(() => reverseNames(names_data.value));
相关文章