Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 全局混合多次激发-Vue_Javascript_Typescript_Vue.js - Fatal编程技术网

Javascript 全局混合多次激发-Vue

Javascript 全局混合多次激发-Vue,javascript,typescript,vue.js,Javascript,Typescript,Vue.js,我使用document.title和全局mixin创建了一个mixin来更改页面标题 我的混音文件(title.ts): 然后我在main.ts中全局注册了这个mixin: import titleMixin from '@/mixins/title' Vue.mixin(titleMixin) 然后在Vue组件中设置标题: @Component export default class Login extends Vue { public title: string = 'New tit

我使用
document.title
和全局mixin创建了一个mixin来更改页面标题

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

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

import titleMixin from '@/mixins/title'
Vue.mixin(titleMixin)
然后在Vue组件中设置标题:

@Component
export default class Login extends Vue {
  public title: string = 'New title'
}
我的项目中有5个组件,如果我在mixin中使用
console.log
,我可以看到它在每个组件中一步一步地启动,因此
document.title
由最后一个组件
created()
hook设置


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

您应该只在页面的父组件(保存所有页面本身的组件)中使用mixin

使用
vue属性装饰器时,应采用以下方式:

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

@Component
export default class Login extends Mixins(titleMixin) {
  public title: string = 'New title'
}

并且不要使用
Vue.mixin(titleMixin)
全局导入它。通过这种方式,它将为所有组件导入。

正如您所说,全局混合将影响Vue应用程序中的每个组件,这意味着设置
文档的逻辑。title
将在应用程序中每个组件的
创建的
钩子中触发

我认为您需要的是VueRouter的
beforeRouteEnter
hook,它是库提供给您的任何组件的。组件的
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
钩子没有对
的引用。您可以阅读我链接到的文档以了解更多信息。

不要创建全局混合,请尝试使用

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

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[]
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
然后,我们将在
/router/index.ts
文件中创建一个全局解析卫士,将标题元字段设置为文档标题:

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

关于您的问题,您应该看一看,很可能您并不是懒散地加载视图,因此在每个视图中调用
创建的
生命周期挂钩,这就是为什么最后一个要设置
document.title
。试着用
挂载的
钩子代替。@Ricky,问题是,我实际上在项目中使用了延迟加载:
组件:()=>导入('@/views/Login.vue')
。我仍然不明白,为什么
created()
会为每个组件触发,而不是只为当前组件触发?顺便说一下,你是对的,在
mounted()
中,它只发射了一次。再次阅读生命周期。我需要在所有组件中导入它,这就是为什么我在主文件中使用
Vue.mixin()
。正如@ricky指出的,问题在于
created()
hook,即使使用惰性加载,它似乎也会被触发。您的变体也是可行的,但它涉及到一个
组件。registerHooks
在类中使用
beforeRouterner
,因此在我的例子中它更多的是不必要的代码:D您能解释一下,为什么我的例子中每个组件都会触发
created()
,是的,无论组件是否延迟加载,在创建组件时总是触发
created
钩子。问题在于,您正在使用全局mixin来指定在创建应用程序中的每个组件时,它应该运行您的逻辑来设置文档标题。我希望@ricky建议使用
mounted
也会面临同样的问题,尽管我不确定您是如何初始化路由器视图的。实际上
mounted()
只触发了一次。我的路由器是Vue CLI 3 generator的标准配置。有什么想法吗?你可以在一个干净的项目上测试自己,如果你使用全局混合和
created()
生命周期,它实际上会在每个组件上激发。如果你说你现在使用全局混合为每个组件指定一个要在
mounted
钩子中运行的函数,并且该函数只运行一次,那就意味着你在你的应用程序中只安装了一个组件。我希望当您更改路由时,关联组件的
挂载的
钩子将再次调用该函数。如果看不到您的代码,很难判断。嗯,
mounted()
是在实际安装组件时触发的,例如,在我的情况下,当我访问页面时,
Login.vue
。因此,当我访问
Login.vue
时,我的标题更改为“Login”,当我离开此组件时,它被
销毁()
,新组件
仪表板.vue
已装入()。现在逻辑上是正确的。但是我想,
created()
hooks的工作方式也是一样的。真奇怪。