从可组合项访问 ref 值(第 2 部分)
Accessing ref values from composable (part 2)
这是我上一个问题的后续问题:
这是我的应用程序代码:
<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
函数内,控制台显示函数中正确的 return 字典。
但是,在 watchEffect
函数之外,控制台只显示在 watchEffect()
调用之前定义的空 ref({})
。
它是由setup()
return编辑并显示在模板中的空字典。
如何从 watchEffect
中获取 setup()
到 return 的 reversed_names
?
const reversed_names
outside 和 inside watchEffect
函数作用域不同,不相关的变量。 reversed_names
内部函数作用域遮蔽了父作用域中的另一个作用域。
ref 是一种模式,它在 JavaScript 中利用了对象通过引用传递,而不是通过值传递。这意味着它是一个 ref 而不是需要在每个需要保留反应性的地方传递的值,并注意它在 Vue 应用程序的上下文中使用。永远不要重新分配包含 ref 的变量,而是 value
属性 需要重新分配。
reverseNames
不是通用的辅助函数,而是特定于 Vue 的,因此可以接受引用。 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
调用期间无法跟踪的更改,这将是有意义的,类似于 。但它是同步的,只影响一个 ref,所以没有理由使用反应性。相反,可以将反应性提升给调用者:
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));
这是我上一个问题的后续问题:
这是我的应用程序代码:
<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
函数内,控制台显示函数中正确的 return 字典。
但是,在 watchEffect
函数之外,控制台只显示在 watchEffect()
调用之前定义的空 ref({})
。
它是由setup()
return编辑并显示在模板中的空字典。
如何从 watchEffect
中获取 setup()
到 return 的 reversed_names
?
const reversed_names
outside 和 inside watchEffect
函数作用域不同,不相关的变量。 reversed_names
内部函数作用域遮蔽了父作用域中的另一个作用域。
ref 是一种模式,它在 JavaScript 中利用了对象通过引用传递,而不是通过值传递。这意味着它是一个 ref 而不是需要在每个需要保留反应性的地方传递的值,并注意它在 Vue 应用程序的上下文中使用。永远不要重新分配包含 ref 的变量,而是 value
属性 需要重新分配。
reverseNames
不是通用的辅助函数,而是特定于 Vue 的,因此可以接受引用。 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
调用期间无法跟踪的更改,这将是有意义的,类似于
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));