切換語言為:簡體
詳細剖析 Vue3 與 Vue2 模板指令的不同之處

詳細剖析 Vue3 與 Vue2 模板指令的不同之處

  • 爱糖宝
  • 2024-07-24
  • 2049
  • 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.