使用reactive无法在更新后获取到vm中的bottomOffset,但是shallowReactive可以
来源:10-8 createMessage 编码第六部分

78264609
2024-11-08
老师,我这里使用了reactive在第一时间获取不到vm.exposed.bottomOffset中的属性,但是后面Message组件挂载完成后,也没有重新去执行getLastMessageBottomOffset函数去获取最新的vm中的数据,但是使用shallowReactive就可以,这不应该啊
//method.ts
import { render, h, nextTick, shallowReactive, reactive } from 'vue'
import type { MessageCreatorProps, MessageContext } from './types'
import Message from './Message.vue'
let lastMessageId = 1
const DkMessageContext:MessageContext[] = reactive([])
export const DkMessage = (props: MessageCreatorProps) => {
const id = `dk_message_${lastMessageId++}`
const container = document.createElement('div')
const _props = {
...props,
id,
onDestory: () => {
const index = DkMessageContext.findIndex((msg) => msg.id === id)
if (index === -1) return
DkMessageContext.splice(index, 1)
render(null, container)
},
}
const vnode = h(Message, _props)
render(vnode, container)
const message = {
id,
vnode: vnode,
vm: vnode.component!,
props: _props,
}
DkMessageContext.push(message)
nextTick(() => {
document.body.appendChild(container.firstElementChild!)
})
return DkMessageContext
}
export const getLastMessage = () => {
return DkMessageContext.at(-1)
}
export const getLastMessageBottomOffset = (id: number | string) => {
const index = DkMessageContext.findIndex((msg) => msg.id === id)
if (index > 0) {
console.log(
id,
'-find_index:',
index,
'-find_prev.vm:',
typeof DkMessageContext[index - 1].vm,
'-find_prev.vm-->bottomOffset',
DkMessageContext[index - 1].vm.exposed!.bottomOffset.value
)
}
if (index <= 0) {
return 0
} else {
const prev: MessageContext = DkMessageContext[index - 1]
return prev.vm.exposed!.bottomOffset.value
}
}
<!-- Message.vue -->
<template>
<div ref="messageRef" class="dk-message" :class="{
[`dk-message-${type}`]: type,
'is-close': showClose
}" :style="messageStyle" role="alert" v-if="messageShow">
<div class="dk-message__content">
<slot>
{{ lastMessageBottomOffset + ' ' + offset + ' ' + currentMessageTopOffset + ' ' + +messageHeight + ' ' +
currentMessageBottomOffset }}
<Render :vnode="message" />
</slot>
</div>
<span class="dk-message__close" v-if="message" @click="$event => messageShow = false">
<Icon icon="xmark"></Icon>
</span>
</div>
</template>
<script setup lang="ts">
import { computed, nextTick, onMounted, ref, watch } from 'vue';
import Render from '../common/Render';
import Icon from '../Icon/Icon.vue';
import type { MessageProps } from './types';
import { getLastMessageBottomOffset } from './method';
const props = withDefaults(defineProps<MessageProps>(), {
type: 'info',
duration: 3000,
offset: 20
})
const messageRef = ref<HTMLElement>()
const messageShow = ref(false)
const messageHeight = ref(0)
const lastMessageBottomOffset = computed(() => {
console.log(props.id, '-get_lastMessageBottomOffset--',getLastMessageBottomOffset(props.id))
return getLastMessageBottomOffset(props.id)
})
const currentMessageTopOffset = computed(() => props.offset + lastMessageBottomOffset.value)
const currentMessageBottomOffset = computed(() => currentMessageTopOffset.value + messageHeight.value)
const messageStyle = computed(() => ({
top: currentMessageTopOffset.value + 'px'
}))
const showing = () => {
if (props.duration <= 0) return
setTimeout(() => {
messageShow.value = false
}, props.duration)
}
watch(messageShow, (cur) => {
if (!cur) {
props.onDestory()
}
})
defineExpose({
bottomOffset: currentMessageBottomOffset
})
onMounted(async () => {
messageShow.value = true
showing()
await nextTick()
messageHeight.value = messageRef.value!.getBoundingClientRect().height
})
</script>
<style scoped>
.dk-message {
position: fixed;
top: 10%;
left: 50%;
padding: 4px 8px;
border: 2px solid black;
background: springgreen;
transform: translateX(-50%);
}
</style>
下面是我的项目地址
仓库地址
写回答
1回答
-
张轩
2024-11-09
同学你好
你说的vm.exposed.bottomOffset 这个直接是是 undefined 的对吗?我还没运行代码,先问一下
012024-11-09
相似问题