From fd533d444100676577d2da64701d5f10fc95a5e0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Feb 2026 06:38:25 +0000 Subject: [PATCH 1/3] Initial plan From c3b1eeed824daeeeac818c69c73710e29b0471e9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Feb 2026 06:44:30 +0000 Subject: [PATCH 2/3] Migrate lazy-image.js and lazy-component.js from Options API to Composition API Co-authored-by: yoyo837 <6134547+yoyo837@users.noreply.github.com> --- .../lazyload/vue-lazyload/lazy-component.js | 114 ++++++----- .../src/lazyload/vue-lazyload/lazy-image.js | 189 ++++++++++-------- 2 files changed, 164 insertions(+), 139 deletions(-) diff --git a/packages/vant/src/lazyload/vue-lazyload/lazy-component.js b/packages/vant/src/lazyload/vue-lazyload/lazy-component.js index 9768a74095f..4cbe06f748f 100644 --- a/packages/vant/src/lazyload/vue-lazyload/lazy-component.js +++ b/packages/vant/src/lazyload/vue-lazyload/lazy-component.js @@ -3,66 +3,76 @@ * license at https://github.com/hilongjw/vue-lazyload/blob/master/LICENSE */ -import { h } from 'vue'; +import { + h, + ref, + reactive, + defineComponent, + getCurrentInstance, + onMounted, + onBeforeUnmount, +} from 'vue'; import { inBrowser, useRect } from '@vant/use'; -export default (lazy) => ({ - props: { - tag: { - type: String, - default: 'div', +export default (lazy) => + defineComponent({ + props: { + tag: { + type: String, + default: 'div', + }, }, - }, - - emits: ['show'], - render() { - return h( - this.tag, - this.show && this.$slots.default ? this.$slots.default() : null, - ); - }, + emits: ['show'], - data() { - return { - el: null, - state: { + setup(props, { slots, emit }) { + const instance = getCurrentInstance(); + const show = ref(false); + const state = reactive({ loaded: false, - }, - show: false, - }; - }, + }); - mounted() { - this.el = this.$el; - lazy.addLazyBox(this); - lazy.lazyLoadHandler(); - }, + const lazyBox = { + get el() { + return instance.proxy.$el; + }, + get $el() { + return instance.proxy.$el; + }, + get $parent() { + return instance.proxy.$parent; + }, + state, + checkInView() { + const rect = useRect(instance.proxy.$el); + return ( + inBrowser && + rect.top < window.innerHeight * lazy.options.preLoad && + rect.bottom > 0 && + rect.left < window.innerWidth * lazy.options.preLoad && + rect.right > 0 + ); + }, + load() { + show.value = true; + state.loaded = true; + emit('show', instance.proxy); + }, + destroy() { + return undefined; + }, + }; - beforeUnmount() { - lazy.removeComponent(this); - }, + onMounted(() => { + lazy.addLazyBox(lazyBox); + lazy.lazyLoadHandler(); + }); - methods: { - checkInView() { - const rect = useRect(this.$el); - return ( - inBrowser && - rect.top < window.innerHeight * lazy.options.preLoad && - rect.bottom > 0 && - rect.left < window.innerWidth * lazy.options.preLoad && - rect.right > 0 - ); - }, - - load() { - this.show = true; - this.state.loaded = true; - this.$emit('show', this); - }, + onBeforeUnmount(() => { + lazy.removeComponent(lazyBox); + }); - destroy() { - return this.$destroy; + return () => + h(props.tag, show.value && slots.default ? slots.default() : null); }, - }, -}); + }); diff --git a/packages/vant/src/lazyload/vue-lazyload/lazy-image.js b/packages/vant/src/lazyload/vue-lazyload/lazy-image.js index 5cbdb9c5050..6529f5126b7 100644 --- a/packages/vant/src/lazyload/vue-lazyload/lazy-image.js +++ b/packages/vant/src/lazyload/vue-lazyload/lazy-image.js @@ -6,105 +6,120 @@ import { useRect } from '@vant/use'; import { loadImageAsync } from './util'; import { noop } from '../../utils'; -import { h } from 'vue'; +import { + h, + ref, + reactive, + defineComponent, + getCurrentInstance, + onMounted, + onBeforeUnmount, + watch, +} from 'vue'; -export default (lazyManager) => ({ - props: { - src: [String, Object], - tag: { - type: String, - default: 'img', - }, - }, - render() { - return h( - this.tag, - { - src: this.renderSrc, +export default (lazyManager) => + defineComponent({ + props: { + src: [String, Object], + tag: { + type: String, + default: 'img', }, - this.$slots.default?.(), - ); - }, - data() { - return { - el: null, - options: { + }, + setup(props, { slots }) { + const instance = getCurrentInstance(); + const renderSrc = ref(''); + const options = { src: '', error: '', loading: '', attempt: lazyManager.options.attempt, - }, - state: { + }; + const state = reactive({ loaded: false, error: false, attempt: 0, - }, - renderSrc: '', - }; - }, - watch: { - src() { - this.init(); - lazyManager.addLazyBox(this); - lazyManager.lazyLoadHandler(); - }, - }, - created() { - this.init(); - }, - mounted() { - this.el = this.$el; - lazyManager.addLazyBox(this); - lazyManager.lazyLoadHandler(); - }, - beforeUnmount() { - lazyManager.removeComponent(this); - }, - methods: { - init() { - const { src, loading, error } = lazyManager.valueFormatter(this.src); - this.state.loaded = false; - this.options.src = src; - this.options.error = error; - this.options.loading = loading; - this.renderSrc = this.options.loading; - }, - checkInView() { - const rect = useRect(this.$el); - return ( - rect.top < window.innerHeight * lazyManager.options.preLoad && - rect.bottom > 0 && - rect.left < window.innerWidth * lazyManager.options.preLoad && - rect.right > 0 - ); - }, - load(onFinish = noop) { - if (this.state.attempt > this.options.attempt - 1 && this.state.error) { - if ( - process.env.NODE_ENV !== 'production' && - !lazyManager.options.silent - ) { - console.log( - `[@vant/lazyload] ${this.options.src} tried too more than ${this.options.attempt} times`, - ); - } + }); - onFinish(); - return; - } - const { src } = this.options; - loadImageAsync( - { src }, - ({ src }) => { - this.renderSrc = src; - this.state.loaded = true; + const init = () => { + const { src, loading, error } = lazyManager.valueFormatter(props.src); + state.loaded = false; + options.src = src; + options.error = error; + options.loading = loading; + renderSrc.value = options.loading; + }; + + const lazyBox = { + get el() { + return instance.proxy.$el; + }, + get $el() { + return instance.proxy.$el; }, + get $parent() { + return instance.proxy.$parent; + }, + state, + options, + checkInView() { + const rect = useRect(instance.proxy.$el); + return ( + rect.top < window.innerHeight * lazyManager.options.preLoad && + rect.bottom > 0 && + rect.left < window.innerWidth * lazyManager.options.preLoad && + rect.right > 0 + ); + }, + load(onFinish = noop) { + if (state.attempt > options.attempt - 1 && state.error) { + if ( + process.env.NODE_ENV !== 'production' && + !lazyManager.options.silent + ) { + console.log( + `[@vant/lazyload] ${options.src} tried too more than ${options.attempt} times`, + ); + } + onFinish(); + return; + } + const { src } = options; + loadImageAsync( + { src }, + ({ src }) => { + renderSrc.value = src; + state.loaded = true; + }, + () => { + state.attempt++; + renderSrc.value = options.error; + state.error = true; + }, + ); + }, + }; + + init(); + + watch( + () => props.src, () => { - this.state.attempt++; - this.renderSrc = this.options.error; - this.state.error = true; + init(); + lazyManager.addLazyBox(lazyBox); + lazyManager.lazyLoadHandler(); }, ); + + onMounted(() => { + lazyManager.addLazyBox(lazyBox); + lazyManager.lazyLoadHandler(); + }); + + onBeforeUnmount(() => { + lazyManager.removeComponent(lazyBox); + }); + + return () => h(props.tag, { src: renderSrc.value }, slots.default?.()); }, - }, -}); + }); From ff4071f0151a11697abd6beb8f3557f42d0545f0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Feb 2026 07:03:48 +0000 Subject: [PATCH 3/3] fix(lazyload): remove duplicate addLazyBox call in watch callback Co-authored-by: yoyo837 <6134547+yoyo837@users.noreply.github.com> --- packages/vant/src/lazyload/vue-lazyload/lazy-image.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/vant/src/lazyload/vue-lazyload/lazy-image.js b/packages/vant/src/lazyload/vue-lazyload/lazy-image.js index 6529f5126b7..638ed887c6b 100644 --- a/packages/vant/src/lazyload/vue-lazyload/lazy-image.js +++ b/packages/vant/src/lazyload/vue-lazyload/lazy-image.js @@ -106,7 +106,6 @@ export default (lazyManager) => () => props.src, () => { init(); - lazyManager.addLazyBox(lazyBox); lazyManager.lazyLoadHandler(); }, );