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

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

(0)

相关推荐

  • vue cli2.0单页面title修改方法

    一.npm install vue-wechat-title --save  执行命令 二.在main.js中添加 Vue.use(VueWechatTitle); Vue.config.productionTip= false 三.在router/index.js文件中添加 routes: [{ path: '/',redirect: 'Home' },{ path: '/Home',name: 'Home',component: Home, meta:{ title:'银行开户' }},],

  • 解决vue单页面应用中动态修改title问题

    详细信息查看:vue-weachat-title 解决问题: 1.Vuejs 单页应用在iOS系统下部分APP的webview中 标题不能通过 document.title = xxx 的方式修改 该插件只为解决该问题而生(兼容安卓) 2.在vue单页面中,通过浏览器分享到QQ.微信等应用中的链接,只有一个首页标题和默认icon图片 已测试:APP 微信 QQ 支付宝 淘宝 安装 npm install vue-wechat-title --save 用法 1.在main.js中引入 impor

  • 基于Vue的SPA动态修改页面title的方法(推荐)

    最近基于VUE做个SPA手机端web发现动态修改页面标题通过document.title=xxxx 来修改着实蛋疼,而且在IOS的微信端据说没效果.百度发现要针对IOS的微信做点额外的操作,即:创建一个隐藏的Iframe,然后随便加载一个图片文件,然后加载完成移除,这样就能修改页面title了.网上有几种方案: 1,App.Vue里面设置title属性,然后页面title去绑定,所有子组件修改标题就通过 this.$root.data.title=xxxxx;去修改 缺点:App.Vue默认的e

  • vue2中,根据list的id进入对应的详情页并修改title方法

    一般项目中,我们会遇到有个list...然后你随便点击一个,会进入他对应的详情页...正常,那个详情页是一个公共的组件,我们只需根据id传值来判断,这个页面显示的是哪个list的数据即可.如图:点击电影进入电影详情--以此类推 具体代码如下: (有人会奇怪,我为什么不循环--这个是根据项目需求而定的,这个相当于入口,而进入里面分别对应的还是多个list,并且后台给的图片的url也不一样,我懒得v-if去写了,so,这三个我就用了通过了路由id过去.当然,后面有循环list..两种不同的方式,大家

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

    由于之前的 Vue 项目打包成果物一直是嵌入集成平台中,所以一直没有关注过项目的 title.直到最近,突然有个需求,要求点击按钮在集成平台外新开一个页面,此时我才发现,原来我的项目的 title 一直是万年不变的 vue-project.理所应当的,这个问题被测试爸爸提了一个大大的缺陷. 犯了错的我赶紧解决这个问题,但是经过一段时间的摸索,我却发现,这一个小小的问题,却有着很多不同的解法. 首先,毫无疑问的是,我们应该使用 document.title 方法通过 DOM 操作来修改 title

  • 浅谈vue单一组件下动态修改数据时的全部重渲染

    今天在学习vue的过程中,发现一个有趣的现象. 在某一组件下的某一数据通过点击事件被动态修改的时候,对应view中的数据同步的进行了修改,没错,这不是废话吗,vue的一大特色就是数据的双向绑定.可有趣的是,该组件下我写的另一个用Math.random()的data值对应的值和视图也发生了变化 这就让我这个刚入门的小白有点奇怪了,我修改一个,怎么变了两个????脑洞放开一想,会不会数据在双向同步的时候,发生了什么,比如.是不是只要有一个节点变了,node都重新进行了加载??? 我想这其中的缘由必定

  • 聊聊Vue中provide/inject的应用详解

    众所周知,在组件式开发中,最大的痛点就在于组件之间的通信.在 Vue 中,Vue 提供了各种各样的组件通信方式,从基础的 props/$emit 到用于兄弟组件通信的 EventBus,再到用于全局数据管理的 Vuex. 在这么多的组件通信方式中,provide/inject 显得十分阿卡林(毫无存在感).但是,其实 provide/inject 也有它们的用武之地.今天,我们就来聊聊 Vue 中 provide/inject 的应用. 何为 provide/inject provide/inj

  • vue中element组件样式修改无效的解决方法

    如下所示: <style> .detail{ .el-input__inner { height: 48px; } } </style> 直接写style注意不加scoped,然后用一个组件最外层的class包裹住,就不会改到所有的组件的样式了. 以上这篇vue中element组件样式修改无效的解决方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们. 您可能感兴趣的文章: Vue 组件间的样式冲突污染 浅谈vue中改elementUI默认样式引发的st

  • vue中如何让子组件修改父组件数据

    一.关于vue中watch的认识 我们要监听一个属性的的变化就使用watch一般是父组件传递给子组件的时候 •1.常见的使用场景 ... watch:{ value(val) { console.log(val); this.visible = val; } } ... •2.如果要一开始就执行 ... watch: { firstName: { handler(newName, oldName) { this.fullName = newName + '-' + this.lastName;

  • vue中img src 动态加载本地json的图片路径写法

    目录: 注意:本地json文件和json文件里的图片地址都必须写在static 静态文件夹里:否则json文件里的url地址找不到. major_info.json文件里的图片路径写法 页面通过v-bind的方式加载: PS:vue中图片src路径赋值 vue中引入static文件夹中图片,本以为src中直接写入图片所在路径即可,结果发现图片无法显示,控制台报404错误,图片无法找到.网上找到解决方案,在此mark一下,以便以后查询. 图片src路径动态赋值 <img class="thu

  • Vue中的循环及修改差值表达式的方法

    一.Vue中的循环 v-for 常见的4总情况 #第一种 <div v-for="item in items"></div> #第二种 <div v-for="(item, index) in items"></div> #第三种 <div v-for="(val, key) in object"></div> #第四种 <div v-for="(val, n

  • 聊聊vue 中的v-on参数问题

    vue中v-on:clock的使用 最近在学习vue.js框架.记下其中遇到的一些问题,以便以后查阅. 首先,这是一个页面(为了便于观察,将各个标签都一一着色): 其中html代码: <div class="groupbody "> <ul class="list "> <li v-for="cell in todo.groupbody " class="pagegroupcell " v-on:

  • 简单聊聊Vue中的计算属性和属性侦听

    目录 1. 计算属性 语法:  1.简写方式: 语法:  2.完整写法: 2. 监视(侦听)属性 1. 监视属性watch: 2. 深度监视 3. 区别和原则 总结 1. 计算属性 定义 计算属性:要用的属性不存在,要通过已有属性计算得来,计算属性要有一个全新的配置项computed 对Vue来说,data里面的数据就是属性,只要Vue中的数据改变,就会重新解析模板,遇到插值语法里的方法会重新调用 原理 底层借助了Objcet.defineproperty方法提供的getter和setter.

  • 详细聊聊vue中组件的props属性

    目录 问题一:那props具体是怎么使用呢?原理又是什么呢?往下看 问题二:那如果我们想给年龄加1岁,怎么实现? 问题三:对于年龄这一类型,我们最希望拿到的是什么数据类型? 问题四:可以限制类型,那是不是也可以限制是否必传呢? 问题五:props接收的属性值可以修改吗? 问题六:必须要修改props属性值,怎么办? 总结:配置项props 总结 今天这篇文章,让你彻底学会props属性-- props主要用于组件的传值,他的工作就是为了接收外面传过来的数据,与data.el.ref是一个级别的配

随机推荐