昨天我們講到了屬性綁定,而 Vue 也可以用「JS 表達式」來綁定數據,偶們看看故事會如何發展下去⋯⋯
官方文件:在 Vue 模板內,JavaScript 表達式可以被使用在如下場景上:
- 在文本插值中 (雙大括號)
- 在任何 Vue 指令 (以 v- 開頭的特殊屬性) 屬性的值中
而 JS 表達式(expression),可以以「是否有回傳結果」來判斷。
也就是官方文件說的:
「一個簡單的判斷方法是是否可以合法地寫在 return 後面。」
來看看以下四行,它們都是 JS 表達式,皆有回傳結果。
a / 2;
Math.floor(Math.random() * 10);
isOK ? "YES" : "NO";
[0, 1, 2, 3, 4].map((i) => i + 1).join(",");
因此我們可以使用 {{ }}
將其綁定數據:
<script setup>
const a = 1;
let isOK = true;
</script>
<template>
<div>{{ a / 2 }}</div>
<div>{{ Math.floor(Math.random() * 10) }}</div>
<div>{{ isOK ? "YES" : "NO" }}</div>
<div>{{ [0, 1, 2, 3, 4].map((i) => i + 1).join(",") }}</div>
</template>
在瀏覽器上將會看到:
官方文件:每個綁定僅支持單一表達式,也就是一段能夠被求值的 JavaScript 代碼。
只支持「單一表達式」,那什麼不是?
例如:if 判斷式 和 for 迴圈 都是多重陳述句(statement),因為它們主要用於執行某些動作、控制程式流程,但不會直接回傳值。
if (isOk) {
console.log("I am okay");
}
for (let i = 0; i < 5; i++) {
console.log(i)
}
想了解更多 JS 表達式可以前往 MDN!
官方文件:
可以在綁定的表達式中使用一個組件暴露的方法
It is possible to call a component-exposed method inside a binding expression
翻譯蒟蒻:這表示我們可以在 <script>
區塊中定義函式,並將這些函式綁定到 <template>
的屬性上。
而 <script setup>
語法糖 預設行為是:會將其中定義的東西直接暴露給模板的,所以就是說,我們可以在模板綁定表達式中使用 script setup
定義的 method。
<template>
<time :title="toTitleDate(date)" :datetime="date">
{{ formatDate(date) }}
</time>
</template>
<script setup>
import { ref } from "vue";
const date = ref(new Date());
const formatDate = (date) => {
return date.toLocaleDateString();
};
const toTitleDate = (date) => {
return date.toLocaleString();
};
</script>
一起從 <script setup>
區塊來看看,這段程式碼做了什麼事:
const date = ref(new Date());
Date()
物件:會 return 當前的日期和時間。
new Date()
:創建了一個 Date
物件,並 return 一個新的 Date
物件。
用開發者工具簡易看一下,如果我把這個「return 的新的 Date
物件」存進 date
變數,將會顯示:
ref(new Date())
:將 return 的物件包裝為響應式數據。
也就是:當 date 變數發生變化時,Vue 組件會自動重新渲染相應的部分。
const date = ref(new Date())
:將響應式數據存到 date
這個變數裡。
const formatDate = (date) => {
return date.toLocaleDateString();
};
const toTitleDate = (date) => {
return date.toLocaleString();
};
</script>
date.toLocaleDateString();
會 return 可讀的日期格式date.toLocaleString();
會 return 完整的日期和時間格式而這裡的兩者都是用 JS 函式表達式(function expression)定義,因此,即可這樣呼叫它們:
formatDate(date);
toTitleDate(date);
回到範例的 <template>
,所以我們可以這樣「呼叫函式去綁定屬性」:
<template>
<time :title="toTitleDate(date)" :datetime="date">
{{ formatDate(date) }}
</time>
</template>
<time>
區塊中也就是做了:
title
屬性綁定為 toTitleDate(date)
的回傳值。datetime
屬性綁定為 date
變數的值。formatDate(date)
的回傳值用 {{ }}
做顯示。官方文件提到:綁定在表達式中的方法在組件每次更新時都會被重新調用,因此不應該產生任何副作用,例如改變數據或觸發異步操作。
也就是說:
<time :title="toTitleDate(date)" :datetime="date">
{{ formatDate(date) }}
</time>
此範例中,當 date
變數被更新,title
上的屬性 toTitleDate(date)
及文本插值 formatDate(date)
,皆會被重新渲染、更新數據。
所以當:定義的這些表達式若有更新數據、或非同步的操作時,就可能會導致錯誤。
例如小菜菜每次更新 date 都打一隻 API 打打打打打打,可能就會有什麼意料之外的奇怪性能問題⋯⋯
沙盒機制是一種為軟體提供的安全隔離環境,通常會有一些限制去確保程式碼的安全性。
維基百科:This article is about the computer security mechanism. For the software testing environment, see Sandbox (software development).
官方文件在這邊就補充了~自己使用了這個機制,在組件中,只能夠直接使用這些 JavaScript 的內建物件。
不在此內的物件可能會受到限制。
像本文範例就使用了:Math
、Date
此兩種,但若是 window
就不在合規的範圍內,但可以用 app-config-globalproperties
方式添加到全域環境中使用,可以參考官方文件。
Btw 想要了解 Math 有哪些函式庫可以用,可以光顧本團隊長的系列文章,與之一起詠唱咒語 XD
小菜菜真的是用這種蝸牛⋯⋯爬爬爬的步調理解這些東西,雖然很慢很慢,但是應該可以爬很遠吧⋯⋯!
直接塞表達式太酷了!!感覺也是另類的一種咒語呢!
多謝推推!希望我的文章出現在妳的文章中不會造成妳的品質下降