Skip to content

Commit fd63a28

Browse files
authored
fix(vue): support computed getter trigger (#638)
1 parent 16de435 commit fd63a28

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

packages/vue/src/scripts/useScript.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ export interface UseScriptOptions<T extends Record<symbol | string, any> = Recor
2626
* - `Promise` - Load the script when the promise resolves, exists only on the client.
2727
* - `Function` - Register a callback function to load the script, exists only on the client.
2828
* - `server` - Have the script injected on the server.
29-
* - `ref` - Load the script when the ref is true.
29+
* - `Ref<boolean>` - Load the script when the ref becomes true.
30+
* - `() => boolean` - Getter function, load the script when return value becomes true.
3031
*/
31-
trigger?: BaseUseScriptOptions['trigger'] | Ref<boolean>
32+
trigger?: BaseUseScriptOptions['trigger'] | Ref<boolean> | (() => boolean)
3233
/**
3334
* Unhead instance.
3435
*/
@@ -78,11 +79,14 @@ export function useScript<T extends Record<symbol | string, any> = Record<symbol
7879
if (scope && typeof options.trigger === 'undefined') {
7980
options.trigger = onMounted
8081
}
81-
else if (isRef(options.trigger)) {
82-
const refTrigger = options.trigger as Ref<boolean>
82+
else if (isRef(options.trigger) || (typeof options.trigger === 'function' && options.trigger.length === 0)) {
83+
// Handle refs, computed refs, and getter functions (zero-arg functions that return boolean)
84+
// Getter functions like `() => shouldLoad.value` have length 0
85+
// Callback functions like `(load) => onMounted(load)` have length 1+
86+
const trigger = options.trigger as Ref<boolean> | (() => boolean)
8387
let off: WatchHandle
8488
options.trigger = new Promise<boolean>((resolve) => {
85-
off = watch(refTrigger, (val) => {
89+
off = watch(trigger, (val) => {
8690
if (val) {
8791
resolve(true)
8892
}

packages/vue/test/unit/useScript.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,43 @@ describe('vue e2e scripts', () => {
117117
expect(status2.value).toEqual('loading')
118118
})
119119

120+
it('getter function trigger', async () => {
121+
const dom = useDom()
122+
const head = createHead({
123+
document: dom.window.document,
124+
})
125+
126+
const shouldLoad = ref(false)
127+
128+
const { status, _triggerPromises } = useScript({
129+
src: '//getter-trigger.script',
130+
}, {
131+
// getter function like () => shouldLoad.value
132+
trigger: () => shouldLoad.value,
133+
head,
134+
})
135+
136+
// promise pending
137+
expect(_triggerPromises).toMatchInlineSnapshot(`
138+
[
139+
Promise {},
140+
]
141+
`)
142+
143+
expect(status.value).toEqual('awaitingLoad')
144+
145+
// trigger by setting the ref
146+
shouldLoad.value = true
147+
// wait next tick
148+
await new Promise<void>((resolve) => {
149+
setTimeout(() => {
150+
resolve()
151+
}, 25)
152+
})
153+
154+
expect(status.value).toEqual('loading')
155+
})
156+
120157
it('respects useScript privacy controls - #293', async () => {
121158
const head = createHeadCore()
122159
const script = useScript({

0 commit comments

Comments
 (0)