教你在微信中给 Vue 单页应用动态设置标题

6,285 阅读1分钟
前言

由于Vue React Angular等框架出来的应用都是SPA(single-page-application),所以就没有所谓的页面 都是router
而网页的标题 随着路由的改变而改变 也就成了一个需求

问题

在iOS的微信中 一个SPA应用 想要改变微信顶部导航栏的标题 使用document.title = xxx来改变网页标题是无效的

原因大致就是因为在微信中webview只加载网页标题一次 动态改变是无效的 除非都以新页面打开(那SPA的用户体验有什么卵用吗)

解决方案

既然js动态改变不能生效 那为什么不尝试在路由切换完成后 静默加载一个空iframe动态设置title呢?
这也是加载页面的一种方式不是吗?

代码 Github

file: utils/setWechatTitle.js

module.exports = function (title) {
  document.title = title
  var mobile = navigator.userAgent.toLowerCase()
  if (/iphone|ipad|ipod/.test(mobile)) {
    var iframe = document.createElement('iframe')
    iframe.style.visibility = 'hidden'
    // 替换成站标favicon路径或者任意存在的较小的图片即可
    iframe.setAttribute('src', '/static/logo.png')
    var iframeCallback = function () {
      setTimeout(function () {
        iframe.removeEventListener('load', iframeCallback)
        document.body.removeChild(iframe)
      }, 0)
    }
    iframe.addEventListener('load', iframeCallback)
    document.body.appendChild(iframe)
  }
}

file: main.js

import Vue from 'vue'
import App from './App'
import Router from 'vue-router'
import setWechatTitle from './utils/setWechatTitle.js'
Vue.use(Router)
var router = new Router()
// 这里用到的API是Vue-router1.x的对应Vuejs1.x
// 请注意根据不同版本的API去修改代码 包括下方的 afterEach
router.map({
  home: {
    name: 'home',
    title: '首页',
    component: require('./views/Home.vue')
  },
  order: {
    name: 'order',
    title: '订单',
    component: require('./views/Order.vue')
  },
  UCenter: {
    name: 'UCenter',
    title: '用户中心',
    component: require('./views/UCenter.vue')
  }
})
router.afterEach((transition) => {
  let title = transition.to.title + '-Custom-Suffix'
  setWechatTitle(title)
})
router.redirect({
  '*': '/home'
})
router.start(App, 'app')

效果


扩展

可以在路由的声明中 添加诸多自定义属性
比如: 是否需要后缀 是否需要前缀 等等自定义控制选项
本文仅作引导 有许多高级用法 需要自行扩展 在此不做细谈