简体   繁体   English

VueJS SSR + Quasar - 如何在 ssr 中调用“挂载”?

[英]VueJS SSR + Quasar - How to call “mounted” in ssr?

According to the docs:根据文档:

https://quasar.dev/quasar-cli/developing-ssr/writing-universal-code#Component-Lifecycle-Hooks https://quasar.dev/quasar-cli/developing-ssr/writing-universal-code#Component-Lifecycle-Hooks

Since there are no dynamic updates, of all the Vue lifecycle hooks, only beforeCreate and created will be called during SSR.由于没有动态更新,在所有的 Vue 生命周期钩子中,只有 beforeCreate 和 created 会在 SSR 期间被调用。 This means any code inside other lifecycle hooks such as beforeMount or mounted will only be executed on the client.这意味着其他生命周期钩子(例如 beforeMount 或mounted)中的任何代码都只会在客户端上执行。

I'm confused at how to make this call happen.我对如何进行此调用感到困惑。 I have some stuff that can't run on the server.我有一些无法在服务器上运行的东西。 I would have guessed that having "mounted" alone would cause it to fire, but that doesn't seem to happen.我猜想单独“安装”会导致它着火,但这似乎没有发生。

To add a little context, I'm building a drop-down menu using foundation.为了添加一点上下文,我正在使用基础构建一个下拉菜单。 I have it working on standard Vue (non-ssr).我让它在标准 Vue(非 ssr)上工作。

The file looks like this:该文件如下所示:

<template>

<ul class="vertical menu accordion-menu" data-accordion-menu data-multi-open="false">
    <li v-for="i in htmlData.sidenav" :key="i.title">
        <router-link v-bind:to=i.href>{{ i.title }}</router-link>
        <ul class="menu vertical nested" v-if="i.sub1">
            <li v-for="j in i.sub1" :key="j.name">
                <router-link v-bind:to=j.href>{{ j.name }}</router-link>
                <ul class="menu vertical nested" v-if="j.sub2">
                    <li v-for="k in j.sub2" :key="k.name">
                        <router-link v-bind:to=k.href>{{ k.name }}</router-link>
                      </li>
                  </ul>
              </li>
          </ul>
      </li>
  </ul>
</div>


</template>


<script>
import SideNav from '../store/modules/sidenav'
import $ from 'jquery'

export default {
    name: 'sidenav',

    computed: {
        htmlData () {
            this.acc()
            return this.$store.state.sn.nav
        }
    },

    // Server-side only
    serverPrefetch () {
        this.$store.registerModule('sn',  SideNav)
        return this.getData()
    },

    // Client-side only
    mounted () {
        console.log('mt')
        const doesExist = !!this.$store.state.sn.nav
        this.$store.registerModule('sn', SideNav, { preserveState: true })

        if (!doesExist) {
            this.getData()
        }
    },

    destroyed () {
        this.$store.unregisterModule('sn')
        this.menu.destroy()
    },

    methods: {
        async getData () {
            return this.$store.dispatch('sn/snav')
        },

        acc () {
            this.$nextTick(function () {
                this.menu = new this.$foundation.AccordionMenu($('.accordion-menu'))
            })
        },
    }
}

While the sidenav does render, the client is unable to see it, which results in this error:当 sidenav 渲染时,客户端无法看到它,这会导致此错误:

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'AccordionMenu' of undefined

This is wrong because the menu does render, there is no log of mt in console, although pref does log.这是错误的,因为菜单确实呈现,控制台中没有mt的日志,尽管pref确实记录了。 This causes a slew of other problems with page rendering (it doesn't without hard refresh).这会导致页面呈现的许多其他问题(它并非没有硬刷新)。

The file under boot/sidenav looks like this: boot/sidenav下的文件如下所示:

// const SideNav = () => import('../layouts/SideNav.vue')
import SideNav from '../layouts/SideNav.vue'

export default async ({ Vue }) => {
    Vue.component('side-nav', SideNav)
}

And the quasar.conf has this: quasar.conf 有这个:

        boot: [
            'axios',
            'sidenav',
            'notemenu',
            {
                path: 'foundation',
                server: false
            },
            {
                path: 'osmd',
                server: false
            }
        ],

The client can't see either foundation or osmd .客户端看不到foundationosmd Neither can run on the server since they both require window to run.两者都不能在服务器上运行,因为它们都需要window才能运行。 It's doubly confusing because sidenav does render and behave like a reactive component.这让人倍感困惑,因为sidenav确实呈现并表现得像一个反应组件。

Only beforeCreate and create are called in SSR and client-side.只有 beforeCreate 和 create 在 SSR 和客户端调用。 Use this component to see the lifecycle in action.使用此组件查看运行中的生命周期。

<template>
<div>Hello World</div>
</template>

<script>
export default {
name: "Test",
beforeCreate() {
 console.log('beforeCreate', process.env, this)
},
created() {
 console.log('created', process.env, this)
},
beforeMount() {
 console.log('created', process.env, this)
},
mounted() {
 console.log('mounted', process.env, this)
},
beforeUpdate() {
 console.log('beforeUpdate', process.env, this)
},
updated() {
 console.log('updated', process.env, this)
},
beforeDestroy() {
 console.log('beforeDestroy', process.env, this)
},
destroyed() {
 console.log('destroyed', process.env, this)
},
preFetch() {
 console.log('preFetch', process.env, this)
}
}
</script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM