Поскольку упаковка предыдущего проекта Vue всегда была встроена в интеграционную платформу, я не обращал внимания на название проекта. До недавнего времени возникала внезапная потребность нажать кнопку, чтобы открыть новую страницу вне интегрированной платформы, а в это время я узнал, что название моего проекта не меняется уже десять тысяч лет.vue-project. Как и положено, этот вопрос был поставлен тестирующим папой как большой недостаток.
Если я ошибался, я быстро решал эту проблему, но после некоторого периода исследований я обнаружил, что у этой небольшой проблемы есть много разных решений.
Во-первых, нет сомнений в том, что мы должны использоватьdocument.titleМетод изменяет значение title посредством манипуляции с DOM. На данный момент от решения проблемы осталось два шага:
- Как сдать титул?
- Когда менять заголовок?
ps: Многие люди упоминали, что невозможно пройти в WeChat или некоторых веб-просмотрах IOS (далее WeChat)document.titleМетод модифицирует значение title Решение этой проблемы будет упомянуто в пасхалке в конце статьи.
Переход титула
Далее введите первый ключевой момент: передача титула. В зависимости от того, как передается значение title, есть два варианта:
- передача глобальной переменной
- маршрутизация
Зачем передавать глобальные переменные? Передача глобальной переменной означает, что все страницы поддерживают одну и ту же глобальную переменную и переключают страницы, чтобы переназначить ее.Наиболее распространенный метод — использование Vuex.Конечно, если вы хотите использоватьthis.$rootдаже безумно хочется использоватьprovide/injectАналогичного эффекта можно добиться.
Способ передачи маршрутизации проще для понимания, то есть значение title передается через параметры перехода маршрутизации. Так как сама бизнес-логика содержит большое количество параметров маршрутизации, для развязки и облегчения последующего обслуживания рекомендуется передавать значение title через мета в конфигурации маршрутизации.
После этого значение title можно получить, обратившись к метаатрибуту текущего объекта маршрута ($route).
// router.js
const routes = [
{
path: '/',
...
meta: {
title: '首页'
}
}, {
path: '/A',
meta: {
title: 'A模块'
}
}
]
// 业务模块,获取 title
...
beforeCreate () {
console.log(this.$route.meta)
}
...
Через два вышеупомянутых метода значение title может быть передано плавно.
Когда менять заголовок
Теперь, когда значение заголовка передано, давайте поговорим о том, когда пришло время изменить заголовок.
Размышляя над этим вопросом, большинство людей в первую очередь должны подумать об изменении заголовка в хуке жизненного цикла.
крючки жизненного цикла
Как правило, мыmountedЗапрос на инициализацию делается в хуке жизненного цикла, поэтому по инерционному мышлению я модифицировал заголовок в Mounted.
// 业务代码
mounted () {
document.title = this.$route.meta.title
}
В результате эффект не очень хороший, и заголовок вкладки задерживается более чем на 1 секунду, прежде чем будет успешно изменен. По этой задержке видно, что, очевидно, наш код выполняется слишком поздно!
Вспоминая детали кода, связанные с инициализацией в исходном коде Vue, мы можем обнаружить, что мы дажеbeforeCreateНазвание можно изменить в хуке.
Модифицированный код выглядит следующим образом:
// 业务代码
beforeCreate () {
document.title = this.$route.meta.title
}
Можно обнаружить, что эффект модифицированного кода, очевидно, намного лучше, и, хотя ощущение задержки все еще есть, оно уже не очевидно.
охранник маршрута
По сравнению с изменением значения заголовка в хуке жизненного цикла, разве не прекрасно использовать защиту маршрутизации для завершения изменения заголовка при скачке маршрута? В конце концов, переход маршрутизации происходит до выполнения функции жизненного цикла.Использование функции защиты маршрутизации для изменения значения заголовка может значительно сократить задержку модификации заголовка.
// router.js
router.beforeEach((to, from, next) => {
document.title = to.meta.title
next()
})
На данный момент мы в основном полностью выполнили функциональные требования, но все еще есть небольшой недостаток - если значение 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 для управления заголовком
vue-metaКогда плагин установлен, как и Vuex, он вводит глобальное состояние —metaInfo, вы можете определитьmetaInfoАтрибут title в объекте позволяет динамически модифицировать заголовок.
Пасхальное яйцо 2: анализ исходного кода vue-wechat-title
При поиске нужной информации,vue-wechat-titleЧастота этого пакета неожиданно высока.Этот пакет в основном решает проблему, упомянутую выше: он не может пройти через WeChat.document.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)
}
})()
Поскольку браузер WeChat доступен только вonloadЗаголовок инициализируется значением title в событии, и последующая модификация заголовка не может инициировать изменение заголовка. Поскольку событие onload может изменить заголовок через заголовок, я создаю пустой iframe и запускаю событие onload, чтобы изменить заголовок, а затем удалить его. Это изменяет заголовок на основе заголовка и не оказывает дополнительного влияния на страницу.
Как мы все знаем,vue-wechat-titleпройти черезv-wechat-titleинструкция для запуска динамической модификации заголовка, и каждый раз, когда значение инструкции изменяется, запускается функция обратного вызова в обработчике обновления ——setWechatTitle. Эта функция реализует упомянутую выше обработку совместимости,document.titleИзменения в заголовке.