前提
想想这个项目我就头疼,因为但是在开会的时候说的很简单,预计也就一个月就可以做好了,结果就设计稿都花了一个多月才确定下来,然后就是加班加点做好,因为有几个界面是需要做SEO,所以就使用预渲染(prerender-spa-plugin和vue-meta-info)来做SEO,然后就开开心心的测试上线了。
隔天上班
产品说:
- •在后台修改SEO后为什么在检查源代码的时候还是之前的SEO?
- •而且其他界面为什么没有SEO?
- •不能动态的吗?
- •(我真是栓Q了)
于是乎,就带着这些疑问在我的脑海里找对应的解决方案(脑海里找对应的解决方案===想中午吃啥,vue官网+百度找解决方案)。首先,vue官网是有SSR介绍和说明的(传送门:服务端渲染(SSR))
图一
图二
在图一可以看到,我们可以使用createSSRApp()。但是在图二
可以发现有几种解决方案
- •ViteSSR:由于项目是使用Vue-cli创建的,所以就不考虑了
- •Quasar:可以看到它提供了很多功能,它可以让你用同一套代码库构建不同目标的应用,关键是它还提供了一整套MaterialDesign风格的组件库,但我们就简单弄个SEO,用它就不划算了
- •Nuxt:从图片中可以看到圈起来的那一部分,没错,vue官方推荐使用的,又由于前端几种方案都不考虑,总不能都不考虑吧
- •它们之间的区别可自行去了解一下
既然已经有现成的方案了,那咱们就去看看嘛~
- •因为我是那个有现成的就不自己写,当然了,像这种级别框架的不是我现在这种级别能写的
- •比如项目中有几个界面是需要全屏滚动的,然后我就使用了Swiper来做,结果在测试的时候,移动端和电脑触摸板滚动的时,有时候出现划一下滚好几屏的情况,我这暴脾气能忍它?直接卸载自己封装一个,完美解决!!!
有请本期主角:Nuxt.js
先上图
果然,vue官方推荐的就是不一样,主题色都差不多【手动狗头】
目录结构
- •nuxt文件夹:(nuxt.jsbuildoutput)nuxt自动生成的,临时的用于编辑的文件。
- •assets文件夹:存放未编译的静态资源譬如less,sass或javascript。
- •components:放置vue组件,这些组件不会像页面组件那样有asyncData方法的特性。
- •layouts:组织应用的布局组件。
- •middleware:放置应用所需的中间件(中间件允许定义一个自定义函数运行在一个页面或一组页面渲染之前)。
- •pages:用于组织应用的路由及视图。Nuxt.js框架读取该目录下所有的.vue文件并自动生成对应的路由配置。
- •plugins:组织那些需要在vue.js应用实例化之前需要运行的Javascript插件。
- •static:存放应用的静态资源文件,该目录下的文件不会被webpack编译处理。
- •store:管理vuex状态。
- •.env:(这个文件不是必须的)设置环境变量的参数,可以通过process.env.参数名进行获取。
- •.gitignore:设置不需要提交到git上面的文件。
- •nuxt.config.js:用于组织Nuxt.js应用的个性化配置,以便覆盖默认配置。
- •package.json:npm包管理的配置文件。
- •pageage.lock.json:指定npm包的具体版本,以达到统一。
nuxt的路由:
- •路由管理:可以使用
<Nuxt/>
或<router-view/>
- •路由组件:nuxt推荐使用
<nuxt-link></nuxt-link>
其参数和<router-link></router-link>
一致
nuxt路由生成规则
Nuxt.js依据pages目录结构在_nuxt
隐藏文件夹中自动生成vue-router模块的路由配置。
目录
pages/ --| user/ -----| index.vue -----| one.vue --| index.vue
自动生成_nuxt/router.js
router: { routes: [ { name: 'index', path: '/', component: 'pages/index.vue' }, { name: 'user', path: '/user', component: 'pages/user/index.vue' }, { name: 'user-one', path: '/user/one', component: 'pages/user/one.vue' } ] }
动态路由:文件名需要以下划线开头
目录:
pages/ --| _slug/ -----| comments.vue -----| index.vue --| _users/ -----| _id.vue --| index.vue
自动生成_nuxt/router.js
router: { routes: [ { name: 'index', path: '/', component: 'pages/index.vue' }, { name: 'users-id', path: '/:users/:id?', component: 'pages/users/_id.vue' }, { name: 'slug', path: '/:slug', component: 'pages/_slug/index.vue' }, { name: 'slug-comments', path: '/:slug/comments', component: 'pages/_slug/comments.vue' } ] }
更多详情可官网查看(点不了可底部查看链接)
Tips:创建nuxt项目后如果看不见_nuxt文件夹,应该电脑设置了不显示隐藏文件,可访问此链接显示隐藏文件怎么把电脑隐藏文件显示出来?点击不了可底部查看链接
项目创建与迁移
项目迁移/重构需对项目熟悉,由于公司项目都是我一人负责,所以迁移/重构应该没啥问题(只是应该【手动狗头】)
创建nuxt项目
// nuxt-ssr 为项目名,自定义 npx create-nuxt-app nuxt-ssr
创建过程中和VueCLI差不多。
创建项目参考文章(点击不了可底部查看链接)
初始目录结构
VueCLI已完成项目目录结构对比nuxt目录结构
由于上面已经介绍了nuxt目录作用,接下来直接迁移
第一步:将src/views下面的页面文件移到pages目录下
第二步:将src/components下面的组件移到components目录下
第三步:如果原项目图片不在static中就将图片文件移到static目录下,公共JS和CSS或第三方需要编译的文件放到assets目录下
然后在根目录下的nuxt.config.js
文件中引入公共的JS/CSS
export default { css: [ <span data-raw-text="" "="" data-textnode-index-1656827066221="314" data-index-1656827066221="3064" class="character" style="margin: 0px; padding: 0px;">"element-ui/lib/theme-chalk/index.css<span data-raw-text="" "="" data-textnode-index-1656827066221="314" data-index-1656827066221="3101" class="character" style="margin: 0px; padding: 0px;">", <span data-raw-text="" "="" data-textnode-index-1656827066221="317" data-index-1656827066221="3107" class="character" style="margin: 0px; padding: 0px;">"~/assets/scss/global.scss<span data-raw-text="" "="" data-textnode-index-1656827066221="317" data-index-1656827066221="3133" class="character" style="margin: 0px; padding: 0px;">", ] }
第四步:将src/下面的其他文件移到nuxt根目录下
第五步:路由修改,由于我们已经有路由文件了,所以需要自定义路由,不需要nuxt根据pages目录自动创建路由,
首先,将src/router下面的index.js移到nuxt根目录下并改名为router.js
然后安装@/nuxt/router
npm i @nuxtjs/router
然后在根目录下的nuxt.config.js
文件中引入@nuxtjs/router
export default { modules: [ <span data-raw-text="" "="" data-textnode-index-1656827066221="344" data-index-1656827066221="3391" class="character" style="margin: 0px; padding: 0px;">"@nuxtjs/router<span data-raw-text="" "="" data-textnode-index-1656827066221="344" data-index-1656827066221="3406" class="character" style="margin: 0px; padding: 0px;">", ], }
因为nuxtjs需要返回一个路由实例,所以需要修改原来路由模式。
修改前:
const router = new VueRouter({ mode: <span data-raw-text="" "="" data-textnode-index-1656827066221="359" data-index-1656827066221="3491" class="character" style="margin: 0px; padding: 0px;">"history<span data-raw-text="" "="" data-textnode-index-1656827066221="359" data-index-1656827066221="3499" class="character" style="margin: 0px; padding: 0px;">", routes, }); router.beforeEach((to, form, next) => { // do somming }); export default router;
修改后:
export function createRouter() { const router = new VueRouter({ mode: <span data-raw-text="" "="" data-textnode-index-1656827066221="390" data-index-1656827066221="3670" class="character" style="margin: 0px; padding: 0px;">"history<span data-raw-text="" "="" data-textnode-index-1656827066221="390" data-index-1656827066221="3678" class="character" style="margin: 0px; padding: 0px;">", routes, }); router.beforeEach((to, form, next) => { if (to.query.nav_id) { getPrevNav(to.query.nav_id); } // console.log(mutations); next(); process.client && window.scrollTo(0, 0); }); return router; }
当你配置完这些之后,路由就可以跳转了,但是如果路由中使用到了懒加载可能会报错:Failedtomountcomponent:templateorrenderfunctionnotdefined
这是因为nuxt的路由规则不一样,解决方案:
// 懒加载修改成这样即可 path: <span data-raw-text="" "="" data-textnode-index-1656827066221="431" data-index-1656827066221="4058" class="character" style="margin: 0px; padding: 0px;">"/about<span data-raw-text="" "="" data-textnode-index-1656827066221="431" data-index-1656827066221="4065" class="character" style="margin: 0px; padding: 0px;">", name: <span data-raw-text="" "="" data-textnode-index-1656827066221="436" data-index-1656827066221="4075" class="character" style="margin: 0px; padding: 0px;">"About<span data-raw-text="" "="" data-textnode-index-1656827066221="436" data-index-1656827066221="4081" class="character" style="margin: 0px; padding: 0px;">", component: () => import(<span data-raw-text="" "="" data-textnode-index-1656827066221="444" data-index-1656827066221="4112" class="character" style="margin: 0px; padding: 0px;">"~/pages/about/index.vue<span data-raw-text="" "="" data-textnode-index-1656827066221="444" data-index-1656827066221="4136" class="character" style="margin: 0px; padding: 0px;">").then((com) => com.default || com), },
.then((com)=>com.default||com)
这个格式是固定的,里面的com
是可自定义参数,也可以叫res
等,例如:.then((res)=>res.default||res)
Tips:
nuxt.config.js
中还有许多配置,可前往官网查看(底部链接)
第六步:使用@nuxtjs/axios
替换node_modules/axios
// 安装:@nuxtjs/axios 和 @nuxtjs/proxy npm i @nuxtjs/axios @nuxtjs/proxy
然后在根目录下的nuxt.config.js
文件中引入@nuxtjs/axios
export default { modules: [ <span data-raw-text="" "="" data-textnode-index-1656827066221="476" data-index-1656827066221="4508" class="character" style="margin: 0px; padding: 0px;">"@nuxtjs/router<span data-raw-text="" "="" data-textnode-index-1656827066221="476" data-index-1656827066221="4523" class="character" style="margin: 0px; padding: 0px;">", <span data-raw-text="" "="" data-textnode-index-1656827066221="479" data-index-1656827066221="4531" class="character" style="margin: 0px; padding: 0px;">"@nuxtjs/axios<span data-raw-text="" "="" data-textnode-index-1656827066221="479" data-index-1656827066221="4545" class="character" style="margin: 0px; padding: 0px;">", <span data-raw-text="" "="" data-textnode-index-1656827066221="482" data-index-1656827066221="4553" class="character" style="margin: 0px; padding: 0px;">"@nuxtjs/proxy<span data-raw-text="" "="" data-textnode-index-1656827066221="482" data-index-1656827066221="4567" class="character" style="margin: 0px; padding: 0px;">", ], // 配置代理 proxy: { <span data-raw-text="" "="" data-textnode-index-1656827066221="491" data-index-1656827066221="4598" class="character" style="margin: 0px; padding: 0px;">"/api<span data-raw-text="" "="" data-textnode-index-1656827066221="491" data-index-1656827066221="4603" class="character" style="margin: 0px; padding: 0px;">": { target: 'http:xxx.xxxx', changeOrigin: true, }, }, }
@nuxtjs/axios拦截器
1、打开根目录下的plugins
文件夹,创建一个js
文件,名字随意,例如:axios.js
export default function ({ $axios }) { // 请求拦截器 $axios.onRequest((config) => { (config) => { return config; }, }); // 响应拦截器 $axios.onResponse((res) => { return res; }); // 请求失败(服务器报错),做一些事情 $axios.onError((err) => { return Promise.reject(err); }); }
然后需要在根目录下的nuxt.config.js
文件中引入axios.js
export default { plugins: [ // 方式一:服务端客户端都用 <span data-raw-text="" "="" data-textnode-index-1656827066221="569" data-index-1656827066221="5113" class="character" style="margin: 0px; padding: 0px;">"~/plugins/axios<span data-raw-text="" "="" data-textnode-index-1656827066221="569" data-index-1656827066221="5129" class="character" style="margin: 0px; padding: 0px;">", // 方式二:仅在客户端使用,不需要 SSR { src: <span data-raw-text="" "="" data-textnode-index-1656827066221="576" data-index-1656827066221="5169" class="character" style="margin: 0px; padding: 0px;">"~/plugins/axios<span data-raw-text="" "="" data-textnode-index-1656827066221="576" data-index-1656827066221="5185" class="character" style="margin: 0px; padding: 0px;">", mode: <span data-raw-text="" "="" data-textnode-index-1656827066221="580" data-index-1656827066221="5194" class="character" style="margin: 0px; padding: 0px;">"client<span data-raw-text="" "="" data-textnode-index-1656827066221="580" data-index-1656827066221="5201" class="character" style="margin: 0px; padding: 0px;">" }, // 方式三:仅在客户端使用,不需要 SSR,和方式二一样 { src: <span data-raw-text="" "="" data-textnode-index-1656827066221="587" data-index-1656827066221="5250" class="character" style="margin: 0px; padding: 0px;">"~/plugins/axios<span data-raw-text="" "="" data-textnode-index-1656827066221="587" data-index-1656827066221="5266" class="character" style="margin: 0px; padding: 0px;">", ssr: false }, ] }
Tips:项目中用到的字符
~
或者@
默认情况下都是表示项目根目录,具体的可官方查看详情,例如:自定义项目根目录等
@nuxtjs/axios的使用
做完上面几步之后,组件内部this
上就会有$axios
这个属性,可直接调用请求接口,用法可参考@nuxtjs/axios
官网和axios
官网
methods:{ async getArticleList() { const res = await this.$axios.$get('http://xxx.xxx.xxx/list') console.log(res) } }
VuexStore
如果项目中使用到Vuex,也需要进行改造
迁移前:
import Vue from <span data-raw-text="" "="" data-textnode-index-1656827066221="643" data-index-1656827066221="5618" class="character" style="margin: 0px; padding: 0px;">"vue<span data-raw-text="" "="" data-textnode-index-1656827066221="643" data-index-1656827066221="5622" class="character" style="margin: 0px; padding: 0px;">"; import Vuex from <span data-raw-text="" "="" data-textnode-index-1656827066221="651" data-index-1656827066221="5641" class="character" style="margin: 0px; padding: 0px;">"vuex<span data-raw-text="" "="" data-textnode-index-1656827066221="651" data-index-1656827066221="5646" class="character" style="margin: 0px; padding: 0px;">"; import Index from <span data-raw-text="" "="" data-textnode-index-1656827066221="659" data-index-1656827066221="5666" class="character" style="margin: 0px; padding: 0px;">"./modules/index<span data-raw-text="" "="" data-textnode-index-1656827066221="659" data-index-1656827066221="5682" class="character" style="margin: 0px; padding: 0px;">"; Vue.use(Vuex); export default new Vuex.Store({ state: {}, mutations: {}, actions: {}, modules: { Index, }, });
迁移后:方式一(nuxt官方不推荐)
import Vue from <span data-raw-text="" "="" data-textnode-index-1656827066221="701" data-index-1656827066221="5834" class="character" style="margin: 0px; padding: 0px;">"vue<span data-raw-text="" "="" data-textnode-index-1656827066221="701" data-index-1656827066221="5838" class="character" style="margin: 0px; padding: 0px;">"; import Vuex from <span data-raw-text="" "="" data-textnode-index-1656827066221="709" data-index-1656827066221="5857" class="character" style="margin: 0px; padding: 0px;">"vuex<span data-raw-text="" "="" data-textnode-index-1656827066221="709" data-index-1656827066221="5862" class="character" style="margin: 0px; padding: 0px;">"; import home from <span data-raw-text="" "="" data-textnode-index-1656827066221="715" data-index-1656827066221="5881" class="character" style="margin: 0px; padding: 0px;">"./modules/home<span data-raw-text="" "="" data-textnode-index-1656827066221="715" data-index-1656827066221="5896" class="character" style="margin: 0px; padding: 0px;">"; Vue.use(Vuex); const store = () => { return new Vuex.Store({ state: {}, mutations: {}, actions: {}, modules: { Index, }, }); } // 因为函数里面就一条返回值,所以也可以写成下面这样 // const store = () => new Vuex.Store({ // state: {}, // mutations: {}, // actions: {}, // modules: { // Index, // }, // }); export default store
方式二(nuxt官方推荐)
import Vue from <span data-raw-text="" "="" data-textnode-index-1656827066221="774" data-index-1656827066221="6239" class="character" style="margin: 0px; padding: 0px;">"vue<span data-raw-text="" "="" data-textnode-index-1656827066221="774" data-index-1656827066221="6243" class="character" style="margin: 0px; padding: 0px;">"; import Vuex from <span data-raw-text="" "="" data-textnode-index-1656827066221="782" data-index-1656827066221="6262" class="character" style="margin: 0px; padding: 0px;">"vuex<span data-raw-text="" "="" data-textnode-index-1656827066221="782" data-index-1656827066221="6267" class="character" style="margin: 0px; padding: 0px;">"; // 在 modules 文件中新建一个index.js文件,将 模块导入进去 //再导出为一个变量,防止影响 store/index.js 可读性 import modulesGroup from <span data-raw-text="" "="" data-textnode-index-1656827066221="790" data-index-1656827066221="6367" class="character" style="margin: 0px; padding: 0px;">"./modules/index<span data-raw-text="" "="" data-textnode-index-1656827066221="790" data-index-1656827066221="6383" class="character" style="margin: 0px; padding: 0px;">"; Vue.use(Vuex); // state export const state = () => ({}); // mutations export const mutations = {}; // actions export const actions = {}; // modules export const modules = { modules: modulesGroup, }; // 不需要使用 export default 全部导出,因为 nuxt 会自动生成和 vuex 一样的结构
@nuxtjs/axios在vuex中使用
如果项目api
是使用Vuex的actions
,需要进行改造一下,nuxt已经内置vuex,所以无需安装
迁移前:
// API 文件夹下的home.js // 自己封装的 http 请求 import http from <span data-raw-text="" "="" data-textnode-index-1656827066221="838" data-index-1656827066221="6759" class="character" style="margin: 0px; padding: 0px;">"@/lib/http<span data-raw-text="" "="" data-textnode-index-1656827066221="838" data-index-1656827066221="6770" class="character" style="margin: 0px; padding: 0px;">"; const LISTURL = <span data-raw-text="" "="" data-textnode-index-1656827066221="844" data-index-1656827066221="6788" class="character" style="margin: 0px; padding: 0px;">"/getList<span data-raw-text="" "="" data-textnode-index-1656827066221="844" data-index-1656827066221="6797" class="character" style="margin: 0px; padding: 0px;">"; const API = { getArticleList({ dispatch }, data) { return new Promise((resolve, reject) => { http .post(LISTURL, data) .then((res) => { resolve(res); }) .catch((error) => { // 错误收集 // dispatch('ERROR', error) reject(error); }); }); }, export default API; // 在 store/modules/home.js 文件中引入定义好的api,并导出 import Actions from <span data-raw-text="" "="" data-textnode-index-1656827066221="899" data-index-1656827066221="7198" class="character" style="margin: 0px; padding: 0px;">"@/api/home<span data-raw-text="" "="" data-textnode-index-1656827066221="899" data-index-1656827066221="7209" class="character" style="margin: 0px; padding: 0px;">"; export default { namespaced: true, state: {}, getters: {}, mutations: {}, actions: { ...Actions, }, };
迁移后:
API文件夹下的home.js文件修改:移除
自己封装的http请求,将http.post
改为this.$axios.post
注意:这里的this是可以拿到this.$axios的
const LISTURL = <span data-raw-text="" "="" data-textnode-index-1656827066221="939" data-index-1656827066221="7442" class="character" style="margin: 0px; padding: 0px;">"/getList<span data-raw-text="" "="" data-textnode-index-1656827066221="939" data-index-1656827066221="7451" class="character" style="margin: 0px; padding: 0px;">"; const API = { getArticleList({ dispatch }, data) { return new Promise((resolve, reject) => { this.$axios .$post(LISTURL, data) .then((res) => { resolve(res); }) .catch((error) => { // 错误收集 // dispatch('ERROR', error) reject(error); }); }); }, export default API;
store/modules/home.js文件修改:
// 在 store/modules/home 文件中引入定义好的api,并导出 import Actions from <span data-raw-text="" "="" data-textnode-index-1656827066221="995" data-index-1656827066221="7884" class="character" style="margin: 0px; padding: 0px;">"@/api/index<span data-raw-text="" "="" data-textnode-index-1656827066221="995" data-index-1656827066221="7896" class="character" style="margin: 0px; padding: 0px;">"; // actions const actions = { ...Actions, }; export default { namespaced: true, actions, };
使用:
// index.vue import { mapActions } from <span data-raw-text="" "="" data-textnode-index-1656827066221="1021" data-index-1656827066221="8029" class="character" style="margin: 0px; padding: 0px;">"vuex<span data-raw-text="" "="" data-textnode-index-1656827066221="1021" data-index-1656827066221="8034" class="character" style="margin: 0px; padding: 0px;">"; created(){ this.getArticleList() }, methods: { ...mapActions(<span data-raw-text="" "="" data-textnode-index-1656827066221="1036" data-index-1656827066221="8097" class="character" style="margin: 0px; padding: 0px;">"modules/home<span data-raw-text="" "="" data-textnode-index-1656827066221="1036" data-index-1656827066221="8110" class="character" style="margin: 0px; padding: 0px;">", [<span data-raw-text="" "="" data-textnode-index-1656827066221="1038" data-index-1656827066221="8114" class="character" style="margin: 0px; padding: 0px;">"getArticleList<span data-raw-text="" "="" data-textnode-index-1656827066221="1038" data-index-1656827066221="8129" class="character" style="margin: 0px; padding: 0px;">"]), }
注意:
这里和Vuex有点不同,就是我们vuex在modules开启命名空间之后,使用辅助函数可以直接这样写
...mapActions(<span data-raw-text="" "="" data-textnode-index-1656827066221="1046" data-index-1656827066221="8201" class="character" style="margin: 0px; padding: 0px;">"home<span data-raw-text="" "="" data-textnode-index-1656827066221="1046" data-index-1656827066221="8206" class="character" style="margin: 0px; padding: 0px;">", [<span data-raw-text="" "="" data-textnode-index-1656827066221="1048" data-index-1656827066221="8210" class="character" style="margin: 0px; padding: 0px;">"getArticleList<span data-raw-text="" "="" data-textnode-index-1656827066221="1048" data-index-1656827066221="8225" class="character" style="margin: 0px; padding: 0px;">"]),
而在nuxt中需要多加一个modules
mapActions(<span data-raw-text="" "="" data-textnode-index-1656827066221="1053" data-index-1656827066221="8262" class="character" style="margin: 0px; padding: 0px;">"modules/home<span data-raw-text="" "="" data-textnode-index-1656827066221="1053" data-index-1656827066221="8275" class="character" style="margin: 0px; padding: 0px;">", [<span data-raw-text="" "="" data-textnode-index-1656827066221="1055" data-index-1656827066221="8279" class="character" style="margin: 0px; padding: 0px;">"getArticleList<span data-raw-text="" "="" data-textnode-index-1656827066221="1055" data-index-1656827066221="8294" class="character" style="margin: 0px; padding: 0px;">"]),
设置SSR
首先nuxt有一个head属性和vue的data同级,所以先写上
第一步:
export defaul { data() { return { desc_seo_content: '描述', keywords_seo_content: '关键词', list:[] } } head() { return { title: this.title, meta: [ { hid: 'description', name: 'description', content: this.desc_seo_content }, { hid: 'keywords', name: 'keywords', content: this.keywords_seo_content } ] } } }
第二步:也是重要的一步使用nuxt的内置函数asyncData
与created
同级
注意:
由于asyncData方法是在组件初始化前被调用的,所以在方法内是没有办法通过this来引用组件的实例对象。所以我们应该将获取需要SEO的接口放到asyncData中去执行就可以了
// 由于无法使用 this,所以 vuex 的辅助函数导出来的函数不能使用 // 但是 asyncData 会有一个 store 参数,所以我们可以直接使用 store.dispatch 来调用 actions async asyncData({app, store, route, params, query, env, isDev,isHMR, redirect, error}) { // asyncData 有 10 个参数供我们使用 try{ // 因为我们的 SEO 依赖于 data 中的属性,所以需要定义和 data 一样的属性并 return 出去 let list = [], desc_seo_content, keywords_seo_content const res = await store.dispatch(<span data-raw-text="" "="" data-textnode-index-1656827066221="1165" data-index-1656827066221="9349" class="character" style="margin: 0px; padding: 0px;">"modules/home/getArticleList<span data-raw-text="" "="" data-textnode-index-1656827066221="1165" data-index-1656827066221="9377" class="character" style="margin: 0px; padding: 0px;">"); list = res.data desc_seo_content = res.desc_seo_content keywords_seo_content = res.keywords_seo_content return {list,desc_seo_content,keywords_seo_content} }catch(err) { console.log(err) } }
当我们做完这些之后,在右键检查源代码时就能看到SEO了,而且通过v-for=“iteminlist”
出来的li标签也能全部展示在网页上了,百度蜘蛛就能爬取到。
注意:
为了避免子组件中的meta标签不能正确覆盖父组件中相同的标签而产生重复的现象,建议利用hid键为meta标签配一个唯一的标识编号,更多vue-meta
遇到的问题
Window或Document未定义
由于在服务端没有Window或Document所以需要添加判断process.client
// 项目里封装的全屏滚动组件 mounted() { if (process.client) { let scrollObj = document.querySelector(<span data-raw-text="" "="" data-textnode-index-1656827066221="1206" data-index-1656827066221="9926" class="character" style="margin: 0px; padding: 0px;">"#my-swiper-contanier<span data-raw-text="" "="" data-textnode-index-1656827066221="1206" data-index-1656827066221="9947" class="character" style="margin: 0px; padding: 0px;">"); } }
如果使用到的第三方插件里面有Window或Document
就先在plugins文件中创建一个和插件一样的名字然后导入插件再在nuxt.config.js
中配置(这样会全局引入)
plugins: [ { src: <span data-raw-text="" "="" data-textnode-index-1656827066221="1221" data-index-1656827066221="10075" class="character" style="margin: 0px; padding: 0px;">"~/plugins/viewer<span data-raw-text="" "="" data-textnode-index-1656827066221="1221" data-index-1656827066221="10092" class="character" style="margin: 0px; padding: 0px;">", ssr: false } ],
还有几个问题忘记了
链接
链接
prerender-spa-plugin:https://www.npmjs.com/package/prerender-spa-plugin
vue-meta-info:https://www.npmjs.com/package/vue-meta-info
vue-router:https://router.vuejs.org/zh/
显示隐藏文件:https://jingyan.baidu.com/article/636f38bb5d49e797b84610a1.html
Nuxt.js:https://www.nuxtjs.cn/
axios:http://www.axios-js.com/
vue-meta:https://vue-meta.nuxtjs.org/api/#tagidkeyname
Nuxt部署:https://blog.csdn.net/weixin_40287511/article/details/123123802
好了,以上就是本期内容了