当 Flickity 使用轮播渲染子组件时,Nuxt 应用程序抛出“无法读取未定义的属性”

Posted

技术标签:

【中文标题】当 Flickity 使用轮播渲染子组件时,Nuxt 应用程序抛出“无法读取未定义的属性”【英文标题】:Nuxt app throwing "Cannot read properties of undefined" when child component renders with a carousel by Flickity 【发布时间】:2021-12-03 23:17:34 【问题描述】:

我正在尝试将我自己的自定义按钮链接到 nuxt 应用程序中的轻弹轮播。我的父组件将属性direction 的默认值设置为left

<CarouselBase class="w-screen carousel" :direction="direction">
  <items/>
</CarouselBase>

data() 
  return 
    direction: 'left',  
  ,

这是我的轮播组件的代码。

<template>
    <ClientOnly>
        <Flickity
            ref="flickity"
            :key="keyIncrementer"
            class="carousel"
            :class=" 'carousel--active': active "
            :options="computedOptions"
        >
            <slot />
        </Flickity>
    </ClientOnly>
</template>

<script>

export default 
    name: 'BaseCarousel',
    props: 
        direction: 
            type: String,
            default: '',
        ,
    ,
    mounted() 
        if (this.direction === 'right') 
            this.$refs.flickity.next()
         else if (this.direction === 'left') 
            this.$refs.flickity.previous()
        
    ,
    

我的插件文件夹中有这个文件vue-flickity.js

import Vue from 'vue'
import Flickity from 'vue-flickity'

Vue.component('Flickity', Flickity)

我收到此错误消息 =>

Cannot read properties of undefined (reading 'previous')

我不知道如何解决这个问题...

【问题讨论】:

为什么不尝试从组件内部的“vue-flickity”而不是插件中导入 Flickity,并将其添加到“组件”属性中?因为到目前为止,由于某种原因,Flickity 似乎没有从插件中获取。 你到底想在这里做什么?在mounted() 上滑动滑块?您不应该像文档中那样使用带有@click 的方法吗?反正组件挂载了直接滑动有什么意义? @StasParshin 这个不起作用,因为包不处理 s-s-r 并且只是崩溃。我们在作者之前的一个问题中发现了这一点。 我不想在挂载时直接滑动滑块,但我将其初始化为“左”而不是空字符串(“”),以便查看道具“左”时会发生什么原因很简单,现在我不知道如何在道具更改值时重新渲染轮播。无论如何,现在我刚刚尝试使用文档中的 @click 并收到相同的错误消息。 你实际上不需要在这里初始化任何东西。轮播的内部状态将为您处理previousnext 步骤。你也不需要让它重新渲染。你可以使用你的 Vue 开发工具,用$vm0 包裹元素并手动切换它,它会正确移动。你能用你迄今为止尝试过的内容来编辑你的问题吗? 【参考方案1】:

mounted 挂钩中尚不提供 flickity 模板引用,因为 &lt;Flickity&gt; 将在下一个循环中呈现。

使用$nextTick() callback 等待下一个渲染周期之前 访问mounted() 中的模板引用:

export default 
  async mounted() 
    // wait until next render cycle for refs to be available
    await this.$nextTick()

    if (this.direction === 'right') 
      this.$refs.flickity.next()
     else if (this.direction === 'left') 
      this.$refs.flickity.previous()
    
  ,

demo

【讨论】:

我已经尝试过你的演示,你的轮播正在使用 flickity 提供的按钮。我已经注释掉了整个异步 mouted 钩子,它的工作原理是一样的。看起来方向道具什么也没做。 @Maxime 不确定你在哪里看到你需要一个方向道具。正如我告诉你的,只需使用带有@click 事件的按钮,如文档中所述。 @kissu 我在文档中做了,去掉了方向道具。 @Maxime 是的。这个问题是关于为什么 this.$refs.flickitymounted 挂钩中未定义。与使用自定义按钮或 direction 道具无关,它们在您的单独问题中。【参考方案2】:

将轮播作为这样的组件

<template>
  <ClientOnly>
    <Flickity ref="flickity">
      <slot />
    </Flickity>
  </ClientOnly>
</template>

export default 
    name: 'BaseCarousel',

并在我的索引中使用我自己的自定义按钮

<template>
  <CarouselBase ref="flickityIndex">
    <items for the carousel/>
  </CarouselBase>
  <button @click="previous">Custom Previous Button</button>
  <button @click="next">Custom Next Button</button>
</template>

export default 
     methods: 
    next() 
      this.$refs.flickityIndex.$refs.flickity.next();
    ,
    
    previous() 
      this.$refs.flickityIndex.$refs.flickity.previous();
    
  

调用下一个或上一个需要通过$refs 到达flickity

【讨论】:

以上是关于当 Flickity 使用轮播渲染子组件时,Nuxt 应用程序抛出“无法读取未定义的属性”的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript响应式轮播图插件–Flickity

React 啥时候重新渲染子组件?

React.memo()、useCallback()、useMemo() 区别及基本使用

React 子组件在重新渲染时失去动画

react使用swiper轮播

React 子组件不会在其状态更改时重新渲染