iT邦幫忙

2024 iThome 鐵人賽

DAY 9
1
Modern Web

欸你是要進 Vue 了沒?系列 第 9

欸你是要進 Vue 了沒? - Day9:Vue 模板語法【JS 表達式】

  • 分享至 

  • xImage
  •  

昨天我們講到了屬性綁定,而 Vue 也可以用「JS 表達式」來綁定數據,偶們看看故事會如何發展下去⋯⋯
/images/emoticon/emoticon32.gif

定義

官方文件:在 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>

在瀏覽器上將會看到:
https://ithelp.ithome.com.tw/upload/images/20240922/20169139N18TxBvMo8.png

單一表達式的限制

官方文件:每個綁定僅支持單一表達式,也就是一段能夠被求值的 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 當前的日期和時間。
    https://ithelp.ithome.com.tw/upload/images/20240922/20169139ae6ZGDVa8p.png

  • new Date():創建了一個 Date 物件,並 return 一個新的 Date 物件。
    用開發者工具簡易看一下,如果我把這個「return 的新的 Date 物件」存進 date 變數,將會顯示:
    https://ithelp.ithome.com.tw/upload/images/20240922/2016913992AsFzYmJM.png

  • 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 完整的日期和時間格式

https://ithelp.ithome.com.tw/upload/images/20240922/20169139oWtDmwWuRJ.png

而這裡的兩者都是用 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 打打打打打打,可能就會有什麼意料之外的奇怪性能問題⋯⋯

Vue 中 的沙盒機制

沙盒機制是一種為軟體提供的安全隔離環境,通常會有一些限制去確保程式碼的安全性。

維基百科:This article is about the computer security mechanism. For the software testing environment, see Sandbox (software development).

官方文件在這邊就補充了~自己使用了這個機制,在組件中,只能夠直接使用這些 JavaScript 的內建物件
不在此內的物件可能會受到限制。

像本文範例就使用了:MathDate 此兩種,但若是 window 就不在合規的範圍內,但可以用 app-config-globalproperties 方式添加到全域環境中使用,可以參考官方文件

Btw 想要了解 Math 有哪些函式庫可以用,可以光顧本團隊長的系列文章,與之一起詠唱咒語 XD

小結

小菜菜真的是用這種蝸牛⋯⋯爬爬爬的步調理解這些東西,雖然很慢很慢,但是應該可以爬很遠吧⋯⋯!
/images/emoticon/emoticon37.gif

範例 code ⬇️

參考資料


上一篇
欸你是要進 Vue 了沒? - Day8:Vue 模板語法【屬性綁定】
下一篇
欸你是要進 Vue 了沒? - Day10:Vue 模板語法【指令 Directives】
系列文
欸你是要進 Vue 了沒?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
2
Chris
iT邦新手 3 級 ‧ 2024-09-23 10:00:03

注意!前方高能!XD

++ iT邦新手 5 級 ‧ 2024-09-23 10:10:45 檢舉

/images/emoticon/emoticon32.gif

2
jeremykuo
iT邦新手 5 級 ‧ 2024-09-23 10:01:29

直接塞表達式太酷了!!感覺也是另類的一種咒語呢!
多謝推推!希望我的文章出現在妳的文章中不會造成妳的品質下降/images/emoticon/emoticon06.gif

++ iT邦新手 5 級 ‧ 2024-09-23 10:11:02 檢舉

/images/emoticon/emoticon50.gif

1
橘子
iT邦新手 5 級 ‧ 2024-09-23 10:15:14

這隻蝸牛根本在騎擋車(☉д⊙)

Chris iT邦新手 3 級 ‧ 2024-09-23 10:28:52 檢舉

1000cc 的「檔」車

jeremykuo iT邦新手 5 級 ‧ 2024-09-23 10:29:58 檢舉

螳臂擋車

++ iT邦新手 5 級 ‧ 2024-09-23 11:44:37 檢舉

https://ithelp.ithome.com.tw/upload/images/20240923/20169139EMRQlsKjdR.jpg
(!跟橘的版一樣有圖了

我要留言

立即登入留言