简介
1、服务渲染
服务端渲染技术NUXT,即数据的操作过程在服务端实现,客户端只负责做显示,利于 SEO
服务端渲染又称 SSR (Server Side Render)是在服务端完成页面的内容,而不是在客户端通过AJAX获取数据。即原来是客户端发送 ajax请求,然后服务端得到数据,返回并做渲染,即异步,但异步不利于做 SEO,当爬虫抓取的时候,抓取工具并不会等待异步完成后再进行页面内容的抓取,又因为是异步,所以内容可能还没有渲染成功,会造成网站排名靠后。
服务器端渲染(SSR)的优势主要在于:更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
2、nuxt
Nuxt.js 是一个基于 Vue.js的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性
3、下载使用
3.1、下载
https://github.com/nuxt-community/starter-template/archive/master.zip
3.2、使用
-
解压出来,然后在前端项目文件夹下面新建文件夹,然后将压缩后的 template文件夹下的所有内容放进新建的文件夹
-
打开项目,找到这个文件夹下的 package.json文件,修改 name、description、author
-
找到 nuxt.config.js,修改 title、meta->content
-
右键该 nuxt项目->在集成终端中打开,输入 npm install
-
再下载一个 element-ui, npm install element-ui
-
在 plugins文件夹下创建 myPlugin.js文件,并加入内容,用于引用 element-ui
import Vue from 'vue' //element-ui的全部组件 import ElementUI from 'element-ui' //element-ui的css import 'element-ui/lib/theme-chalk/index.css' //使用elementUI Vue.use(ElementUI)
-
在 nuxt.config.js的 build{}的下面加入内容
plugins: [ { src: '~/plugins/myPlugin.js', ssr: false } ]
-
测试运行,npm run dev,访问项目:http://localhost:3000/
4、nuxt的目录结构
-
.nuxt:相关的编译后文件
-
assets:放一些静态资源,比如:css、js、图片
-
components:vue支持的相关组件
-
middleware、static、store:放相关的静态资源
-
plugins:放依赖的插件
4.1、layouts
页面布局,比如上部固定样式,下部固定样式等,中间的内容引用 pages的页面
4.2、pages
页面内容
5、封装 axios
-
下载 axios,npm install axios
-
在 nuxt项目下新建文件夹 utils
-
在 utils中新建文件 request.js,并加入内容
import axios from 'axios' import { MessageBox, Message } from 'element-ui' // 创建axios实例 const service = axios.create({ baseURL: 'http://localhost', timeout: 15000 // 请求超时时间 }) // http request 拦截器 service.interceptors.request.use( config => { // token 先不处理,后续使用时在完善 return config }, err => { return Promise.reject(err) }) // http response 拦截器 service.interceptors.response.use( response => { if (response.data.code !== 200) { Message({ message: response.data.message, type: 'error', duration: 5 * 1000 }) return Promise.reject(response.data) } else { return response.data } }, error => { return Promise.reject(error.response) }) export default service
nuxt技术点
1、nuxt的路由跳转
nuxt有两种路由跳转方式:固定路由、动态路由
1.1、固定路由
是什么路径,就跳转到什么页面,即路径对应固定的页面,
会默认寻找 pages文件夹下的对应文件夹的默认文件(index.vue)
//找到 pages/hospital/index.vue页面 window.location.href = '/hospital'
1.2、动态路由
在路径中添加参数,不同的参数会显示不同的内容
会寻找 pages文件夹下对应文件夹的 参数名称.vue,即有一个命名规范:参数名称.vue
动态路由相当于 vue那样的 router/index.js的情况,但 nuxt中没有 router/index.js,所以可用动态路由来路径传参
//找到 pages/hospital/_hoscode.vue页面 window.location.href = '/hospital/' + hoscode
2、监听全局事件
页面 B想调用页面 A的方法
2.1、A引入 Vue
import Vue from 'vue'
2.2、A添加 mounted方法
即页面渲染之后执行的方法
mounted() { // 注册全局登录事件对象 window.loginEvent = new Vue(); // 监听登录事件 loginEvent.$on('loginDialogEvent', function () { document.getElementById("loginDialog").click(); }) }
2.3、B添加 js-cookie
import cookie from 'js-cookie'
2.4、B调用方法
schedule(depcode) { // 登录判断 let token = cookie.get('token') if (!token) { loginEvent.$emit('loginDialogEvent') return } window.location.href = '/hospital/schedule?hoscode=' + this.hospital.hoscode + "&depcode="+ depcode },
简单使用
1、实例1
1.1、实现首页
1.1.1、添加静态资源
将 css、images放入 assets文件夹下
1.1.2、修改 layouts/default.vue
<template> <div class="app-container"> <div id="main"> <!-- 公共头 --> <myheader /> <div class="main-container"> <el-scrollbar class="page-component__scroll"> <!-- 内容区域 --> <nuxt /> </el-scrollbar> </div> <!-- 公共底 --> <myfooter /> </div> </div> </template> <script> import "~/assets/css/app.css" import "~/assets/css/chunk.css" import "~/assets/css/iconfont.css" import "~/assets/css/main.css" export default {} </script>
1.1.3、提取头文件
创建 layouts/myheader.vue文件
<template> <div class="header-container"> <div class="wrapper"> <!-- logo --> <div class="left-wrapper v-link selected"> <img style="width: 50px" width="50" height="50" src="~assets/images/logo.png"> <span class="text">互联网医院平台</span> </div> <!-- 搜索框 --> <div class="search-wrapper"> <div class="hospital-search animation-show"> <el-autocomplete class="search-input small" prefix-icon="el-icon-search" v-model="state" :fetch-suggestions="querySearchAsync" placeholder="点击输入医院名称" @select="handleSelect"> <span slot="suffix" class="search-btn v-link highlight clickable selected">搜索 </span> </el-autocomplete> </div> </div> <!-- 右侧 --> <div class="right-wrapper"> <span class="v-link clickable">帮助中心</span> <!-- <el-dropdown >--> <!-- <span class="el-dropdown-link">--> <!-- 晴天<i class="el-icon-arrow-down el-icon--right"></i>--> <!-- </span>--> <!-- <el-dropdown-menu class="user-name-wrapper" slot="dropdown">--> <!-- <el-dropdown-item>挂号订单</el-dropdown-item>--> <!-- <el-dropdown-item>就诊人管理</el-dropdown-item>--> <!-- <el-dropdown-item divided>退出登录</el-dropdown-item>--> <!-- </el-dropdown-menu>--> <!-- </el-dropdown>--> <span class="v-link clickable" @click="dialogUserFormVisible = true">登录/注册</span> </div> </div> </div> </template> <script> export default {} </script>
1.1.4、提取尾文件
创建 layouts/myfooter.vue文件
<template> <div class="footer-container"> <div class="wrapper"> <div> <span class="record">京ICP备13018369号</span> <span class="phone">电话挂号010-56253825</span> </div> <div class="right"> <span class="v-link clickable"> 联系我们 </span> <span class="v-link clickable"> 合作伙伴 </span> <span class="v-link clickable"> 用户协议 </span> <span class="v-link clickable"> 隐私协议 </span> </div> </div> </div> </template> <script> export default {} </script>
1.1.5、默认布局引入头尾文件
修改 layouts/default.vue文件,将两个页面作为组件引入进去,使得页面中可用标签进行使用
<script> import "~/assets/css/app.css" import "~/assets/css/chunk.css" import "~/assets/css/iconfont.css" import "~/assets/css/main.css" import myheader from './myheader' import myfooter from './myfooter' export default { components: { myheader,myfooter } } </script>
1.1.6、修改首页
修改 pages/inde.vue文件,然后重启即可
1.2、开发过程
1.2.1、创建 api文件
创建 js文件,用于引用对应 controller的接口方法
import request from '@/utils/request' const api_name = `/admin/cmn/dict` export default { //根据 dictCode获取子节点 findByDictCode(dictCode){ return request({ url: `${api_name}/findByDictCode/${dictCode}`, method: 'get' }) }, }
1.2.2、修改 index.vue
在里面定义方法和组件,最后进行首页展示,主要是服务端的异步渲染
export default { //服务端渲染异步,显示医院列表 //很多代码做了封装,不需要去 data中定义数据,可直接在 return 中定义 //params用于得到路径中的数据,error用于得到异常信息 asyncData({ params, error }) { //调用 return hospital.findByConditionWithPage(1,10,null) .then(response => { return { hospitalList: response.data.content, totalPages: response.data.totalPages } }) }, }