在Vue 3的 composition api 中,Computed 是如何工作的?

回答 2 浏览 2.4万 2022-03-13

我正试图让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)

我做错了什么呢?

Artur Müller Romanov 提问于2022-03-13
2 个回答
#1楼 已采纳
得票数 23

<template>中,。

仅限getter:

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

getter 和 setter:

  • <input v-model="myVal">

重要:不要使用myVal.get()myVal.set(value)!使用:

  • 获取:myVal
  • 设置(分配):myVal = value

<script setup>中:

仅限getter:

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

Getter & setter:

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
  }
})

请记住,你总是可以在reactive里面使用computed。例子。

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会警告你(the computed wrapper is unnecessary)。
  • 当传递给它一个包含循环依赖关系的引用(例如:一个组件实例)时,Vue会再次警告你,并建议你使用shallowRefmarkRaw
tao 提问于2022-03-13
tao 修改于2022-10-09
如何在脚本部分而不是在模板中访问myVal?Bill 2022-08-05
@Bill 在代码中访问计算的属性值,如setup函数,使用计算的属性名称,后加.value,例如myVal.valueMaksim Shamihulau 2022-10-31
#2楼
得票数 1

计算过的属性作为字段出现。无论你是传入一个函数(如computed(() => /*...*/))还是传入一个带有get()方法的对象(如果你不提供set()方法,这里是等效的)。

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

<template>
  <div>
    <p>{{ whatever }}</p>
  </div>
</template>
Jeff Bowman 提问于2022-03-13
Jeff Bowman 修改于2022-03-13