Vue.js 2.6.14中如何在setup()内访问data()中的属性?
问题解决:Vue 2.6.14中setup无法传入data里的form.style到vue-query查询函数
你遇到的核心问题是Vue 2的composition-api中,setup函数内无法直接通过this访问选项式API里的data属性——setup的执行时机早于组件实例初始化完成,且它本身没有绑定组件的this上下文,所以this.form.style根本取不到正确的值。
下面给两种可行的解决方式:
方式一:通过getCurrentInstance访问组件实例
借助@vue/composition-api提供的getCurrentInstance方法获取组件实例,进而访问data中的form.style,同时要确保查询的依赖项能被vue-query正确追踪:
<script lang="ts"> import { useQuery, getCurrentInstance } from '@vue/composition-api'; import type { ComponentInstance } from '@vue/composition-api'; const fetchRandomImg = async (style: FormType["style"]) => { const params = new URLSearchParams(); if (style.type === "grayscale") { params.append("grayscale", ""); } else if (style.type === "blur") { params.append("blur", style.blurValue.toString()); } const response = await fetch( `https://picsum.photos/150?${params.toString()}` ); const blob = await response.blob(); return URL.createObjectURL(blob); }; export default Vue.extend({ data() { return { form: { style: { type: "normal", blurValue: 1 }, // ...其他属性 } } }, setup() { // 获取组件实例 const instance = getCurrentInstance() as ComponentInstance; // 通过实例访问data中的form.style const formStyle = instance.proxy?.form.style; const { data: randomImg, refetch: refetchRandomImg } = useQuery( // 把style的关键属性作为查询键,确保变化时触发重查 ["randomImage", formStyle.type, formStyle.blurValue], () => fetchRandomImg(formStyle), { refetchOnWindowFocus: false, } ); return { randomImg, refetchRandomImg }; }, }) </script>
注意:查询键不能直接传入对象(form.style),因为对象的引用变化才会触发重查,而修改对象内部属性不会触发。所以建议把对象的具体属性值作为查询键的一部分,比如type和blurValue,这样当这些值变化时,vue-query会自动重新发起请求。
方式二:将form.style移到setup中用reactive定义
更符合组合式API的写法是把响应式数据直接定义在setup里,避免选项式和组合式API混合带来的上下文问题:
<script lang="ts"> import { useQuery, reactive } from '@vue/composition-api'; const fetchRandomImg = async (style: FormType["style"]) => { // 原fetch逻辑不变 const params = new URLSearchParams(); if (style.type === "grayscale") { params.append("grayscale", ""); } else if (style.type === "blur") { params.append("blur", style.blurValue.toString()); } const response = await fetch( `https://picsum.photos/150?${params.toString()}` ); const blob = await response.blob(); return URL.createObjectURL(blob); }; export default Vue.extend({ setup() { // 用reactive定义响应式的form数据 const form = reactive({ style: { type: "normal", blurValue: 1 }, // ...其他属性 }); const { data: randomImg, refetch: refetchRandomImg } = useQuery( // 同样用具体属性作为查询键 ["randomImage", form.style.type, form.style.blurValue], () => fetchRandomImg(form.style), { refetchOnWindowFocus: false, } ); // 把form也返回,供模板使用 return { randomImg, refetchRandomImg, form }; }, }) </script>
这种写法更清晰,响应式依赖追踪也更可靠,推荐优先使用。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

