赞
踩
服务端渲染又称SSR (Server Side Render)是在服务端完成页面的内容,而不是在客户端通过AJAX获取数据。
服务器端渲染优势主要在于:更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
使用服务器端渲染,可以获得更快的内容到达时间,无需等待所有的 JavaScript 都完成下载并执行,产生更好的用户体验。
Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。
Nuxt.js 预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置,为客户端/服务端 这种典型的应用架构模式提供了许多有用的特性,例如异步数据加载、中间件支持、布局支持等。
官网: https://nuxtjs.org/
中文网站:https://www.nuxtjs.cn/
Nuxt.js 应用一个完整的服务器请求到渲染(或用户通过 切换路由渲染页面)的流程:
一句话:为什么使用Nuxt.js?
对于有SEO需求的网页如果使用前端渲染技术去开发就不利于SEO,而Nuxt.js提供了服务
端渲染的解决方案,使用Nuxt.js则将有利于SEO。
Nuxt.js 团队创建了脚手架工具 create-nuxt-app,使用时需安装create-nuxt-app脚手架
npm install create-nuxt-app -g
创建Nuxt项目
npx create-nuxt-app 项目名
在`NPM`版本5.2.0默认安装了`npx`,在命令行窗口输入`npm --version`可查看当前版本号
输入项目名
✨ Generating Nuxt.js project in nuxt
? Project name: nuxt_demo
选择JavaScript作为编程语言
? Programming language: (Use arrow keys)
> JavaScript
TypeScript
选择Npm作为包管理工具
? Package manager: (Use arrow keys)
Yarn
> Npm
选择喜欢的 UI 框架
? UI framework: (Use arrow keys)
> None
Ant Design Vue
BalmUI
Bootstrap Vue
Buefy
Bulma
Chakra UI
Element
Framevuerk
iView
Tachyons
Tailwind CSS
Vuesax
Vuetify.js
Oruga
选择Axios作为Nuxt.js模块,需要通过按空格键才会选中期望值,此时括号中会出现星号,然后按下回车键进行确认即可。
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
>( ) Axios - Promise based HTTP client
( ) Progressive Web App (PWA)
( ) Content - Git-based headless CMS
? Nuxt.js modules:
>(*) Axios - Promise based HTTP client
( ) Progressive Web App (PWA)
( ) Content - Git-based headless CMS
选择ESLint工具作为代码规范检查工具
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
>( ) ESLint
( ) Prettier
( ) Lint staged files
( ) StyleLint
( ) Commitlint
选择测试框架
? Testing framework: (Use arrow keys)
> None
Jest
AVA
WebdriverIO
Nightwatch
选择渲染模式为SSR,SPA适合在客户端渲染
> Universal (SSR / SSG)
Single Page App
启动项目
cd 项目名
npm run 项目名
应用现在运行在 http://localhost:3000 上运行。
注意:Nuxt.js 会监听 pages 目录中的文件更改,因此在添加新页面时无需重新启动应用程序。
资源目录
资源目录assets 用于组织未编译的静态资源如 LESS、SASS 或 JavaScript。
组件目录
组件目录 components 用于组织应用的 Vue.js 组件。Nuxt.js 不会扩展增强该目录下 Vue.js 组件,即这些组件不会像页面组件那样有 asyncData 方法的特性。
布局目录
布局目录 layouts 用于组织应用的布局组件。
该目录名为Nuxt.js保留的,不可更改。
中间件目录
middleware 目录用于存放应用的中间件。
页面目录
页面目录 pages 用于组织应用的路由及视图。Nuxt.js 框架读取该目录下所有的 .vue 文件并自动生成对应的路由配置。
该目录名为Nuxt.js保留的,不可更改。
插件目录
插件目录 plugins 用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。
静态文件目录
静态文件目录 static 用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。
服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下。
举个例子: /static/logo.png 映射至 /logo.png
该目录名为Nuxt.js保留的,不可更改。
Store 目录
store 目录用于组织应用的 Vuex 状态树 文件。
Nuxt.js 框架集成了 Vuex 状态树 的相关功能配置,在 store 目录下创建一个 index.js 文件可激活这些配置。
该目录名为Nuxt.js保留的,不可更改。
nuxt.config.js 文件
nuxt.config.js 文件用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置。
该文件名为Nuxt.js保留的,不可更改。
package.json 文件
package.json 文件用于描述应用的依赖关系和对外暴露的脚本接口。
该文件不能被重命名。
别名
默认情况下,srcDir 和 rootDir 相同。
提示: vue 模板中, 如果需要引入 assets 或者 static 目录, 使用 ~/assets/your_image.png 和 ~/static/your_image.png方式。
Nuxt.js 依据 pages 目录结构自动生成 vue-router 模块的路由配置。
Nuxt.js根据pages的目录结构及页面名称定义规范来生成路由
要在页面之间使用路由,建议使用<nuxt-link>
标签。
<template>
<nuxt-link to="/">首页</nuxt-link>
</template>
假设 pages 的目录结构如下:
pages/
--| user/
-----| index.vue
-----| one.vue
--| index.vue
那么,Nuxt.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'
}
]
}
index.vue
<template>
<div>index.vue</div>
</template>
<script>
export default {
name: "index"
}
</script>
<style scoped>
</style>
one.vue
<template>
<div>one.vue</div>
</template>
<script>
export default {
name: "one"
}
</script>
<style scoped>
</style>
进行测试:
http://localhost:3000/user
http://localhost:3000/user/one
在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录。
以下目录结构:
pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue
Nuxt.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'
}
]
}
名称为 users-id 的路由路径带有 :id? 参数,表示该路由是可选的。如果想将它设置为必选的路由,需要在 users/_id 目录内创建一个 index.vue 文件。
API Configuration generate
警告:generate 命令会忽略动态路由: API Configuration generate
创建user.vue文件与user目录同一级
<template>
<div>
user.vue
<nuxt-child/>
</div>
</template>
<script>
export default {
name: "user"
}
</script>
<style scoped>
</style>
在user目录下创建_id.vue文件
<template>
<div>
参数id值:{{id}}
</div>
</template>
<script>
export default {
name: "_id",
data(){
return{
id:0,
}
},
mounted(){
this.id = this.$route.params.id || 0;
}
}
</script>
<style scoped>
</style>
http://localhost:3000/user
http://localhost:3000/user?123
Nuxt.js 可以让你在动态路由组件中定义参数校验方法,如果校验方法返回的值不为 true或Promise中 resolve 解析为false或抛出 Error , Nuxt.js 将自动加载显示 404 错误页面或 500 错误页面。
在pages/users/_id.vue中添加校验方法:
export default {
validate({ params }) {
// 必须是number类型
return /^\d+$/.test(params.id)
}
}
当携带数字参数时:
当携带非数字参数时:
可以通过 vue-router 的子路由创建 Nuxt.js 应用的嵌套路由。
创建内嵌子路由,你需要添加一个 Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。
Warning: 别忘了在父组件(.vue文件) 内增加<nuxt-child/>
用于显示子视图内容。
假设文件结构如:
pages/
--| users/
-----| _id.vue
-----| index.vue
--| users.vue
Nuxt.js 自动生成的路由配置如下:
router: {
routes: [
{
path: '/users',
component: 'pages/users.vue',
children: [
{
path: '',
component: 'pages/users/index.vue',
name: 'users'
},
{
path: ':id',
component: 'pages/users/_id.vue',
name: 'users-id'
}
]
}
]
}
创建user.vue文件与user目录保持平级
<template>
<div>
user.vue
<nuxt-link :to="'/user/123'">携带参数123,去_id.vue页面</nuxt-link>
<nuxt-child/>
</div>
</template>
<script>
export default {
name: "user"
}
</script>
<style scoped>
</style>
在user目录下创建_id.vue
<template>
<div>
参数id值:{{id}}
</div>
</template>
<script>
export default {
name: "_id",
data(){
return{
id:0,
}
},
mounted(){
this.id = this.$route.params.id;
}
}
</script>
<style scoped>
</style>
http://localhost:3000/user
Nuxt.js将/layout/default.vue作为所有页面的默认布局,Nuxt.js 允许你扩展默认的布局,或在 layout 目录下创建自定义的布局。
提示: 别忘了在布局文件中添加 <nuxt/> 组件用于显示页面的主体内容。
<template>
<div>
<Nuxt />
</div>
</template>
layouts 目录中的每个文件 (顶级) 都将创建一个可通过页面组件中的 layout 属性访问的自定义布局。
创建一个博客布局并将其保存到layouts/blog.vue
<template>
<div>
<div>我的博客导航栏在这里</div>
<nuxt />
</div>
</template>
然后必须告诉页面 (即pages/user/index.vue) 使用的自定义布局
<template>
<div>
user.vue
<nuxt-child/>
</div>
</template>
<script>
export default {
layout: "blog"
}
</script>
<style scoped>
</style>
Nuxt.js 扩展了 Vue.js,增加了一个叫 asyncData 的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。
asyncData方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用
asyncData方法来获取数据,Nuxt.js 会将 asyncData 返回的数据融合组件 data 方法返回的数据一并返回给当前组件。
注意:由于asyncData方法是在组件 初始化 前被调用的,所以在方法内是没有办法通过 this 来引用组件的实例对象。
asyncData方法返回data模型数据,在服务端被渲染,最后响应给前端,刷新页面查看页面源代码可以看到name模型数据已在页面源代码中显示。
export default {
asyncData(){
return {
name:'nuxt'
}
},
}
使用Promise是异步调用。
export default {
asyncData({ params }) {
return axios.get(`https://my-api/posts/${params.id}`).then(res => {
return { title: res.data.title }
})
}
}
nuxt.js中使用async 和 await配合promise可以实现同步调用效果。
export default {
async asyncData({ store, route }) {
var a = await new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("1")
resolve(1)
},2000)
});
var a = await new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("2")
resolve(2)
},1000)
});
}
在根目录plugins中新建文件axios.js
import { Message } from 'element-ui'
export default function({$axios, redirect}){
$axios.onError(err => {
const {statusCode, message} = err.response.data;
if(statusCode === 400){
Message.warning({message});
}
})
}
修改nuxt.config.js,调用插件
plugins: [
'@/plugins/element-ui',
'@/plugins/axios'
],
在store
文件夹新建user.js
/**
* 用户状态管理
* @returns {{userInfo: {user: {}, token: string}}}
*/
export const state = () => ({
userInfo: {
token: '',
user: {},
},
})
export const mutations = {
/**
* 保存用户信息到state
* @param state
* @param data
*/
setUserInfo (state, data) {
console.log('mutations---setUserInfo')
state.userInfo = data
},
}
export const actions = {
/**
* 登录
* @param commit
* @param data
* @returns {Promise<AxiosResponse<any>>}
*/
login ({ commit }, data) {
console.log('actions---login')
return this.$axios({
url: '/user/login',
method: 'POST',
data: data
}).then(res => {
const data = res.data
commit('setUserInfo', data)
return data
})
}
}
methods: {
clickChange () {
// this.$store.commit('user/setUserInfo',"ok")
this.$store.dispatch('user/login', this.form).then(res => {
// 跳转到首页
setTimeout(() => {
this.$router.replace('/')
}, 1000)
})
}
<div v-if="$store.state.user.userInfo.token">
<h3>{{$store.state.user.userInfo.user.name}}</h3>
</div>
现在可以将数据保存到
store
了,但是数据是保存在缓存中的,如果页面一刷新,那么数据就会丢失。所以需要使用localStorage
把数据保存到本地,但是由于nuxtjs
是运行在服务器的,不能直接在store
中使用浏览器的方法,所以需要借助插件vuex-persistedstate
,把本地存储的数据读取到store
插件地址:https://github.com/robinvdvleuten/vuex-persistedstate
安装插件
npm install --save vuex-persistedstate
在根目录plugins
中新建文件localStorage.js
import createPersistedState from 'vuex-persistedstate'
export default ({store}) => {
window.onNuxtReady(() => {
createPersistedState({
// 读取本地存储的数据到store
key: "store",
})(store)
})
}
修改nuxt.config.js
配置文件,在plugins
配置项中新增一条数据
plugins: [
{ src: '@/plugins/localStorage', ssr: false }
],
export const mutations = {
/**
* 清除用户数据
* @param state
* @param info
*/
cleanUserInfo (state, info) {
if (process.browser) {
localStorage.removeItem('userInfo')
}
state.userInfo = {}
}
}
this.$store.commit('user/cleanUserInfo')
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。