Computed 如何在 Vue 3 脚本设置中工作?

我试图让 computed<script setup> 中工作:

<template>
  <div>
    <p>{{ whatever.get() }}</p>
  </div>
</template>

<script setup>
import {computed} from "vue";

const whatever = computed({
    get() {
        console.log('check')
        return 'check?';
    }
})
</script>

console.log() 通过,但 return 语句似乎抛出错误:

check
Vue warn]: Unhandled error during execution of render function 
  at <Cms>
Uncaught TypeError: $setup.whatever.get is not a function
at Proxy.render (app.js?id=d9e007128724c77a8d69ec76c6c081a0:39550:266)
at renderComponentRoot (app.js?id=d9e007128724c77a8d69ec76c6c081a0:25902:44)
at ReactiveEffect.componentUpdateFn [as fn] (app.js?id=d9e007128724c77a8d69ec76c6c081a0:30019:57)
at ReactiveEffect.run (app.js?id=d9e007128724c77a8d69ec76c6c081a0:23830:29)
at setupRenderEffect (app.js?id=d9e007128724c77a8d69ec76c6c081a0:30145:9)
at mountComponent (app.js?id=d9e007128724c77a8d69ec76c6c081a0:29928:9)
at processComponent (app.js?id=d9e007128724c77a8d69ec76c6c081a0:29886:17)
at patch (app.js?id=d9e007128724c77a8d69ec76c6c081a0:29487:21)
at render (app.js?id=d9e007128724c77a8d69ec76c6c081a0:30630:13)
at mount (app.js?id=d9e007128724c77a8d69ec76c6c081a0:28882:25)

我究竟做错了什么?

stack overflow How does Computed work in Vue 3 script setup?
原文答案
author avatar

接受的答案

<template> 中:

仅吸气剂:

  • {{ myVal }}
  • <p v-text="myVal" />

获取器和设置器:

  • <input v-model="myVal">

重要提示: **not** 使用 myVal.get()myVal.set(value) !利用:

  • 得到: myVal

  • 设置(赋值): myVal = value

    • *

<script setup> 中:

仅吸气剂:

const someReactiveRef = ref(null)
const myVal = computed(() => someReactiveRef.value)

获取器和设置器:

const someReactiveRef = ref(null)

const myVal = computed({
  get() {
    return someReactiveRef.value
  },
  set(val) {
    someReactiveRef.value = val
  }
})
// myVal can now be used in `v-model`

当响应式引用来自 reactive() 对象的属性时,您不需要在 setter 或 getter 中使用 .value 。例子:

const state = reactive({
  someProp: null
})

const myVal = computed({
  get() {
    return store.someProp
  },
  set(val) {
    store.someProp = val
  }
})

请记住,您始终可以在 computed 中使用 reactive 。例子:

const { createApp, reactive, computed, toRefs } = Vue
createApp({
  setup() {
    const state = reactive({
      firstName: 'John W.',
      lastName: 'Doe',

      // getter + setter
      fullName: computed({
        get() {
          return [state.firstName, state.lastName].join(' ')
        },
        set(val) {
          const [last, ...rest] = val.split(' ').reverse()
          state.firstName = rest.reverse().join(' ')
          state.lastName = last
        }
      }),

      // getter only:
      name: computed(() => state.fullName)
    })
    return toRefs(state)
  }
}).mount('#app')
<script src="https://unpkg.com/vue@3.2.40/dist/vue.global.prod.js"></script>
<div id="app">
  <input v-model="firstName" />
  <input v-model="lastName" />
  <input v-model="fullName" />
  <pre v-text="{ firstName, lastName, fullName, name }"></pre>
</div>

重要笔记:

  • 当传递一个对 computed 的非响应式引用时,Vue 会警告你(计算的包装器是不必要的)。
  • 当传递一个包含循环依赖的引用(例如:组件实例)时,Vue 会再次警告你并建议使用 shallowRefmarkRaw

答案:

作者头像

Computed properties appear as fields. 无论你传入一个函数(如在 computed(() => /*...*/) 中)还是一个具有 get() 方法的对象(如果你不提供 set() 方法,这在此处等效)都是如此)。

您的模板应该简单地使用计算属性的名称,这里是 whatever

<template>
  <div>
    <p>{{ whatever }}</p>
  </div>
</template>