在Vue.js 3中使用TypeScript解构和重新分配属性

q0qdq0h2  于 2023-11-21  发布在  Vue.js
关注(0)|答案(1)|浏览(176)

我有一个有输入参数的组件。我试图在properties对象上使用解构赋值,并将变量重新赋值为不同的名称:

<script setup lang="ts">
const { modelValue: isSelected, date1: inputDate1 } = defineProps({
  modelValue: Boolean,
  date1: String
})

console.log(isSelected)

const date1 = 'abc'
console.log(date1)
</script>

<template>
  <div v-if="isSelected">Selected!</div>
</template>

字符串
在上面的代码中,变量modelValue被重新分配给isSelecteddate1被重新分配给inputDate1
代码产生两个问题。

编辑const date1 = 'abc'行出错

重复键“date 1”。可能会导致脚本或模板标记中的名称冲突。eslintvue/no-dupe-keys
这是一个完全虚假的错误。如果你重写代码如下:

const date2 = 'abc'
console.log(date1)


那么你会在console.log(date1)行遇到另一个错误:
找不到名称“日期1”。您的意思是“日期2”吗?ts(2552)
所以很明显没有其他变量与date1同名。那么最初的问题是什么?为什么编译器会抱怨同名?
此外,为了累加,console.log(date1)行在运行时输出正确的值。

运行时模板抛出异常/警告

[Vue warn]:在渲染期间访问了属性“isSelected”,但未在示例上定义。
我不明白这怎么可能...台词是:

console.log(isSelected)


输出正确的值(truefalse)。
所以,我还是不明白问题出在哪里。如果我去掉了解构变量的重新赋值,那么代码就不会出错:

<script setup lang="ts">
const { modelValue } = defineProps({
  modelValue: Boolean
})
console.log(modelValue)
</script>

<template>
  <div v-if="modelValue">Selected!</div>
</template>


console.log(modelValue)输出与之前相同的精确值。
console.log(typeof modelValue)打印boolean
console.log(typeof isSelected)也可以打印boolean
那有什么问题

oknwwptz

oknwwptz1#

首先要做的是:
你不能只解构props。defineProps()返回的props对象是React性的,解构一个React性对象会破坏React性;解构后的变量将被赋予属性的当前值(因为对象是一个代理,只有属性访问被监控)。你必须使用toRefs()将它转换为refs对象,然后你可以解构它。
好吧,实际上,我撒了一点谎。“React性属性解构”(文档页面上说React性转换已被弃用,但这个特定功能已被分离)现在是一个东西,这意味着本质上编译器重写了

const { prop: foo } = defineProps({ prop: String })
console.log(foo)

字符串

const __props = defineProps({ prop: String })
console.log(__props.prop)


有些人喜欢这样。就我个人而言,我觉得这非常不直观和混乱。每个人都有自己的。
在上面的例子中,foo是一个字符串,但它是秘密React的(据我所知,这是“裸”React原语脚本块中唯一的情况)。
简化第一个代码块:

<script setup lang="ts">
const { date1: inputDate1 } = defineProps({
  date1: String
})

const date1 = 'abc'
console.log(date1)
</script>


所以,你有这个错误:
重复键“date 1”。可能会导致脚本或模板标记中的名称冲突。eslintvue/no-dupe-keys
Props在模板中自动解包。也就是说,你可以像访问window上的属性一样访问它们,而不需要显式指定window.;它们在顶级作用域中。
props有一个名为date1的prop,展开意味着它将在模板中处于顶层。然后定义一个名为date1的变量,它也将在模板中处于顶层。这两个标识符可能会冲突,这就是ESLint警告的内容。
然后,您的示例编辑:

const date2 = 'abc'
console.log(date1)


新的错误:
找不到名称“日期1”。您的意思是“日期2”吗?ts(2552)
这是因为props只会在模板中自动解包,而不会在脚本中自动解包,所以date1没有在模板中定义。
此外,为了累加,console.log(date1)行在运行时输出正确的值。
它将输出组件创建时的prop值。但它不是响应式的;即使它是响应式的,console.log()也不会再次运行。(好吧,它是部分响应式的;请参阅本答案的第一部分。)
下一个错误:
[Vue warn]:在渲染期间访问了属性“isSelected”,但未在示例上定义。
恐怕我不能复制这个。
可能是HMR问题/故障?
我不知道你的Vue版本或配置,所以我不能说更多的细节,比如我无法复制的错误。如果你想按下这一点,请将复制的完整代码和配置添加到你的答案中,最好是Vue Playground或StackBlitz项目或类似项目的链接。
我在测试的时候做了一个Vue Playground。你可以在里面玩,也可以查看编译好的代码。

相关问题