全局mixins多次触发-Vue

时间:2019-05-14 17:29:28

标签: javascript typescript vue.js

我使用[Authorize(Policy = "CustomPolicy", Roles = "Admin")] 和全局混合来创建了一个混合来改变页面标题。

我的混合文件(title.ts):

document.title

然后我在main.ts中全局注册了该mixin:

import { Vue, Component } from 'vue-property-decorator'

function getTitle(vm: any): string {
  const title: string = vm.title
  if (title) {
    return `${title} | site.com`
  }
  return 'Admin panel | site.com'
}

@Component
export default class TitleMixin extends Vue {
  public created(): void {
    const title: string = getTitle(this)
    if (title) {
      document.title = title
    }
  }
}

然后在Vue组件中设置标题:

import titleMixin from '@/mixins/title'
Vue.mixin(titleMixin)

我在项目中有5个组件,如果我在mixin中使用@Component export default class Login extends Vue { public title: string = 'New title' } ,我会看到它在每个组件中逐步触发,因此console.log由最后一个组件设置document.title钩子。

如何正确设置当前页面的标题?

3 个答案:

答案 0 :(得分:2)

正如您所说,全局混合将影响Vue应用程序中的每个组件,这意味着设置document.title的逻辑将在应用程序中每个组件的created挂钩中触发。 / p>

我认为您正在寻找的是VueRouter的beforeRouteEnter钩子,该钩子是one of the navigation guards,该库可用于您的任何组件。组件的beforeRouteEnter挂钩会在路线更改为与之关联的那个路线之前立即触发。

在您的情况下,它看起来像这样:

@Component
export default class TitleMixin extends Vue {
  public beforeRouteEnter(to, from, next): void {
    next(vm => {
      const title: string = getTitle(vm)
      if (title) {
        document.title = title
      }
    })
  }
}

您会注意到next函数(解析路径需要调用)传递了一个回调,该回调具有对组件实例(vm)的引用。正在传递给getTitle而不是this。这是必需的,因为beforeRouteEnter钩子没有对this的引用。您可以阅读我链接到的文档以了解更多信息。

答案 1 :(得分:0)

请尝试将route meta fieldglobal resolve guard一起使用,而不是创建全局mixin。

首先,我们首先向RouteConfig文件中的每个/router/routes.ts添加一个meta字段:

import { RouteConfig } from 'vue-router'

export default [
  {
    path: '/login',
    name: 'Login',
    component: () => import(/* webpackChunkName: 'login-view' */ '@views/Login.vue'),
    meta: {
      title: 'Login', // Set the view title
    },
  },
  // ... Add the title meta field to each `RouteConfig`
] as RouteConfig[]

然后,我们将在/router/index.ts文件中创建一个全局解析保护,以将title meta字段设置为文档标题:

import Vue from 'vue'
import Router, { Route } from 'vue-router'
import routes from './routes'

Vue.use(Router)

const router = new Router({
  // ... RouterOptions
})

// Before each route resolves...
// Resolve guards will be called right before the navigation is confirmed,
// after all in-component guards and async route components are resolved.
router.beforeResolve((routeTo, routeFrom, next) => {

  const documentTitle = getRouteTitle(routeTo)

  // If the `Route` being navigated to has a meta property and a title meta field,
  // change the document title
  if (documentTitle ) {
    document.title = documentTitle 
  }

  // Call `next` to continue...
  next()

  function getRouteTitle(route: Route): string {
    const title: string = route.meta && route.meta.title
    if (title) {
      return `${title} | site.com`
    }
    return 'Admin panel | site.com'
  }
})

export default router

答案 2 :(得分:-1)

您应仅在页面的父组件(包含所有页面本身的组件)中使用mixin。

使用> db.test_coll.insert({string: `3~!@#$%^&*()__+}{|":<>?/.,';\][NAME`}); WriteResult({ "nInserted" : 1 }) > db.test_coll.find({string: "3~!@#$%^&*()__+}{|\":<>?/.,';\][NAME" }); { "_id" : ObjectId("5cdafcb1176f787fae2db871"), "string" : "3~!@#$%^&*()__+}{|\":<>?/.,';][NAME" } 的方式应为:

vue-property-decorator

也不要使用import { Vue, Component, Mixins } from 'vue-property-decorator'; @Component export default class Login extends Mixins(titleMixin) { public title: string = 'New title' } 将其全局导入。这样就可以为所有组件导入它。