所以我說那個型別呢?來一個有形別提示的 Vue h function 吧!(/≧▽≦)/

更新於 2024/08/26閱讀時間約 6 分鐘
鱈魚的魚缸搬家了!新家文章皆有重新修訂,歡迎來新家看看喔。(´▽`ʃ♡ƪ)
raw-image

先前提到 Quasar 的 Dialog Plugin 很好用,再讓我補充一個用法。


有時候會希望可以點擊圖片時將圖片最大化呈現,這個需求如果要簡單實現,可以使用 QDialog 實作。

最直接的做法應該是點擊指定圖片時,將圖片的 src 存起來,再將 dialog 的顯示狀態改為 true,讓 Dialog 開啟。


其實你可以直接使用 $q.dialog 配合 h function 簡單完成。

<script setup lang="ts">
import { useQuasar, QDialog, QImg } from 'quasar';
import { h } from 'vue';

const $q = useQuasar();

/** 將 QImg 使用 QDialog 包起來後,使用 $q.dialog 開啟 */
function openImgWithDialog(src: string) {
$q.dialog({
component: h(
QDialog,
undefined,
{ default: () => h(QImg, { src }) }
)
});
}

</script>

<template>
<div class="fit flex flex-col gap-4">
<q-img class="w-[20rem] h-[15rem]" src="<https://live.staticflickr.com/4325/35716212880_217fa28b46_k.jpg>"
@click="openImgWithDialog('<https://live.staticflickr.com/4325/35716212880_217fa28b46_k.jpg>')" />
</div>
</template>

這樣就可以簡單快速的利用 Dialog 開啟圖片了,完全不會有額外的 template 與變數!♪( ◜ω◝و(و

(不過如果要複雜的互動,例如縮放平移等等,當然還是要包個專用元件處理。)


當然不只有 QImg,想用其他元件也行,概念都一樣。◝( •ω• )◟

不過這裡稍微有個小小的困擾,就是 h function 不會提示元件的參數,給錯或是參數改了都不知道。…(›´ω`‹ )

讓我們建立一個有元件參數提示的 h function 吧!(/≧▽≦)/


第一步是建立協助抽取 Vue 元件型別的實用 function。

types/index.ts

import { DefineComponent, Slot } from 'vue';

/** 提取 Vue Component 之內部 props
*
* 會將 style、class、event 全部取出來
*/
export type ExtractComponentProps<Comp> = Comp extends new () => {
$props: infer P;
}
? P
: never;

/** 提取 Vue Component slots */
export type ExtractComponentSlots<Comp> = Comp extends new (...args: any) => {
$slots?: infer S
}
? (S extends Slot ? Parameters<S>[0]
: {}
) : {};


接著新增 typedH function。

common/utils.ts

import { Component, h } from 'vue';
import { ExtractComponentProps, ExtractComponentSlots } from '../types';

/** 元件繼承參數
*
* [文檔](<https://cn.vuejs.org/guide/components/attrs.html#fallthrough-attributes>)
*/
export interface InheritAttr {
class?: string;
style?: Record<string, string>;
/** 為了讓範例精簡,這裡只列出 click,可以自行追加基礎事件 */
onClick?: (event: MouseEvent) => void;
}

/** Veu h function 有型別推導的版本
*
* [何謂 h function](<https://cn.vuejs.org/guide/extras/render-function.html>)
*
* @param component Vue SFC 元件或 html tag 名稱
* @param props SFC 內所有參數,包含 class、style、event 等等
* @param slots SFC 插槽
*/
export function typedH(
component: string,
props?: string,
): ReturnType<typeof h>
export function typedH<Comp extends Component>(
component: string,
props?: InheritAttr,
slots?: ExtractComponentSlots<Comp>,
): ReturnType<typeof h>
export function typedH<Comp extends Component>(
component: Comp,
props?: ExtractComponentProps<Comp> & InheritAttr,
slots?: ExtractComponentSlots<Comp>,
): ReturnType<typeof h>
export function typedH(
component: any,
props?: any,
slots?: any,
) {
if (!slots) {
return h(component, props);
}
return h(component, props, slots);
}


用法與原本的 h function 一模一樣,現在我們有型別提示了!✧*。٩(ˊᗜˋ*)و✧*。

就這樣,其實也不是甚麼神奇的東西。(´,,•ω•,,)


範例程式在此,大家下次見。( ´ ▽ ` )ノ

avatar-img
17會員
14內容數
各種鱈魚滾鍵盤的雜紀
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
鱈魚的魚缸 的其他內容
Quasar Dialog 的 Invoking custom component 很好用,但是有些困擾的地方,一起來看看有甚麼辦法吧。
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
有時候使用 Pinia 會遇到資料意外變更問題,這其實不是鳳梨的錯,讓我們看看怎麼回事吧。( ´ ▽ ` )ノ
到底要用 ref 還是 reactive 是一個很常見的問題,不過現在官方文檔推薦使用 ref 就行,所以也不是甚麼大問題就是了。( •̀ ω •́ )✧ 所以 reactive 真的沒用用途了嗎?這篇文章來記錄一下 reactive 的用法。
watch 不是不能用,而是在使用 watch 之前,先想想有沒有其他方案,真的沒有才用 watch。 千萬不要為了一時方便讓元件裡滿滿的 watch,因為容易產生難以追蹤的副作用,會讓資料流更加複雜。
如果 watch 沒有放在元件最外層,可能會導致元件 onUnmounted 後watch不會自動解除,至於該怎麼辦,就讓我們娓娓道來。( ´ ▽ ` )ノ
Quasar Dialog 的 Invoking custom component 很好用,但是有些困擾的地方,一起來看看有甚麼辦法吧。
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
有時候使用 Pinia 會遇到資料意外變更問題,這其實不是鳳梨的錯,讓我們看看怎麼回事吧。( ´ ▽ ` )ノ
到底要用 ref 還是 reactive 是一個很常見的問題,不過現在官方文檔推薦使用 ref 就行,所以也不是甚麼大問題就是了。( •̀ ω •́ )✧ 所以 reactive 真的沒用用途了嗎?這篇文章來記錄一下 reactive 的用法。
watch 不是不能用,而是在使用 watch 之前,先想想有沒有其他方案,真的沒有才用 watch。 千萬不要為了一時方便讓元件裡滿滿的 watch,因為容易產生難以追蹤的副作用,會讓資料流更加複雜。
如果 watch 沒有放在元件最外層,可能會導致元件 onUnmounted 後watch不會自動解除,至於該怎麼辦,就讓我們娓娓道來。( ´ ▽ ` )ノ
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
採訪高管,不免擔憂多於興奮,憂心問答制式,或是與部門實際工作樣貌有著巨大落差。「來吧請坐!今天我們要聊聊什麼?」正與同仁聊天的文鎧副總抬起頭,像是家中爸爸一般微笑招呼,國泰置地廣場 27 樓的會議室,一瞬間成了溫馨客廳。
Thumbnail
本篇沒有暴雷(應該),但有作者癖好本篇沒有暴雷(應該),但有作者癖好
【寶寶有2臍動脈 + 1臍靜脈👶🏻】 定義上:向心的叫靜脈,離心的叫動脈。 臍靜脈是以寶寶為基準。流向寶寶的心臟。從母體帶來豐富的氧氣。 【胎兒的右心負責65%心輸出量❤️】 成人的心輸出主由體循環負責,從左心室打入主動脈。 但是寶寶主要是右心負責心輸出唷。 為什麼呢? 🫁因為胎兒時期,肺臟充
Thumbnail
這個Ksenija Sidorova與馬爾他愛樂交響樂團合作詮釋的 Libertango,應該是有史以來唯一一個樂手因為疫情全員戴口罩的版本....
Thumbnail
晚上行駛的汽車喧囂聲,隔著幾條小巷,透過玻璃窗傳到了我小小的窩居處。一如往常地拿著手機隨意地看著網上的影片。 「你說,她為什麼不體諒我?」朋友的聲音透過電話傳過來,我確實沉默了不知道該如何回答。 『生活不是電影。』不知道從哪裡讀來的這句話,但我覺得很有道理。
Thumbnail
我們都曾為了換取一些方便,說出一些無關痛癢的謊言。 ⁡ ⁡從很早之前就想搬家了,現在的家對於兩個人同時WFH空間實在太小,如果兩個人同時在concall,一個人就得把桌椅搬進廁所裡為防干擾彼此。 某天上班空檔滑591租屋的時候不經意發現一個在喜歡的商圈附近的樓中樓套房在出租,發給她後他看起來也甚是滿
老吳有一個很不識相的女性朋友A小姐,認識很多年,也曾經幫老吳介紹女朋友,但也沒有成功。去年這位A小姐 嫁給了一個也是大她許多的另外一個台商,老吳帶我去參加她的婚禮,也是第一次認識A小姐。
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
採訪高管,不免擔憂多於興奮,憂心問答制式,或是與部門實際工作樣貌有著巨大落差。「來吧請坐!今天我們要聊聊什麼?」正與同仁聊天的文鎧副總抬起頭,像是家中爸爸一般微笑招呼,國泰置地廣場 27 樓的會議室,一瞬間成了溫馨客廳。
Thumbnail
本篇沒有暴雷(應該),但有作者癖好本篇沒有暴雷(應該),但有作者癖好
【寶寶有2臍動脈 + 1臍靜脈👶🏻】 定義上:向心的叫靜脈,離心的叫動脈。 臍靜脈是以寶寶為基準。流向寶寶的心臟。從母體帶來豐富的氧氣。 【胎兒的右心負責65%心輸出量❤️】 成人的心輸出主由體循環負責,從左心室打入主動脈。 但是寶寶主要是右心負責心輸出唷。 為什麼呢? 🫁因為胎兒時期,肺臟充
Thumbnail
這個Ksenija Sidorova與馬爾他愛樂交響樂團合作詮釋的 Libertango,應該是有史以來唯一一個樂手因為疫情全員戴口罩的版本....
Thumbnail
晚上行駛的汽車喧囂聲,隔著幾條小巷,透過玻璃窗傳到了我小小的窩居處。一如往常地拿著手機隨意地看著網上的影片。 「你說,她為什麼不體諒我?」朋友的聲音透過電話傳過來,我確實沉默了不知道該如何回答。 『生活不是電影。』不知道從哪裡讀來的這句話,但我覺得很有道理。
Thumbnail
我們都曾為了換取一些方便,說出一些無關痛癢的謊言。 ⁡ ⁡從很早之前就想搬家了,現在的家對於兩個人同時WFH空間實在太小,如果兩個人同時在concall,一個人就得把桌椅搬進廁所裡為防干擾彼此。 某天上班空檔滑591租屋的時候不經意發現一個在喜歡的商圈附近的樓中樓套房在出租,發給她後他看起來也甚是滿
老吳有一個很不識相的女性朋友A小姐,認識很多年,也曾經幫老吳介紹女朋友,但也沒有成功。去年這位A小姐 嫁給了一個也是大她許多的另外一個台商,老吳帶我去參加她的婚禮,也是第一次認識A小姐。