基于vue.js&vue-router的动态更新TDK(
2018-08-01 本文已影响402人
SeasonDe
本文基于工作项目开发,做的整理笔记
前几天帮朋友解决这个问题,顺带学习了一下,做个笔记Mark下。
前提条件:
你已经了解并使用vue,能够搭建应用站点。
编码环境:
system:OS X EI Capitan 10.13.3
npm:5.5.1
node:v8.9.3
vue-cli:@lastest
相关技术栈:
vue2 + vue-router
基于vue.js&vue-router的动态更新TDK.jpg相关地址:
参考阅读:https://alligator.io/vuejs/vue-router-modify-head/
1.router部分
直接看代码,主要包含一个配置变量mapping
,也可以抽出去放到单独的配置文件中,这里就简化放进来了,容易看。在路由配置中,给了一个meta
字段用于存放对应的TDK信息。
注意:这里我们发现NewsDetail
暂存的TDK信息和News
一样,没关系,因为它和ID有关,在app.js
那边我们还要具体处理。
/**********************************************/
/* src/router/index.js */
/**********************************************/
import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/components/layout'
import Home from '@/components/home'
import News from '@/components/hot-news'
import Detail from '@/components/hot-news/detail'
import About from '@/components/info/about'
import ContactUs from '@/components/info/contact-us'
import JoinUs from '@/components/info/join-us'
import Terms from '@/components/info/terms'
import Error404 from '@/components/404'
Vue.use(Router)
const mapping = {
home: {
title: 'xxxxxxxxxxxxxxxx-【官网名称】',
metaTags: [
{
name: 'keywords',
content: 'xxx, xx, xxxxx, xxx, xxx'
},
{
name: 'description',
content: '官网页面的一段描述'
},
],
},
news: {
title: '【新闻热点】_xxxxxxx-官网名称',
metaTags: [
{
name: 'keywords',
content: 'xxx, xx, xxxxx, xxx, xxx'
},
{
name: 'description',
content: '新闻热点页面的一段描述'
},
],
},
}
export default new Router({
mode: 'history',
routes: [
{
path: '/',
component: Layout,
// redirect: '/home',
hidden: true,
children: [
{
path: '',
component: Home,
meta: mapping.home,
},
{
path: 'home',
redirect: '/',
component: Home,
meta: mapping.home,
},
{
path: 'news',
component: News,
meta: mapping.news,
},
{
path: 'news/:id',
component: NewsDetail,
meta: mapping.news,
},
{
path: 'about',
component: About,
meta: mapping.home,
},
{
path: 'contact-us',
component: ContactUs,
meta: mapping.home,
},
{
path: 'join-us',
component: JoinUs,
meta: mapping.home,
},
{
path: 'terms',
component: Terms,
meta: mapping.home,
},
{
path: '404',
component: Error404,
meta: mapping.home,
},
]
},
]
})
2. 看看app.js这边如何使用
这段代码中,也有一个配置变量mappingFull
,它主要服务于那种带查询条件的,带id的具体路由的TDK。另外注意的就是方法
/**********************************************/
/* src/app.js */
/**********************************************/
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import store from './store';
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import '@/style/base.scss'
Vue.use(ElementUI);
Vue.config.productionTip = false
const mappingFull = {
'/news?categary=xxxxx': {
title: '【新闻热点】_xxxxx-官网名称',
metaTags: [
{
name: 'keywords',
content: 'xxx, xx, xxxx, xxx, xxx'
},
{
name: 'description',
content: '这一搜索条件的相关描述'
},
],
},
'/news/1': {
title: '【xxxxx_新闻热点】_xxxxxx-官网名称',
metaTags: [
{
name: 'keywords',
content: 'xxx, xx, xxxx, xxx, xxx'
},
{
name: 'description',
content: '新闻热点1的相关描述'
},
],
},
'/news/2': {
title: '【xxxxx_新闻热点】_xxxxxx-官网名称',
metaTags: [
{
name: 'keywords',
content: 'xxx, xx, xxxx, xxx, xxx'
},
{
name: 'description',
content: '新闻热点2的相关描述'
},
],
},
'/hot-news/3': {
title: '【xxxxx_新闻热点】_xxxxxx-官网名称',
metaTags: [
{
name: 'keywords',
content: 'xxx, xx, xxxx, xxx, xxx'
},
{
name: 'description',
content: '新闻热点3的相关描述'
},
],
},
}
router.beforeEach((to, from, next) => {
const matchPath = to.matched.slice().reverse();
const meta = mappingFull[to.fullPath];
// console.log(to.fullPath); // 可以打印输出看看
// console.log(meta);
let nearestWithTitle = undefined;
let nearestWithMeta = undefined;
if (meta) {
nearestWithTitle = { meta };
nearestWithMeta = { meta };
} else {
nearestWithTitle = matchPath.find(r => r.meta && r.meta.title);
nearestWithMeta = matchPath.find(r => r.meta && r.meta.metaTags);
}
if(nearestWithTitle) document.title = nearestWithTitle.meta.title;
Array.from(document.querySelectorAll('[data-vue-router-controlled]')).map(el => el.parentNode.removeChild(el));
if(!nearestWithMeta) return next();
nearestWithMeta.meta.metaTags.map(tagDef => {
const tag = document.createElement('meta');
Object.keys(tagDef).forEach(key => {
tag.setAttribute(key, tagDef[key]);
});
tag.setAttribute('data-vue-router-controlled', '');
return tag;
})
.forEach(tag => document.head.appendChild(tag));
if (to.need && to.need.requireAuth) {
if (store.getters.token) {
next();
}
else {
next('/home');
// next({
// path: '/login',
// query: {redirect: to.fullPath} // 将跳转的路由path作为参数,登录成功后跳转到该路由
// });
}
}
else {
next();
}
});
router.afterEach((to,from,next) => {
window.scrollTo(0,0);
})
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app');
3. 疑问
我们大多都知道SEO优化有很多方式,更可行的可能是SSR后端渲染,但是毕竟有时候我们就是前端渲染实现某个官网,只能找找其他简单可行办法。文中这种做法实际上只有真是访问的时候才可以拿到真正准确的TDK,各搜索引擎的爬虫拿到的是静态文件index.html的代码view-source,那个时候TDK还没有被替换,不知道这种做法是否真的有利于SEO。有待验证。
欢迎留言提出此类问题的优化,互相学习。
学习是一条漫漫长路,每天不求一大步,进步一点点就是好的。