由于之前的 Vue 项目打包成果物一直是嵌入集成平台中,所以一直没有关注过项目的 title。直到最近,突然有个需求,要求点击按钮在集成平台外新开一个页面,此时我才发现,原来我的项目的 title 一直是万年不变的 vue-project。理所应当的,这个问题被测试爸爸提了一个大大的缺陷。
犯了错的我赶紧解决这个问题,但是经过一段时间的摸索,我却发现,这一个小小的问题,却有着很多不同的解法。
首先,毫无疑问的是,我们应该使用 document.title 方法通过 DOM 操作来修改 title 的值。此时,距离解决问题还差两步:
1.如何传递 title?
2.何时修改 title?
ps:很多人提到过在微信或者一部分 IOS webview (下文一律以微信指代)中无法通过 document.title 方法修改 title 的值,这个问题的解决方案在文末的彩蛋中会提及。
title 的传递
接下来进入第一个重点:title 的传递。根据传递 title 值的方式,分为两种方案:
1.全局变量传递
2.路由传递
何为全局变量传递?全局变量传递指的是所有页面维护同一个全局变量,切换页面对其重新赋值,最常见的方法是使用 Vuex,当然,如果你要使用 this.$root 甚至丧心病狂地想要使用 provide/inject 一样可以达到类似的效果。
路由传递的方法就比较容易理解了,即通过路由跳转传参传递 title 的值。由于业务逻辑中本身就包含大量的路由传参,为了解耦方便后续维护,推荐将 title 的值通过路由配置中的 meta 进行传递。
之后,通过访问当前路由对象($route)的 meta 属性即可获取到 title 值。
// router.js const routes = [ { path: '/', ... meta: { title: '首页' } }, { path: '/A', meta: { title: 'A模块' } } ] // 业务模块,获取 title ... beforeCreate () { console.log(this.$route.meta) } ...
通过上面的两种方法,可以顺利传递 title 的值。
title 的修改时机
完成了 title 值的传递,接下来我们谈谈何时该修改 title。
想到这个问题,大多数人第一个想到的应该就是在生命周期钩子中修改 title。
生命周期钩子
一般情况下,我们在 mounted 生命周期钩子中进行初始化请求,所以惯性思维之下,我在 mounted 中进行了 title 的修改。
// 业务代码 mounted () { document.title = this.$route.meta.title }
结果,效果不佳,标签页的 title 延迟 1 秒以上才成功修改。通过这个延迟可以发现,显然,我们的代码执行地太晚了!
回忆了一下 Vue 源码中初始化相关的代码细节,我们可以发现,我们甚至在 beforeCreate 钩子中就可以进行 title 的修改。
改动后的代码如下:
// 业务代码 beforeCreate () { document.title = this.$route.meta.title }
可以发现,修改后的代码效果明显好了许多,延迟感虽然还有,但是已经不太明显。
路由守卫
比起在生命周期钩子中修改 title 值,在路由跳转时利用路由守卫完成 title 的修改,岂不美哉?毕竟路由跳转发生在生命周期函数执行之前,使用路由守卫修改 title 值可以明显降低 title 修改的延时。
// router.js router.beforeEach((to, from, next) => { document.title = to.meta.title next() })
此时,我们基本完美完成了功能需求,但是,还是有一点小瑕疵——如果 meta 中没有定义 title 值,此时 title 值就变成了 undefined,扑街~
所以,我们需要设置默认的 title 值(一般可以是该项目的名称),作为 title 值不存在时的备胎。修改后的代码如下:
// router.js const defaultTitle = "默认 title" router.beforeEach((to, from, next) => { document.title = to.meta.title ? to.meta.title : defaultTitle next() })
到这里为止,我们完美实现了需求,并且实现了该功能与业务代码的解耦。
彩蛋1:使用 vue-meta 管理 title
vue-meta 插件在安装时,像 Vuex 类似,注入了全局状态——metaInfo,你可以通过定义 metaInfo 对象中的 title 属性,实现 title 的动态修改。
彩蛋2:vue-wechat-title 源码解析
在搜索相关资料的时候,vue-wechat-title 这个包的出现频率出乎意料的高,这个包主要解决了前面提到的那个问题:在微信中无法通过 document.title 方法修改 title 的值。当然,这个兼容性问题都能解决了,正常情况下的 title 修改当然不在话下。
我们先来看看 vue-wechat-title 的源码:
// vue-wechat-title 源码 (function () { // 插件安装钩子 function install (Vue) { var setWechatTitle = function (title, img) { if (title === undefined || window.document.title === title) { return } // 修改 title document.title = title var mobile = navigator.userAgent.toLowerCase() // 兼容性判断 if (/iphone|ipad|ipod/.test(mobile)) { // 创建空的 iframe,触发 onload 事件 var iframe = document.createElement('iframe') iframe.style.display = 'none' // 替换成站标favicon路径或者任意存在的较小的图片即可 iframe.setAttribute('src', img || 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7') // onload 回调函数 var iframeCallback = function () { setTimeout(function () { // 卸磨杀驴 iframe.removeEventListener('load', iframeCallback) document.body.removeChild(iframe) }, 0) } // 定义事件 iframe.addEventListener('load', iframeCallback) document.body.appendChild(iframe) } } // 定义全局指令, Vue.directive('wechat-title', function (el, binding) { // update 钩子,调用 title 修改函数 setWechatTitle(binding.value, el.getAttribute('img-set') || null) }) } if (typeof exports === 'object') { module.exports = install } else if (typeof define === 'function' && define.amd) { define([], function () { return install }) } else if (window.Vue) { Vue.use(install) } })()
由于微信浏览器只在onload 事件中通过 title 的值初始化标题,而后续的 title 修改,无法触发标题的修改。既然 onload 事件能够通过 title 修改标题,那么我创建一个空的 iframe 触发 onload 事件修改了标题后就移除它。这种方式根据 title 修改了标题,并且没有对页面造成额外的影响。
众所周知,vue-wechat-title 通过 v-wechat-title 指令来触发 title 的动态修改,每当指令的值修改后,触发 update 钩子中的回调函数——setWechatTitle。该函数通过前面提到的兼容性处理,实现了document.title 对标题的修改。
总结
以上所述是小编给大家介绍的Vue 中 title 的动态修改问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
本文向大家介绍聊聊vue 中的v-on参数问题,包括了聊聊vue 中的v-on参数问题的使用技巧和注意事项,需要的朋友参考一下 vue中v-on:clock的使用 最近在学习vue.js框架。记下其中遇到的一些问题,以便以后查阅。 首先,这是一个页面(为了便于观察,将各个标签都一一着色): 其中html代码: js部分的代码: 这时候如果点击cell中有颜色的区域(即点击li标签的字标签的时候),
主要内容:一、背景引入,二、Kafka分布式存储架构,三、Kafka高可用架构,四、Kafka写入数据丢失问题,五、Kafka的ISR机制是什么?,六、数据如何保证不丢失?,七、总结一、背景引入 这篇文章,给大家聊一下写入Kafka的数据该如何保证其不丢失? 看过之前的文章《字节面试官: 让你设计一个MQ每秒要抗几十万并发,怎么做?》的同学,应该都知道写入Kafka的数据是会落地写入磁盘的。 我们暂且不考虑写磁盘的具体过程,先大致看看下面的图,这代表了Kafka的核心架构原理。 二、Kafka分
本文向大家介绍聊聊Java并发中的Synchronized,包括了聊聊Java并发中的Synchronized的使用技巧和注意事项,需要的朋友参考一下 1 引言 在多线程并发编程中Synchronized一直是元老级角色,很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,本文详细介绍了Java SE1.6中为了减少获得锁
本文向大家介绍聊聊MySQL的COUNT(*)的性能,包括了聊聊MySQL的COUNT(*)的性能的使用技巧和注意事项,需要的朋友参考一下 前言 基本职场上的程序员用来统计数据库表的行数都会使用count(*),count(1)或者count(主键),那么它们之间的区别和性能你又是否了解呢? 其实程序员在开发的过程中,在一张大表上统计总行数是非常耗时的一个操作,那么我们应该用哪个方法统计会更快呢?
本文向大家介绍聊一聊Kafka Controller的作用?相关面试题,主要包含被问及聊一聊Kafka Controller的作用?时的应答技巧和注意事项,需要的朋友参考一下 负责管理集群broker的上下线,所有topic的分区副本分配和leader选举等工作。
本文向大家介绍聊一聊Ajax的优缺点,包括了聊一聊Ajax的优缺点的使用技巧和注意事项,需要的朋友参考一下 Ajax,全称 Asynchronous Javascript and XML,是一个动态的WEB应用的开发技术,它的出现丰富了用户的体验。甚至用Ajax开发的WEB应用可以达到桌面应用程序的体验。当然,和其他技术一样Ajax同样也有其自身的优点和缺点。 使用Ajax的优点 1. 提升用户体