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> ...