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>
效果图
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
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
如果把父组件中的name 和 v-bind的书写顺序换一下的话 如下 效果
... <child v-bind="{name: name}" name="hahahah"></child> ...