聊聊Vue 中 title 的动态修改问题


Posted in Javascript onJune 11, 2019

 由于之前的 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 的动态修改问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
一个不错的应用,用于提交获取文章内容,不推荐用
Mar 03 Javascript
JavaScript高级程序设计 客户端存储学习笔记
Sep 10 Javascript
Jquery同辈元素选中/未选中效果的实例代码
Aug 01 Javascript
JS连接SQL数据库与ACCESS数据库的方法实例
Nov 21 Javascript
script标签属性用type还是language
Jan 21 Javascript
jQuery插件Elastislide实现响应式的焦点图无缝滚动切换特效
Apr 12 Javascript
使用Raygun来自动追踪AngularJS中的异常
Jun 23 Javascript
jQuery下拉框的简单应用
Jun 24 Javascript
Node.js数据库操作之查询MySQL数据库(二)
Mar 04 Javascript
Angularjs上传文件组件flowjs功能
Aug 07 Javascript
详解vue-admin和后端(flask)分离结合的例子
Feb 12 Javascript
layer关闭弹出窗口触发表单提交问题的处理方法
Sep 25 Javascript
vue+element模态框中新增模态框和删除功能
Jun 11 #Javascript
vue.js中导出Excel表格的案例分析
Jun 11 #Javascript
ES6 Proxy实现Vue的变化检测问题
Jun 11 #Javascript
webpack实践之DLLPlugin 和 DLLReferencePlugin的使用教程
Jun 10 #Javascript
vue2 中二级路由高亮问题及配置方法
Jun 10 #Javascript
JS中实现一个下载进度条及播放进度条的代码
Jun 10 #Javascript
vuex 中插件的编写案例解析
Jun 10 #Javascript
You might like
追忆往昔!浅谈收音机的百年发展历史
2021/03/01 无线电
深入了解php4(1)--回到未来
2006/10/09 PHP
php 各种应用乱码问题的解决方法
2010/05/09 PHP
利用中国天气预报接口实现简单天气预报
2014/01/20 PHP
php二维数组转成字符串示例
2014/02/17 PHP
destoon二次开发模板及调用语法汇总
2014/06/21 PHP
PHP实现基于mysqli的Model基类完整实例
2016/04/08 PHP
jQuery的Ajax的自动完成功能控件简要说明
2013/02/22 Javascript
javascript常用函数(2)
2015/11/05 Javascript
Jqgrid之强大的表格插件应用
2015/12/02 Javascript
JS实现的倒计时效果实例(2则实例)
2015/12/23 Javascript
基于gulp合并压缩Seajs模块的方式说明
2016/06/14 Javascript
jQuery flip插件实现的翻牌效果示例【附demo源码下载】
2016/09/20 Javascript
js以及jquery实现手风琴效果
2020/04/17 Javascript
angular4实现tab栏切换的方法示例
2017/10/21 Javascript
JavaScript实现为事件句柄绑定监听函数的方法分析
2017/11/14 Javascript
Vuex实现计数器以及列表展示效果
2018/03/10 Javascript
node前端开发模板引擎Jade的入门
2018/05/11 Javascript
详解Require.js与Sea.js的区别
2018/08/05 Javascript
vue通信方式EventBus的实现代码详解
2019/06/10 Javascript
python实现决策树C4.5算法详解(在ID3基础上改进)
2017/05/31 Python
Python正确重载运算符的方法示例详解
2017/08/27 Python
简单了解Python读取大文件代码实例
2019/12/18 Python
python实现在一个画布上画多个子图
2020/01/19 Python
Python集成开发工具Pycharm的安装和使用详解
2020/03/18 Python
anaconda安装pytorch1.7.1和torchvision0.8.2的方法(亲测可用)
2021/02/01 Python
CSS3 3D立方体效果示例-transform也不过如此
2016/12/05 HTML / CSS
美国职棒大联盟官方网上商店:MLBShop.com
2017/11/12 全球购物
The Hut美国/加拿大:英国领先的豪华在线百货商店
2019/03/26 全球购物
应聘医学检验人员自荐信
2013/09/27 职场文书
个人求职信范文
2014/05/24 职场文书
娱乐节目策划方案
2014/06/10 职场文书
专升本学生毕业自我鉴定
2014/10/04 职场文书
如何Tomcat中使用ipv6地址
2022/05/06 Servers
Android RecyclerView实现九宫格效果
2022/06/28 Java/Android
Spring Boot 的创建和运行示例代码详解
2022/07/23 Java/Android