设置组件内钩子

最后,我们还可以使用组件内 Hook 作为组件生命周期 Hook,我们希望将这些 Hook 的范围限制在组件级别,以便更好地维护代码,或者增强工作流程,使同一组件在特定用例中需要有不同的行为。

我们现在可以拥有 About 组件,并定义 beforeRouteEnter() Hook,如下所示:

<script>
export default {
    data() {
        return {
            user: ''
        }
    },
    beforeRouteEnter(to, from, next) {
        if (!to.params || !to.params.user) {
            next(comp => {
                comp.user = 'Alex'
            })
        } else {
            next();
        }
    }
}
</script>

可以看到,在 beforeRouteEnter 期间我们无法访问组件的 this 作用域,因为触发时视图组件仍在创建中。幸运的是,我们可以通过传递给 next() 的回调来访问该实例。每当导航被确认时,这意味着组件被创建,回调将被触发,并且组件实例将作为回调的唯一参数(comp)。

对于 beforeRouteUpdatebeforeRouteLeave,组件已经创建,因此该实例可用,并且不需要 next() 回调。 事实上,在 beforeRouteEnter() 的使用中,只有 next() 支持回调函数。

beforeRouteUpdate 当同一个组件被不同的路由重用时被调用。 这适用于我们使用动态路由的情况,这将在下一节中讨论。

beforeRouteLeave 在组件将被停用或用户离开当前视图之前被触发。 这在新导航的 beforeEach 防护之前调用,通常在编辑器组件中使用,以防止用户在不保存的情况下导航离开。

在这个守卫中,我们可以通过将 false 传递给 next() 函数来取消新的导航。

例如,假设我们将以下 Hook 添加到 About.vue 文件中组件的选项中:

//...
beforeRouteLeave(to, from, next) {
    const ans = window.confirm('You are about to leave the About page. Are you sure?');
    next(!!ans);
}

当我们离开 About 页面时,将出现一个弹出对话框,要求确认,如下图所示,然后继续相应导航:

image 2023 10 14 22 46 44 989
Figure 1. Figure 6.30: Dialog asking to confirm before navigating away from the About page

在本节中,我们研究了如何设置组件内 Hook,即仅限于特定组件的 Hook。 我们为 About 组件设置了一个组件内 Hook,要求用户在离开页面之前进行确认。 在下一节中,我们将把消息列表移动到外部文件中,仅当 MessageFeed 处于视图中时才加载。

练习 6.04:将消息列表提取到外部文件并仅在查看 MessageFeed 时加载它

回到 Exercise 6.03,将所选消息的内容传递到新消息页面并将其打印出来,现在我们将使用 beforeEnter 和 beforeRouteEnter 路由器挂钩进行一些代码增强。本练习旨在让您更熟悉如何使用路由器挂钩。

要访问本练习的代码文件,请参阅 https://packt.live/3lg1F2R

  1. 让我们从 ./src/views/MessageFeed 中提取消息静态数据。vue 并将其保存在 ./src/assets/messages.js 中:

    const messages = [
        'Hello, how are you?',
        'The weather is nice',
        'This is message feed',
        'And I am the fourth message'
    ];
    
    export default messages;
  2. 在 ./src/views/MessageFeed.vue 中,我们将本地数据属性替换为 props: { messages: { type: String, default: [] }}:

    export default {
        props: {
            messages: {
                type: Array,
                default: () => []
            }
        }
    }
  3. 现在我们需要加载消息列表,并在导航到消息路由时将其分配给消息参数。 我们将通过在路由的配置对象中使用 beforeEnter Hook 来完成此操作。 不要忘记添加 props: true 将参数标准化为相关的渲染 props。 您可以通过修改 src/router/index.js 中定义的 route 来做到这一点,如下所示:

    {
        path: '/messages',
        name: 'messageFeed',
        component: () => import(/* webpackChunkName: "messages" */'../views/MessageFeed.vue'),
        props: true,
        async beforeEnter(to, from, next) {
            next()
        }
    },
  4. 我们将通过导入(import)延迟加载消息列表:

    const module = await import (/* webpackChunkName: "messagesFeed" */ '../assets/messages.js');
  5. 然后,检索所需的信息,如下所示:

    const messages = module.default;
    if (messages && messages.length > 0) {
        to.params.messages = messages;
    }
  6. src/router/index.js 中路由的完整代码应如下所示:

    {
        path: '/messages',
        name: 'messageFeed',
        component: () => import(/* webpackChunkName: "messages" */ '../views/MessageFeed.vue'),
        props: true,
        async beforeEnter(to, from, next) {
            if (!to.params || !to.params.messages) {
                const module = await import (/* webpackChunkName: "messagesFeed" */ '../assets/messages.js');
                const messages = module.default;
                if (messages && messages.length > 0) {
                    to.params.messages = messages;
                }
            }
            next()
        }
    },

查看网站时,我们应该看到类似于上一个练习的消息源。 这如下面的屏幕截图所示:

image 2023 10 14 22 57 18 408
Figure 2. Figure 6.31: Message Feed page after refactoring

至此,我们已经学习并实践了如何使用不同的路由 Hooks 在应用程序中配置路由器、传递参数以及拦截页面之间的导航。在下一节中,我们将讨论一个更高级的主题——动态路由。