聊聊 Vue 中 title 的动态修改
由于之前的 Vue 项目打包成果物一直是嵌入集成平台中,所以一直没有关注过项目的 title。直到最近,突然有个需求,要求点击按钮在集成平台外新开一个页面,此时我才发现,原来我的项目的 title 一直是万年不变的 vue-project。理所应当的,这个问题被测试爸爸提了一个大大的缺陷。
犯了错的我赶紧解决这个问题,但是经过一段时间的摸索,我却发现,这一个小小的问题,却有着很多不同的解法。
首先,毫无疑问的是,我们应该使用 document.title
方法通过 DOM 操作来修改 title 的值。此时,距离解决问题还差两步:
- 如何传递 title?
- 何时修改 title?
ps:很多人提到过在微信或者一部分 IOS webview (下文一律以微信指代)中无法通过 document.title
方法修改 title 的值,这个问题的解决方案在文末的彩蛋中会提及。
title 的传递
接下来进入第一个重点:title 的传递。根据传递 title 值的方式,分为两种方案:
- 全局变量传递
- 路由传递
何为全局变量传递?全局变量传递指的是所有页面维护同一个全局变量,切换页面对其重新赋值,最常见的方法是使用 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 中 axios 的封装
聊聊 Vue 中 axios 的封装 axios 是 Vue 官方推荐的一个 HTTP 库,用 axios 官方简介来介绍它,就是: Axios 是一个基于 promise 的 HTTP 库,可以用在 ...
- 聊聊 Vue 中 provide/inject 的应用
众所周知,在组件式开发中,最大的痛点就在于组件之间的通信.在 Vue 中,Vue 提供了各种各样的组件通信方式,从基础的 props/$emit 到用于兄弟组件通信的 EventBus,再到用于全局数 ...
- 解决vue中element组件样式修改无效
vue中element组件样式修改无效 <style> .detail{ .el-input__inner { height: 48px; } } </style> 直接写st ...
- 关于Unity中如何代码动态修改天空盒
在Unity中动态修改天空盒有两种方法: 一.为每个Texture建立天空盒材质球,需要更换时直接将对应材质球作为天空盒,缺点是建立的材质球太多 private void ChangeSkybox(M ...
- Vue中的循环以及修改差值表达式
0828自我总结 一.Vue中的循环 v-for 常见的4总情况 #第一种 <div v-for="item in items"></div> #第二种 & ...
- vue中v-bind:class动态添加class
1.html代码 <template v-for='item in names'> <div id="app" class="selectItem&qu ...
- 用document.title=“xxx”动态修改title,在ios的微信下面不生效的解决办法!
//需要jQuery var $body = $('body'); document.title = 'title'; // hack在微信等webview中无法修改document.title的情况 ...
- a 标签中 title 属性样式修改
无文字描述,直接上测试页,看效果. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
- vue中循环时动态绑定值
在vue项目中,有很多需要动态循环绑定的场景,在未知绑定数量的情况下只能动态生成绑定值 1.首先在data中定义一个对象,我在项目中时循环绑定下拉框,所以定义了一个selectVal = {} 2.在 ...
随机推荐
- 源生JS实现点击复制功能
之前在工作中,有位同事问过我一个问题,JS如何实现点击复制功能.给他解决后现在来总结归纳一下,顺便做个笔记. PS:此乃本人第一篇博客(跟着同事大佬学习),涉及知识尚浅,如有任何意见和建议请告知于我. ...
- Springboot关于tomcat容器配置、三大组件配置、拦截器配置
原文地址:http://www.javayihao.top/detail/172 1.tomcat配置 Springboot默认使用的就是嵌入式servlet容器即tomcat,对于web项目,如果使 ...
- 利用Python进行数据分析-Pandas(第五部分-数据规整:聚合、合并和重塑)
在许多应用中,数据可能分散在许多文件或数据库中,存储的形式也不利于分析.本部分关注可以聚合.合并.重塑数据的方法. 1.层次化索引 层次化索引(hierarchical indexing)是panda ...
- ETCD:etcd网关
原文地址:L4 gateway 什么是etcd网关 etcd网关是一个简单的TCP代理,可将网络数据转发到etcd集群.网关是无状态且透明的: 它既不会检查客户端请求,也不会干扰群集响应. 网关支持多 ...
- Java描述设计模式(09):装饰模式
本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景 1.场景描述 孙悟空有七十二般变化,他的每一种变化都给他带来一种附加的本领.他变成鱼儿时,就可以到水里游泳:他变成鸟儿时,就可以 ...
- python-Redis模块常用的方法汇总
Redes模块常用的方法汇总 一.创建建Redis对象 1.直接使用 import redis r = redis.Redis(host='127.0.0.1', port=6379) 2.连接池使用 ...
- springcloud 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...
- Python 類和對象 Class vs Object
類別定義 class 類別名: 例如: >>> class Point:... x = 0.0... y = 0.0 1. 宣告 >>> p1 = ...
- Spring Boot 2 + Thymeleaf:表单字段绑定、表单提交处理
Spring Boot中Thymeleaf对表单处理的一些用法:(1)使用th:field属性:进行表单字段绑定(2)使用ids对象:一般用于lable配合radio或checkbox使用(3)表单提 ...
- 安装上传下载插件,jdk及redis
安装rz sz (1)编译安装root 账号登陆后,依次执行以下命令:cd /tmpwget http://www.ohse.de/uwe/releases/lrzsz-0.12.20.tar.gzt ...