为什么一个vue组件属性需要冒号作为前缀?

Why does a vue component property need to be prefixed by colon?

所以,在Vue组件中,当你在模板中写标签时,你可以指定一个静态参数,就像在普通的XML中一样,或者,你可以通过在前面添加冒号来指定一个响应式参数参数名称。

现在,我偶然发现了 this Vuetify 示例,并使用了 v-menu 组件。例如,这个组件有一个 close-on-click 属性,在这个例子中,它被标记为反应性的。这是合乎逻辑的,因为在此示例中,当您更改开关的位置时,此 属性 会更新。

不过,您也可以指定一个常量。而且,由于常量值不会改变,在 Vue 中,它们不必是反应式的。但是,在这里,如果我指定 close-on-click(不带冒号),它将无法正常工作。它不会读取这个 属性 除非它是反应性的。

我的问题是,为什么这个 属性 需要标记为反应式,即使我们指定一个常量作为它的值?

因此,更确切地说:为什么 <v-menu close-on-click=false 不起作用,但 <v-menu :close-on-click="false" 起作用?

false 是一个常量,因此,这个 属性 不应标记为反应式。

tldr:

反应性使用绑定来更新模板,但并非所有绑定都必须是反应性的。这个答案试图阐明这两个相关但独立的概念之间的区别。


简答:

不需要“反应性”。需要"bound"(计算为JavaScript表达式)。使用...

<v-menu close-on-click="false" />

...将字符串 "false" 绑定到 属性 close-on-click。由于 属性 需要一个布尔值,因此 "false" 的计算结果为 true,因为除空字符串 ("") 之外的任何字符串在转换为 [= 时计算结果为 true 20=]。还有...

<v-menu :close-on-click="false" />

绑定 JavaScript 表达式 false 的结果,其计算结果为 false,显然。

这与反应无关。它与评估作为字符串(没有 :)或作为 JavaScript 表达式(有 :)传递给属性的值有关。


long/proper 答案:

您混淆了两个相似但不同的概念。

其中之一是 "reactivity" and the other is "dynamically binding" 通过使用 JavaScript 表达式。

属性前面的冒号(:)用于动态绑定,不用于反应。

:v-bind: 的 shorthand。

将绑定视为 {{ }}(小胡子)模板绑定的替代方案,但专为元素属性和道具而设计(因为小胡子在属性中不起作用)。正如 mustache 语法一样,v-bind: 可用于将反应式和 non-reactive 表达式绑定到模板。
Non-reactive 当表达式的结果改变时,表达式不会更新模板。


Reactivity,在 Vue 中,是一个术语,用于命名 Vue 检测数据结构变化并在检测到变化时使用这些数据结构更新表达式的“神奇”能力.

反应对象的几个例子:

  • Options中data()函数返回的对象API
  • Vue.observable(), 在 Vue 中 2.x
  • 在 Vue 3 中(或在 Vue 2 中使用 @vue/composition-api 插件时),ref()reactive() 函数的结果。
  • 列表还在继续(例如:在 piniavuex$router/$route 等中存储状态)但是,在幕后,所有反应对象都是上述情况之一的实现。

实际上,反应性是一个包装器。在 Vue2 中,如果你检查一个反应对象,你会注意到它上面有一个 [__ob__: Observer] 属性。那就是反应性观察者。

在Vue3中,它不再是一个Observer,而是一个Proxy
主要区别在于,在 Vue3 中,原始对象(代理的目标)几乎没有受到影响。此外,使用代理进行更改检测更加直接。

如果有兴趣,网上有很多材料,通常标记为 “高级 vue 反应性”“深度 vue 反应性” .


为了更清楚地理解,这里有一个绑定两个表达式的示例:一个是静态的,一个是反应性的。显然,只有反应式的在结果改变时更新模板:

const staticObj = { foo: 'bar' };
const reactiveObj = Vue.observable({ foo: 'bar' });

new Vue({
  el: '#app',
  computed: {
    staticFoo() {
      // won't update, because staticObj is static
      return staticObj.foo;
    },
    reactiveFoo() {
      // will update, because reactiveObj is reactive
      return reactiveObj.foo;
    }
  },
  methods: {
    changeFoo() {
      staticObj.foo = 'BAZ';
      reactiveObj.foo = 'BAZ';
      console.log('staticObj is now:', { ...staticObj }, ', but the template did not update!');
    },
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
<div id="app">
  Static foo: {{ staticFoo }}<br>
  Reactive foo: {{ reactiveFoo }}
  <br>
  <button @click="changeFoo">Change foo</button>
</div>

注意: 尽管我在上面的示例中使用了 {{}}(小胡子语法),但当您使用 v-bind: 或更短的语法时也会发生同样的事情元素属性中的版本 :

我希望这能澄清 “反应性”“绑定”.

之间的区别