v-model的变化

vue2有两种方式实现双向数据绑定,一种是v-model 一种是 .sync (第二种是自定义组件中实现props双向数据绑定),在vue3中,去掉啦 .sync 修饰符,只需要使用v-model 进行双向数据绑定。

为了让v-model更好的针对多个属性进行双向绑定,vue3作出了以下修改

绑定属性名的变化

当对自定义组件使用v-model指令时,绑定的属性名由原来的value变为modelValue,事件名由原来的input变为update:modelValue

  1. <!-- vue2 -->
  2. <ChildComponent :value="pageTitle" @input="pageTitle = $event" />
  3. <!-- 简写为 -->
  4. <ChildComponent v-model="pageTitle" />
  5. <!-- vue3 -->
  6. <ChildComponent
  7. :modelValue="pageTitle"
  8. @update:modelValue="pageTitle = $event"
  9. />
  10. <!-- 简写为 -->
  11. <ChildComponent v-model="pageTitle" />

去掉了.sync修饰符,它原本的功能由v-model的参数替代

  1. <!-- vue2 -->
  2. <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
  3. <!-- 简写为 -->
  4. <ChildComponent :title.sync="pageTitle" />
  5. <!-- vue3 -->
  6. <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
  7. <!-- 简写为 -->
  8. <ChildComponent v-model:title="pageTitle" />

可以绑定多个v-model

  1. <check-editor
  2. v-for="item in products"
  3. :key="item.id"
  4. v-model="item.sell" // 绑定默认的
  5. v-model:title.trim="item.title"
  6. ></check-editor>

允许自定义 v-model 的修饰符 vue2无此功能

模板的变化 - 图1
示例

  1. export default {
  2. props: {
  3. title: String,
  4. /** 接收自定修饰符*/
  5. titleModifiers: {
  6. default: () => ({}),
  7. }
  8. },
  9. setup(props, context) {
  10. /**输入框修改事件 */
  11. const handleInput = (e) => {
  12. let value = e.target.value;
  13. if(props.titleModifiers.trim) {
  14. value = value.trim()
  15. }
  16. context.emit('update:title', value);
  17. };
  18. return {
  19. handleInput,
  20. };
  21. },
  22. };

v-if 和v-for的变化

vue2 中

  1. <div v-for="item in data" :key="item.id" v-if="是否显示"></div>

在vue2中之所以不建议使用这种方式,是因为 v-for 的优先级会比 v-if 的高,故会先遍历后才会·v-if 当不显示时又会触发响应式数据,这样的效率会很慢

在vue3中

v-if 的优先级会比 v-for 的高,会优先进行 v-if ,故会先进行 v-if 之后才会以进行v-for
但是依旧不推荐上面的那种写法
推荐使用计算属性,使用v-for 遍历需要的数据(数据是通过计算属性筛选出来的)

key

当使用<template>进行v-for循环时,需要把key值放到<template>中,而不是它的子元素中

在 Vue 2.x 中 <template> 标签不能拥有 key。不过你可以为其每个子节点分别设置 key

  1. <!-- Vue 2.x -->
  2. <template v-for="item in list">
  3. <div :key="item.id">...</div>
  4. <span :key="item.id">...</span>
  5. </template>

在 Vue 3.x 中 key 则应该被设置在 <template> 标签上。

  1. <!-- Vue 3.x -->
  2. <template v-for="item in list" :key="item.id">
  3. <div>...</div>
  4. <span>...</span>
  5. </template>

类似地,当使用 <template v-for> 时存在使用 v-if 的子节点,key 应改为设置在 <template> 标签上。

  1. <!-- Vue 2.x -->
  2. <template v-for="item in list">
  3. <div v-if="item.isVisible" :key="item.id">...</div>
  4. <span v-else :key="item.id">...</span>
  5. </template>
  6. <!-- Vue 3.x -->
  7. <template v-for="item in list" :key="item.id">
  8. <div v-if="item.isVisible">...</div>
  9. <span v-else>...</span>
  10. </template>

当使用v-if v-else-if v-else分支的时候,不再需要指定key值,因为vue3会自动给予每个分支一个唯一的key

Vue 2.x 建议在 v-if/v-else/v-else-if 的分支中使用 key

  1. <!-- Vue 2.x -->
  2. <div v-if="condition" key="yes">Yes</div>
  3. <div v-else key="no">No</div>

这个示例在 Vue 3.x 中仍能正常工作。但是我们不再建议在 v-if/v-else/v-else-if 的分支中继续使用 key attribute,因为没有为条件分支提供 key 时,也会自动生成唯一的 key

  1. <!-- Vue 3.x -->
  2. <div v-if="condition">Yes</div>
  3. <div v-else>No</div>

非兼容变更体现在如果你手动提供了 key,那么每个分支都必须使用一个唯一的 key。因此大多数情况下都不需要设置这些 key

  1. <!-- Vue 2.x -->
  2. <div v-if="condition" key="a">Yes</div>
  3. <div v-else key="a">No</div>
  4. <!-- Vue 3.x (recommended solution: remove keys) -->
  5. <div v-if="condition">Yes</div>
  6. <div v-else>No</div>
  7. <!-- Vue 3.x (alternate solution: make sure the keys are always unique) -->
  8. <div v-if="condition" key="a">Yes</div>
  9. <div v-else key="b">No</div>

即便要手工给予key值,也必须给予每个分支唯一的key,不能因为要重用分支而给予相同的 key

**示例:

  1. <div>
  2. <div v-if="isAccount" >
  3. <label>账号:</label>
  4. <input type="text" />
  5. </div>
  6. <div v-else >
  7. <label>手机号:</label>
  8. <input type="text" />
  9. </div>
  10. <button @click="isAccount = !isAccount">切换登录方式</button>
  11. </div>

Fragment

vue3现在允许组件出现多个根节点

**