【问题标题】:Create computed property dependent on variables within onMounted() lifecycle hook根据 onMounted() 生命周期钩子中的变量创建计算属性
【发布时间】:2021-08-21 05:41:03
【问题描述】:

我有一个组件需要使用 DOM 计算一些值,所以我有 onMounted() 生命周期挂钩。在onMounted() 中,我根据 DOM 元素计算了一些值(从技术上讲,它们是计算属性)。

然后我使用在另一个计算属性leftOffset 中找到的值。我需要在template 中使用leftOffset(它改变了一些CSS,并不真正相关)。

下面是我的setup():

setup() {
    let showContent = ref(false);
    
    let windowWidth = ref(null);
    let contentHider = ref(null);

    let contentHiderXPos ;
    let contentHiderWidth ;
    let leftWidth;

    onMounted(() => {
        // The DOM element will be assigned to the ref after initial render
        windowWidth = ref(window.innerWidth);

        contentHiderXPos = computed(() => contentHider.value.getBoundingClientRect().left);
        contentHiderWidth = computed(() => contentHider.value.getBoundingClientRect().width);
        leftWidth = computed(() => contentHiderXPos.value + contentHiderWidth.value);
    });

    let leftOffset = computed(() => {
        return -(windowWidth.value - leftWidth.value)
    });

    return {
        contentHider,
        leftOffset,
    }

contentHider 引用template 中定义的 div 之一的 DOM 元素。

我的问题是leftOffest.value 未定义,因为它尝试访问同样未定义的windowWidth.value 和leftWidth.value。我也尝试将leftOffset 放在onMounted() 中,但我无法从template 访问它(未定义)。

如何重新构造我的代码,以便既可以从template 访问leftOffset,也可以访问在onMounted() 中找到的值?

我在网上搜索过,但找不到任何特定于组合 API 的内容。

【问题讨论】:

    标签: vue.js vuejs3 vue-composition-api


    【解决方案1】:

    您对ref 的使用是错误的。按照下面sn-p中的cmets。

    这也是假设您不希望 window.innerwidth 具有反应性。

    // dont create another ref => you are trying to assign a new object here, thus breaking the reactivity
    // windowWidth = ref(window.innerWidth);
    // do this instead
    windowWidth.value = window.innerWidth
    

    如果您希望innerWidth 具有反应性,则必须像这样使用本机事件侦听器;

    const windowWidth = ref(window.innerWidth)
    onMounted(() => {
        window.addEventListener('resize', () => {windowWidth.value = window.innerWidth} )
    })
    onUnmounted(() => {
        window.removeEventListener('resize', () => {windowWidth.value = window.innerWidth})
    }) 
    

    【讨论】:

    • 如果我将windowWidth 设为计算属性,是否还需要向窗口添加事件侦听器以使innerWidth 具有响应性?
    • 是的,窗口属性在 Vue 中不是反应式的
    • 移除事件监听器有什么意义?
    • 因为如果组件被重新挂载,那么另一个事件监听器将被注册并且两个监听器都将被执行。它效率不高,也容易出错。
    • 没关系。您需要告诉从注册的事件侦听器中删除哪个函数。
    猜你喜欢
    • 1970-01-01
    • 2019-10-11
    • 2020-01-15
    • 2017-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    相关资源
    最近更新 更多