Nuxt.js实战详解


Posted in Javascript onJanuary 18, 2018

一、为什么选择Nuxt.js

多数是基于webpack构建的项目,编译出来的html文件,资源文件都被打包到js中,以下图404页面代码为例。从代码中可以看出,这样的页面是不利于 搜索引擎优化(SEO, Search Engine Optimization) ,并且 内容到达时间(time-to-content) (或称之为首屏渲染时长)也有很大的优化空间。为了解决以上问题,引入了 Nuxt.js 框架。

vue官网对于Nuxt.js也是很推荐的,除此之外,Nuxt.js的开发者积极活跃,版本迭代迅速。经过一系列rc版本后,终于在1月9日发布了 v1.0.0 正式版本!

Nuxt.js实战详解

图1. 使用webpack构建的HTML(代码已格式化)

Nuxt.js实战详解

图2. 使用 Nuxt.js 构建的HTML(代码已格式化)

二、Nuxt.js 简介

Nuxt.js 是一个基于 Vue.js 的通用应用框架,它预设了利用 Vue.js 开发 服务端渲染(SSR, Server Side Render) 的应用所需要的各种配置,同时也可以一键生成静态站点。

作为框架,Nuxt.js 为 客户端/服务端 这种典型的应用架构模式提供了许多有用的特性,例如异步数据加载、中间件支持、布局支持等。区别于其他 vue SSR 框架,Nuxt.js 有以下比较明显的特性。

  1. 自动代码分层
  2. 强大的路由功能,支持异步数据(路由无需额外配置)
  3. HTML头部标签管理(依赖 vue-meta 实现)
  4. 内置 webpack 配置,无需额外配置

三、项目实战1、项目创建

官方提供了基于 vue-cli 脚手架工具,常用的有如下三个,更多脚手架工具可以查看nuxt-community 。本项目使用的是 express-template。

vue init nuxt-community/starter-template <project-name>

vue init nuxt-community/koa-template <project-name>
 
vue init nuxt-community/express-template <project-name>

2、开发

1)目录结构

├─assets   资源目录,未编译的静态资源如less、js
├─components  组件目录
├─layouts  布局目录
├─mock   mock数据
├─node_modules  
├─pages   页面目录
 ├─index.vue
 ├─....   
├─plugins  插件
├─server   express服务
├─static   静态文件目录
├─store   vuex store
├─utils   工具方法

2)配置

Nuxt.js 默认的配置涵盖了大部分使用情形,也可通过修改 nuxt.config.js 来覆盖默认配置。

// nuxt.config.js 文件配置
const path = require('path')

module.exports = {
 // Headers of the page
 head: {
 title: '默认共用title',
 meta: [
 { charset: 'utf-8' },
 { 'http-equiv': 'pragma', content: 'no-cache' },
 { 'http-equiv': 'cache-control', content: 'no-cache' },
 { 'http-equiv': 'expires', content: '0' },
 { content: 'telephone=no', name: 'format-detection' }
 ],
 // html head 中创建 script 标签
 script: [
 { innerHTML: require('./assets/js/flexible_nuxt'), type: 'text/javascript', charset: 'utf-8'}
 ],
 // 不对<script>标签中内容做转义处理
 __dangerouslyDisableSanitizers: ['script']
 },
 // Global CSS
 css: ['~/assets/css/reset.css', '~/assets/css/main.less'],
 // Global env
 env: {
 __ENV: process.env.__ENV
 },
 build: {
 vendor: ['axios'],
 postcss: [
 require('postcss-px2rem')({
 remUnit: 75
 })
 ],
 extend (config, ctx) {
 if (ctx.isClient) {
 // 拓展 webpack 配置
 config.entry['polyfill'] = ['babel-polyfill']
 config.module.rules.push({
  enforce: 'pre',
  test: /\.(js|vue)$/,
  loader: 'eslint-loader',
  exclude: /(node_modules)/
 })
 // 添加 alias 配置
 Object.assign(config.resolve.alias, {
  'utils': path.resolve(__dirname, 'utils')
 })
 }
 }
 },
 plugins: [{src: '~plugins/toast', ssr: false}, {src: '~plugins/dialog', ssr: false}]
}

HTML头部标签管理:

Nuxt.js 通过 vue-meta 实现头部标签管理,在 nuxt.config.js 中的 head 配置。所有的页面都会走这个配置,如果想要修改某一页面的title,可以在 pages/**.vue 文件下,添加如下配置,这时该页面的标题就变成了“收车费”,其余页面还保持原有标题不变。

Nuxt.js实战详解

在config header配置中, __dangerouslyDisableSanitizers: ['script'] 主要是为了不对<script>标签中内容做转义处理。看下面的例子?:

head: {
 title: 'myTitle',
 meta: [
 { charset: 'utf-8' },
 { 'http-equiv': 'pragma', content: 'no-cache' },
 { 'http-equiv': 'cache-control', content: 'no-cache' },
 { 'http-equiv': 'expires', content: '0' },
 { content: 'telephone=no', name: 'format-detection' }
 ],
 script: [
 { innerHTML: 'console.log("hello")', type: 'text/javascript', charset: 'utf-8'}
 ]
 },

生成 html:

<script data-n-head="true" type="text/javascript" charset="utf-8">console.log("hello")</script>

我们发现 vue-meta 把引号做了转义处理,加入 __dangerouslyDisableSanitizers: ['script'] 后,就不会再对这些字符做转义了,该字段使用需慎重!

3)路由

Nuxt.js 依据 pages 目录结构,自动生成 vue-router 模块的路由配置。

假设 pages 的目录结构如下:

Nuxt.js实战详解

那么,Nuxt.js 自动生成的路由配置如下:

Nuxt.js实战详解

嵌套路由:

创建内嵌子路由,需要添加一个 Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。在父级 Vue 文件内增加 <nuxt-child/> 用于显示子视图内容。

4)布局

Nuxt.js布局方式如下图所示:

Nuxt.js实战详解

layouts对应目录中的layouts文件夹,默认pages下的页面走的都是 layouts/default.vue 布局方式,如下图。其中<nuxt/>可以类似vueslot插槽的概念,pages/**.vue中的内容会插在<nuxt/>内。

Nuxt.js实战详解

此外,如果想要某一页面,不走默认布局方式,可以在vue文件中配置layouts,如下。

<script>
export default {
 layout: 'demo_layout',
 ...
}
</script>

5)vuex

在根目录创建 store 目录,就会默认引用 vuex 模块,除此之外,还进行了以下的操作:1)将 vuex 模块 加到 vendors 构建配置中去;2)设置 Vue 根实例的 store 配置项。

Nuxt.js 支持两种使用 store 的方式:

  1. 普通方式:store/index.js 返回一个 Vuex.Store 实例
  2. 模块方式:store 目录下的每个 .js 文件会被转换成为状态树指定命名的子模块 (当然,index 是根模块,相当于设置了namespaced: true)

Nuxt.js提供了模块方式的简单写法:使用状态树模块化的方式,store/index.js 不需要返回 Vuex.Store 实例,直接将 state、mutations 和 actions 暴露出来即可。示例如下:

export const state = () => ({
 accesstoken: ''
})

export const mutations = {
 setAccesstoken (state, accesstoken) {
 state.accesstoken = accesstoken
 }
}

6)异步数据 asyncData

Nuxt.js 增加了一个 asyncData 方法,用于 在设置组件数据 之前 能够异步获取 或 处理数据。
由于 asyncData 是在组件 初始化 之前被调用的,所以不能通过 this 引用组件的实例对象,可以使用上下文对象来实现某些功能,可参考 context api

示例?:

asyncData (params) {
 let accesstoken = params.route.query.accesstoken
 // request 基于 axios 封装的函数
 return request({
 url: '/drivers/banks',
 method: 'get',
 headers: {
 accesstoken
 }
 })
 .then(res => {
 let {
 bankInfo
 } = res.data
 return {
 banksData: bankInfo,
 accesstoken
 }
 })
 .catch(err => {
 return error({ message: 'accesstoken not found', statusCode: 404 })
 })
}

上述代码,会在 组件初始化 之前,请求'/drivers/banks'接口,接口返回的数据会 融合在 data 中,一并返回模版显示。在浏览器中,使用Vue DevTools可以清晰的查看到 banksData, accesstoken 都在data中。
在调试中发现,刷新页面时,该请求是在服务端发送的,由其他页面回退到该页面时,请求是在客户端发送的。

7)fecth方法

asyncData 方法类似,不同的是它不会设置组件的数据,作用是设置 store 数据。

五、总结

本项目在开发中,使用的是 1.0.0-rc9 版本,我们正在积极尝试迁移到 1.0.0 正式版本。但是,1.0.0-rc9 版本,未见明显问题,比较稳定,足以投入到生产中。

本文主要介绍 Nuxt.js 的特性,后面还会和大家分享踩的坑。文中有任何表述不清或不当的地方,欢迎大家批评指正。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
学习YUI.Ext 第六天--关于树TreePanel(Part 1)
Mar 10 Javascript
爱恋千雪-US-AscII加密解密工具(网页加密)下载
Jun 06 Javascript
JavaScript 组件之旅(二)编码实现和算法
Oct 28 Javascript
对xmlHttp对象的理解
Jan 17 Javascript
JavaScript中的关键字&quot;VAR&quot;使用详解 分享
Jul 31 Javascript
理解 JavaScript Scoping &amp; Hoisting(二)
Nov 18 Javascript
JavaScript实现阿拉伯数字和中文数字互相转换
Jun 12 Javascript
基于jQuery的AJAX和JSON实现纯html数据模板
Aug 09 Javascript
关于axios返回空对象的问题解决
Apr 04 Javascript
jQuery实现多张图片上传预览(不经过后端处理)
Apr 29 jQuery
简化vuex的状态管理方案的方法
Jun 02 Javascript
Node.js实现一个HTTP服务器的方法示例
May 13 Javascript
React Native 真机断点调试+跨域资源加载出错问题的解决方法
Jan 18 #Javascript
ajax请求data遇到的问题分析
Jan 18 #Javascript
angular.js和vue.js中实现函数去抖示例(debounce)
Jan 18 #Javascript
vue-scroller记录滚动位置的示例代码
Jan 17 #Javascript
基于vue监听滚动事件实现锚点链接平滑滚动的方法
Jan 17 #Javascript
详解微信小程序审核不通过的解决方法
Jan 17 #Javascript
swiper动态改变滑动内容的实现方法
Jan 17 #Javascript
You might like
晶体管来复再生式二管收音机
2021/03/02 无线电
防止MySQL注入或HTML表单滥用的PHP程序
2009/01/21 PHP
php实现数据库的增删改查
2017/02/26 PHP
JavaScript中window、doucment、body的解释
2013/08/14 Javascript
javascript中数组的concat()方法使用介绍
2013/12/18 Javascript
java和javascript获取word文档的书签位置对比
2014/06/19 Javascript
Jquery 实现grid绑定模板
2015/01/28 Javascript
浅谈JavaScript中的字符编码转换问题
2015/07/07 Javascript
纯javascript判断查询日期是否为有效日期
2015/08/24 Javascript
JS实现带有3D立体感的银灰色竖排折叠菜单代码
2015/10/20 Javascript
浅谈几种常用的JS类定义方法
2016/06/08 Javascript
利用JS判断客户端类型你应该知道的四种方法
2017/12/22 Javascript
深入了解javascript 数组的sort方法
2018/06/01 Javascript
vue实现未登录跳转到登录页面的方法
2018/07/17 Javascript
Vue.js 事件修饰符的使用教程
2018/11/01 Javascript
vscode下的vue文件格式化问题
2018/11/28 Javascript
nodejs微信开发之授权登录+获取用户信息
2019/03/17 NodeJs
详解Vue demo实现商品列表的展示
2019/05/07 Javascript
Vue通过配置WebSocket并实现群聊功能
2019/12/31 Javascript
Vue.js中Line第三方登录api的实现代码
2020/06/29 Javascript
springboot+vue+对接支付宝接口+二维码扫描支付功能(沙箱环境)
2020/10/15 Javascript
Python入门篇之正则表达式
2014/10/20 Python
Python使用logging结合decorator模式实现优化日志输出的方法
2016/04/16 Python
python利用lxml读写xml格式的文件
2017/08/10 Python
python编程嵌套函数实例代码
2018/02/11 Python
python实现微信自动回复及批量添加好友功能
2019/07/03 Python
django 简单实现登录验证给你
2019/11/06 Python
python实现将列表中各个值快速赋值给多个变量
2020/04/02 Python
基于python 将列表作为参数传入函数时的测试与理解
2020/06/05 Python
Python+Kepler.gl实现时间轮播地图过程解析
2020/07/20 Python
详解window.open被浏览器拦截的解决方案
2019/07/18 HTML / CSS
缓刑期间思想汇报范文
2014/10/10 职场文书
关于长城的导游词
2015/01/30 职场文书
社团个人总结范文
2015/03/05 职场文书
毕业生爱心捐书倡议书
2015/04/27 职场文书
React forwardRef的使用方法及注意点
2021/06/13 Javascript