切换语言为:繁体
详细剖析 Vue3 与 Vue2 模板指令的不同之处

详细剖析 Vue3 与 Vue2 模板指令的不同之处

  • 爱糖宝
  • 2024-07-24
  • 2050
  • 0
  • 0

Vue3作为Vue2的升级版本,带来了许多新特性和改进,这篇文章主要讲下vue的模板指令方面,Vue模板指令是Vue框架中用于实现数据绑定和条件渲染的重要机制。在Vue3中,模板指令经历了一系列的优化和更新,使得模板编写更加灵活、高效

v-model

v-model语法糖,有两个修改和两个新增

  • 第一个修改 在自定义组件时,v-model 的 prop 和事件的默认名称发生了更改: prop 由“value”变为“modelValue”; 事件由“input”变为“update:modelValue”;

  • 第二个修改 v-bind 的.sync 修饰符以及组件的 model 选项已被移除,不过可以在 v-model 上添加一个参数来替代

  • 第一个新增 新增的功能是如今能够在同一个组件上运用多个 v-model 绑定

下面仔细说一下 第二个新增功能

第二个新增 现在可以对 v-model 修饰符进行自定义。

例如 v-model.capitalize,.capitalize就是自定义修饰符,然后可以通过 modifiers 对模型属性进行额外的处理或修改。例如,可以使用修饰符来限制输入的值、格式化输出的值、添加验证规则等

modifiers是什么?

modifiers 是defineModel函数返回的第二个参数,它是一个对象,用于定义模型属性的修饰符。

具体使用案例,

parent.vue中使用capitalize修饰符

<template>
  <div class="parent">
    <div class="title">
      <h1>父组件</h1>
    </div>
    <child v-model.capitalize="count"></child>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import child from './child.vue'
let count = ref('')
</script>

<style scoped>
.parent {
  background-color: aqua;
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-around;
}

.title {
  margin: 10px;
}
</style>

child中 defineModel拦截set事件,判断如果有capitalize修饰符,则强制修改value的第一个字母为大写

<template>
  <div class="child">
    <h1>子组件</h1>
    <input v-model="count" />
  </div>
</template>

<script setup>

let model = defineModel({
  set(value) {
    if (modifiers.capitalize) {
      return value.charAt(0).toUpperCase() + value.slice(1);
    }
    return value;
  },
});
const [count, modifiers] = model;

</script>

<style scoped>
.child {
  width: 500px;
  height: 200px;
  background-color: #fff;
  border-radius: 20px;
  color: black;
  padding: 20px;
}
</style>

效果图

详细剖析 Vue3 与 Vue2 模板指令的不同之处

telement标签被允许拥有key属性

在 Vue 2中,<template> 标签不能拥有 key。所以一般是为每个子节点分别设置 key,

但在 Vue 3中 key 被允许设置在 <template> 标签上,并且这是官方推荐的写法

v-if 与 v-for 的优先级对比

先说结论 Vue 2 版本中在一个元素上同时使用 v-if 和 v-for 时,v-for 会优先作用。

但在Vue 3 版本中 v-if 总是优先于 v-for 生效。

不管再vue2中还是vue3中都都要避免同时使用v-if 和 v-for,可以用以下几种方法

  • 计算属性过滤的v-if所限制的条件

  • 初始化list数据时先用filter根据条件进行筛选过滤

  • 通过嵌套标签包裹,将v-for和v-if分别加在不同标签上

vue2 详细剖析 Vue3 与 Vue2 模板指令的不同之处 详细剖析 Vue3 与 Vue2 模板指令的不同之处

vue3

详细剖析 Vue3 与 Vue2 模板指令的不同之处

v-bind 合并行为

在vue2 中 v-bind 和 attribute,书写顺序无论先后,attribute总是覆盖v-bind而

而在vue3 中 v-bind 和 attribute 则是按顺序来执行,后面的会覆盖前面的。

vue2 中案例说明

<template>
  <div class="parent">
    <h1>父级组件</h1>
    <child name="hahahah" v-bind="obj" />
  </div>
</template>

<script>
// @ is an alias to /src
import child from "@/components/child.vue";
export default {
  components: {
    child,
  },
  data() {
    return {
      obj: {
        name: 'iwhao',
      }
    }
  }
};
</script>

<template>
  <div class="child">
    <h1>子组件</h1>
    <h1>{{ name }}</h1>
  </div>
</template>

<script>
export default {
  props: {
    name: String,
  },
};
</script>

vue3 中案例说明

父组件

<template>
  <div class="parent">
    <h1>父组件</h1>
    <child name="hahahah" v-bind="{name: name}" ></child>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import child from './child.vue'
let name = ref('iwhao')
</script>

子组件

<template>
  <div class="child">
    <h1>子组件</h1>
    <p>父组件传过来的name: {{ name }}</p>
  </div>
</template>

<script setup>
defineProps(['name'])
</script>

如上代码,因为父组件中先写的 name 后写的 v-bind name,后面的v-bind会覆盖其那面的name,所以在子组件中接收的值 是 父组件中v-bind中 name:iwhao 详细剖析 Vue3 与 Vue2 模板指令的不同之处 

如果把父组件中的name 和 v-bind的书写顺序换一下的话 如下 效果

...
<child v-bind="{name: name}" name="hahahah"></child>
...

详细剖析 Vue3 与 Vue2 模板指令的不同之处

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.