背景:父组件为vxe-table构成的组件、子组件为table的某一列,这一列的数据通过接口返回,有多少条表格数据就会请求多少次接口,为了提升性能,所以采用接口懒加载,但是需要在回滚的时候不重复请求或者加载数据
npm i @vueuse/core@4.9.0
步骤:
- import { useIntersectionObserver } from '@vueuse/core'
- import { ref } from 'vue'
-
- /**
- * 用于懒加载数据
- * @param {*} apiFn 懒加载数据的接口
- * @returns target: 需要绑定的DOM对象 result: 结果数据
- */
- export const useLazyData = (apiFn: Function) => {
- const target = ref(null)
- const result = ref()
- let stopObserver // 保存观察者的停止函数
-
- const { stop } = useIntersectionObserver(target, ([{ isIntersecting }], observerElement) => {
- if (isIntersecting) {
- stopObserver() // 调用之前保存的停止函数
- apiFn().then((data) => {
- if (data) {
- result.value = data
- }
- })
- }
- })
-
- stopObserver = stop // 保存观察者的停止函数
-
- return { target, result,stopObserver }
- }
- [RootMutations.LOADED_TEST_DATA](state: RootState, value) {
- state.loadedTestData = value
- },
- <section ref="target">
- <span>{{ newData?.end_time }}span>
- section>
- import { defaultProps } from './props'
-
- const props = defineProps(defaultProps)
- const emits = defineEmits(['update'])
- const { modelValue, endTime } = toRefs(props)
-
- const newData: Ref<App.BatteryTest> = ref(unref(modelValue))
- //封装接口请求
- const getDeadline = () => {
- .test(参数, {
- //逻辑代码
- })
- .then(([res]) => {
- if (res?.status === 200) {
- nextTick(() => {
-
- newData.value = { ...unref(newData), end_time: dateFormat(res?.data?.Deadline / 1000) + '' }
- emits('update', unref(newData))
-
- updateLoadedData() //更新已经加载的数据
- })
- return dateFormat(res?.data?.Deadline / 1000) + ''//这里返回给hook中定义的useLazyData中的result
- }else {
- nextTick(() => {
- newData.value = { ...unref(newData), end_time: '' }
-
- emits('update', unref(newData))
- updateLoadedData() //更新已经加载的数据
- })
-
- return ''
- }
- })
-
-
-
-
- function dateFormat(date: any) {
- //转变导出报表记录日期格式
-
- if (date == undefined || date == 0) {
- return ''
- }
-
- return moment(date * 1000).format('YYYY-MM-DD HH:mm:ss')
- }
-
- //更新已经加载的数据isLoaded: true,存入状态机
- function updateLoadedData() {
-
- let bbarr = cloneDeep(store.state.loadedTestData)
- bbarr.push({ ...unref(newData), isLoaded: true })
- store.commit('LOADED_TEST_DATA',bbarr)
- }
-
-
- const { target, result, stopObserver } = useLazyData(getDeadline)
- //监听穿入子组件的props数据
- watch(
- modelValue,
- newValue => {
-
- let originArr = cloneDeep(store.state.loadedTestData)
- if (originArr.length > 0) {
- // 停止观察已经加载的节点
- const hasSameId = originArr.some(item => item.id === unref(modelValue)?.id && item.isLoaded)
- if (hasSameId) {
- stopObserver()
- const item = originArr.find(item => item.id === unref(modelValue)?.id && item.isLoaded)
- newData.value.end_time = formateEndTime(item.end_time)//重新赋值为原来的数据
- }
- }
-
- },
- { deep: true, immediate: true }
- )
-
-
- <vxe-column
- :key="index"
- v-bind.sync="column"
- :field="column.prop"
- :title="column.label"
- width="item.minWidth"
- show-overflow
- :formatter="column.prop === 'test_state' ? formatTestState : null"
- :sortable="column.prop !== 'end_time'"
- v-if="column.checked"
- >
- <template v-else-if="column.prop === 'end_time'" #default="{ row }">
-
- <battary-loading :end-time="row.end_time" :model-value.sync="row" @update="getTableRow">battary-loading>
- template>
- <vxe-column/>
-
-
- //在nMounted里面重置为[]
- onMounted(() => {
-
- store.commit('LOADED_TEST_DATA',[])
- })
- //如果有分页,可在分页事件中将OADED_TEST_DATA重新置为空数组