mirror of https://github.com/vuejs/core.git
parent
6e4de8d75e
commit
b094c72b3d
|
@ -170,15 +170,14 @@ function doWatch(
|
||||||
|
|
||||||
if (__DEV__) baseWatchOptions.onWarn = warn
|
if (__DEV__) baseWatchOptions.onWarn = warn
|
||||||
|
|
||||||
|
// immediate watcher or watchEffect
|
||||||
|
const runsImmediately = (cb && immediate) || (!cb && flush !== 'post')
|
||||||
let ssrCleanup: (() => void)[] | undefined
|
let ssrCleanup: (() => void)[] | undefined
|
||||||
if (__SSR__ && isInSSRComponentSetup) {
|
if (__SSR__ && isInSSRComponentSetup) {
|
||||||
if (flush === 'sync') {
|
if (flush === 'sync') {
|
||||||
const ctx = useSSRContext()!
|
const ctx = useSSRContext()!
|
||||||
ssrCleanup = ctx.__watcherHandles || (ctx.__watcherHandles = [])
|
ssrCleanup = ctx.__watcherHandles || (ctx.__watcherHandles = [])
|
||||||
} else if (!cb || immediate) {
|
} else if (!runsImmediately) {
|
||||||
// immediately watch or watchEffect
|
|
||||||
baseWatchOptions.once = true
|
|
||||||
} else {
|
|
||||||
const watchStopHandle = () => {}
|
const watchStopHandle = () => {}
|
||||||
watchStopHandle.stop = NOOP
|
watchStopHandle.stop = NOOP
|
||||||
watchStopHandle.resume = NOOP
|
watchStopHandle.resume = NOOP
|
||||||
|
@ -226,7 +225,14 @@ function doWatch(
|
||||||
|
|
||||||
const watchHandle = baseWatch(source, cb, baseWatchOptions)
|
const watchHandle = baseWatch(source, cb, baseWatchOptions)
|
||||||
|
|
||||||
if (__SSR__ && ssrCleanup) ssrCleanup.push(watchHandle)
|
if (__SSR__ && isInSSRComponentSetup) {
|
||||||
|
if (ssrCleanup) {
|
||||||
|
ssrCleanup.push(watchHandle)
|
||||||
|
} else if (runsImmediately) {
|
||||||
|
watchHandle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return watchHandle
|
return watchHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
import { createSSRApp, defineComponent, h, ref, watch } from 'vue'
|
import {
|
||||||
|
createSSRApp,
|
||||||
|
defineComponent,
|
||||||
|
h,
|
||||||
|
nextTick,
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
watchEffect,
|
||||||
|
} from 'vue'
|
||||||
import { type SSRContext, renderToString } from '../src'
|
import { type SSRContext, renderToString } from '../src'
|
||||||
|
|
||||||
describe('ssr: watch', () => {
|
describe('ssr: watch', () => {
|
||||||
|
@ -27,4 +35,168 @@ describe('ssr: watch', () => {
|
||||||
|
|
||||||
expect(html).toMatch('hello world')
|
expect(html).toMatch('hello world')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should work with flush: sync and immediate: true', async () => {
|
||||||
|
const text = ref('start')
|
||||||
|
let msg = 'unchanged'
|
||||||
|
|
||||||
|
const App = defineComponent(() => {
|
||||||
|
watch(
|
||||||
|
text,
|
||||||
|
() => {
|
||||||
|
msg = text.value
|
||||||
|
},
|
||||||
|
{ flush: 'sync', immediate: true },
|
||||||
|
)
|
||||||
|
expect(msg).toBe('start')
|
||||||
|
text.value = 'changed'
|
||||||
|
expect(msg).toBe('changed')
|
||||||
|
text.value = 'changed again'
|
||||||
|
expect(msg).toBe('changed again')
|
||||||
|
return () => h('div', null, msg)
|
||||||
|
})
|
||||||
|
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
const ctx: SSRContext = {}
|
||||||
|
const html = await renderToString(app, ctx)
|
||||||
|
|
||||||
|
expect(ctx.__watcherHandles!.length).toBe(1)
|
||||||
|
expect(html).toMatch('changed again')
|
||||||
|
await nextTick()
|
||||||
|
expect(msg).toBe('changed again')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should run once with immediate: true', async () => {
|
||||||
|
const text = ref('start')
|
||||||
|
let msg = 'unchanged'
|
||||||
|
|
||||||
|
const App = defineComponent(() => {
|
||||||
|
watch(
|
||||||
|
text,
|
||||||
|
() => {
|
||||||
|
msg = String(text.value)
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
)
|
||||||
|
text.value = 'changed'
|
||||||
|
expect(msg).toBe('start')
|
||||||
|
return () => h('div', null, msg)
|
||||||
|
})
|
||||||
|
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
const ctx: SSRContext = {}
|
||||||
|
const html = await renderToString(app, ctx)
|
||||||
|
|
||||||
|
expect(ctx.__watcherHandles).toBeUndefined()
|
||||||
|
expect(html).toMatch('start')
|
||||||
|
await nextTick()
|
||||||
|
expect(msg).toBe('start')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should run once with immediate: true and flush: post', async () => {
|
||||||
|
const text = ref('start')
|
||||||
|
let msg = 'unchanged'
|
||||||
|
|
||||||
|
const App = defineComponent(() => {
|
||||||
|
watch(
|
||||||
|
text,
|
||||||
|
() => {
|
||||||
|
msg = String(text.value)
|
||||||
|
},
|
||||||
|
{ immediate: true, flush: 'post' },
|
||||||
|
)
|
||||||
|
text.value = 'changed'
|
||||||
|
expect(msg).toBe('start')
|
||||||
|
return () => h('div', null, msg)
|
||||||
|
})
|
||||||
|
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
const ctx: SSRContext = {}
|
||||||
|
const html = await renderToString(app, ctx)
|
||||||
|
|
||||||
|
expect(ctx.__watcherHandles).toBeUndefined()
|
||||||
|
expect(html).toMatch('start')
|
||||||
|
await nextTick()
|
||||||
|
expect(msg).toBe('start')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('ssr: watchEffect', () => {
|
||||||
|
test('should run with flush: sync', async () => {
|
||||||
|
const text = ref('start')
|
||||||
|
let msg = 'unchanged'
|
||||||
|
|
||||||
|
const App = defineComponent(() => {
|
||||||
|
watchEffect(
|
||||||
|
() => {
|
||||||
|
msg = text.value
|
||||||
|
},
|
||||||
|
{ flush: 'sync' },
|
||||||
|
)
|
||||||
|
expect(msg).toBe('start')
|
||||||
|
text.value = 'changed'
|
||||||
|
expect(msg).toBe('changed')
|
||||||
|
text.value = 'changed again'
|
||||||
|
expect(msg).toBe('changed again')
|
||||||
|
return () => h('div', null, msg)
|
||||||
|
})
|
||||||
|
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
const ctx: SSRContext = {}
|
||||||
|
const html = await renderToString(app, ctx)
|
||||||
|
|
||||||
|
expect(ctx.__watcherHandles!.length).toBe(1)
|
||||||
|
expect(html).toMatch('changed again')
|
||||||
|
await nextTick()
|
||||||
|
expect(msg).toBe('changed again')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should run once with default flush (pre)', async () => {
|
||||||
|
const text = ref('start')
|
||||||
|
let msg = 'unchanged'
|
||||||
|
|
||||||
|
const App = defineComponent(() => {
|
||||||
|
watchEffect(() => {
|
||||||
|
msg = text.value
|
||||||
|
})
|
||||||
|
text.value = 'changed'
|
||||||
|
expect(msg).toBe('start')
|
||||||
|
return () => h('div', null, msg)
|
||||||
|
})
|
||||||
|
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
const ctx: SSRContext = {}
|
||||||
|
const html = await renderToString(app, ctx)
|
||||||
|
|
||||||
|
expect(ctx.__watcherHandles).toBeUndefined()
|
||||||
|
expect(html).toMatch('start')
|
||||||
|
await nextTick()
|
||||||
|
expect(msg).toBe('start')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should not run for flush: post', async () => {
|
||||||
|
const text = ref('start')
|
||||||
|
let msg = 'unchanged'
|
||||||
|
|
||||||
|
const App = defineComponent(() => {
|
||||||
|
watchEffect(
|
||||||
|
() => {
|
||||||
|
msg = text.value
|
||||||
|
},
|
||||||
|
{ flush: 'post' },
|
||||||
|
)
|
||||||
|
text.value = 'changed'
|
||||||
|
expect(msg).toBe('unchanged')
|
||||||
|
return () => h('div', null, msg)
|
||||||
|
})
|
||||||
|
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
const ctx: SSRContext = {}
|
||||||
|
const html = await renderToString(app, ctx)
|
||||||
|
|
||||||
|
expect(ctx.__watcherHandles).toBeUndefined()
|
||||||
|
expect(html).toMatch('unchanged')
|
||||||
|
await nextTick()
|
||||||
|
expect(msg).toBe('unchanged')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue