【问题标题】:VueJS SSR + Quasar - How to call "mounted" in ssr?VueJS SSR + Quasar - 如何在 ssr 中调用“挂载”?
【发布时间】:2020-10-23 15:47:48
【问题描述】:

根据文档:

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

由于没有动态更新,在所有的 Vue 生命周期钩子中,只有 beforeCreate 和 created 会在 SSR 期间被调用。这意味着其他生命周期钩子(例如 beforeMount 或mounted)中的任何代码都只会在客户端上执行。

我对如何进行此调用感到困惑。我有一些无法在服务器上运行的东西。我猜想单独“安装”会导致它触发,但这似乎没有发生。

为了添加一点上下文,我正在使用基础构建一个下拉菜单。我让它在标准 Vue(非 ssr)上工作。

文件如下所示:

<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'))
            })
        },
    }
}

当sidenav渲染时,客户端看不到它,导致这个错误:

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

这是错误的,因为菜单确实呈现,控制台中没有mt 的日志,尽管pref 确实有日志。这会导致页面呈现的许多其他问题(它不会没有硬刷新)。

boot/sidenav下的文件长这样:

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

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

quasar.conf 有这个:

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

客户端看不到foundationosmd。两者都不能在服务器上运行,因为它们都需要window 才能运行。这让人倍感困惑,因为 sidenav 确实呈现并表现得像一个反应组件。

【问题讨论】:

    标签: javascript vue.js server-side-rendering quasar-framework


    【解决方案1】:

    只有 beforeCreate 和 create 在 SSR 和客户端调用。使用此组件查看运行中的生命周期。

    <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>
    
    

    【讨论】:

    • 我放弃了。理论上,Quasar 应该同时运行 SSR 和 F/E,但它并没有像宣传的那样工作。
    • Quasar 扩展了 Vue SSR。代码在服务器上呈现,然后传递给浏览器。来自Vue SSR docs,服务器上的数据反应性 在仅限客户端的应用程序中,每个用户都将在其浏览器中使用该应用程序的新实例。对于服务器端渲染,我们希望是一样的:每个请求都应该有一个新的、隔离的应用程序实例,这样就不会有交叉请求的状态污染。
    • 问题中的引述来自 Quasar 文档,是的,我通读并研究了 Vue SSR 文档(仅 70% 正确)。在退出之前,我在 SSR 上工作了 3 周。
    猜你喜欢
    • 2018-07-09
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 2020-09-19
    • 2020-09-08
    • 2020-08-26
    • 1970-01-01
    相关资源
    最近更新 更多