31. vue3模版中的变化

67 阅读2分钟

v-model

vue2比较让人诟病的一点就是提供了两种双向绑定:v-model.sync,在vue3中,去掉了.sync修饰符,只需要使用v-model进行双向绑定即可。

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

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

    <!-- vue2 -->
    <ChildComponent :value="pageTitle" @input="pageTitle = $event" />
    <!-- 简写为 -->
    <ChildComponent v-model="pageTitle" />
    
    <!-- vue3 -->
    <ChildComponent
      :modelValue="pageTitle"
      @update:modelValue="pageTitle = $event"
    />
    <!-- 简写为 -->
    <ChildComponent v-model="pageTitle" />
    
  • 去掉了.sync修饰符,它原本的功能由v-model的参数替代

    <!-- vue2 -->
    <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
    <!-- 简写为 -->
    <ChildComponent :title.sync="pageTitle" />
    
    <!-- vue3 -->
    <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
    <!-- 简写为 -->
    <ChildComponent v-model:title="pageTitle" />
    
  • model配置被移除

  • 允许自定义v-model修饰符

    vue2 无此功能

    image-20201008163021918

实际项目举例

<CheckEditor
        v-for="item in products"
        :key="item.id"
        v-model="item.sell"
        v-model:title.trim="item.title"
      />
export default {
props: {
  modelValue: Boolean,
  
  title: String,
  // 这里命名只能是xxxModifiers 这样的命名
  
  titleModifiers: {
    default: () => ({}),
  },
},

setup(props, ctx) {
  const handleChecked = () => {
    ctx.emit("update:modelValue", !props.modelValue);
  };

  const handleTextChange = (e) => {
    let value = e.target.value;
    if (props.titleModifiers.trim) {
      value = value.trim();
    }
    ctx.emit("update:title", value);
  };
  return {
    handleChecked,
    handleTextChange,
  };
},
};

trim 是带的修饰符。这里特别要注意的是在props里面一定是

xxxModifiers: {
    default: () => ({}),
  },
 titleModifiers: {
    default: () => ({}),
  },

v-if v-for

其中 vue3 中v-if 的优先级 现在高于 v-for vue2 中是 v-if 的优先级 现在低于 v-for,正是由于vue2中存在这个问题,是有可能会写出

image.png 这里这样写也能运行,由于v-for 优先级高于 v-if,所以会执行 v-for='(item, index) in product' ,所以v-if 是能够拿到item的,在vue3中优先级发生了改变,就会报item这个变量找不到。 其实上面的写法vue2中也是不好,应该弄一个计算属性出来,防止在循环的时候还在用v-if.

key

  • 当使用<template>进行v-for循环时,需要把key值放到<template>中,而不是它的子元素中。注意对比,在vue2中需要在temple里面的每个组件上面都加上key。

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

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

    vue2 中需要给下面的代码给不同的key,而vue3不需要了,vue2 不给会导致if和else已经切换了,而input里面的东西却没有切换。

    <div v-if="isAccount" key="1">
      <label>账号:</label>
      <input type="text" />
    </div>
    <div v-else key="2">
      <label>手机号:</label>
      <input type="text" />
    </div>
    <button @click="isAccount = !isAccount">切换登录方式</button>
    

Fragment

vue3现在允许组件出现多个根节点。vue2必须是单根节点。