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 相关文章推荐
将文本输入框内容加入表中的js代码
Aug 18 Javascript
js获取电脑分辨率的思路及操作
Nov 22 Javascript
网站繁简切换的JS遇到页面卡死的解决方法
Mar 12 Javascript
详解JavaScript对Date对象的操作问题(生成一个倒数7天的数组)
Oct 01 Javascript
js实现商品抛物线加入购物车特效
Nov 18 Javascript
微信小程序 swiper组件详解及实例代码
Oct 25 Javascript
Angularjs根据json文件动态生成路由状态的实现方法
Apr 17 Javascript
jQuery与vue实现拖动验证码功能
Jan 30 jQuery
Vue为什么要谨慎使用$attrs与$listeners
Aug 27 Javascript
微信小程序实现通讯录列表展开收起
Nov 18 Javascript
如何封装Vue Element的table表格组件
Feb 06 Vue.js
js判断两个数组相等的5种方法
May 06 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
PHP 字符串 小常识
2009/06/05 PHP
jQuery中的RadioButton,input,CheckBox取值赋值实现代码
2014/02/18 PHP
分享3个php获取日历的函数
2015/09/25 PHP
JavaScript 的方法重载效果
2009/08/07 Javascript
JS中动态添加事件(绑定事件)的代码
2011/01/09 Javascript
Jquery实现视频播放页面的关灯开灯效果
2013/05/27 Javascript
移动设备web开发首选框架:zeptojs介绍
2015/01/29 Javascript
jquery的幻灯片图片切换效果代码分享
2015/09/07 Javascript
JS判断图片是否加载完成方法汇总(最新版)
2016/05/13 Javascript
vue实现简单实时汇率计算功能
2017/01/15 Javascript
Three.js 再探 - 写一个微信跳一跳极简版游戏
2018/01/04 Javascript
详解关于element级联选择器数据回显问题
2019/02/20 Javascript
ES6基础之 Promise 对象用法实例详解
2019/08/22 Javascript
vuex+axios+element-ui实现页面请求loading操作示例
2020/02/02 Javascript
javascript 数组精简技巧小结
2020/02/26 Javascript
[02:52]2014DOTA2西雅图国际邀请赛 CIS战队巡礼
2014/07/07 DOTA
使用Python对SQLite数据库操作
2017/04/06 Python
利用Anaconda完美解决Python 2与python 3的共存问题
2017/05/25 Python
django表单实现下拉框的示例讲解
2018/05/29 Python
Python 限制线程的最大数量的方法(Semaphore)
2019/02/22 Python
Python面向对象程序设计构造函数和析构函数用法分析
2019/04/12 Python
python和mysql交互操作实例详解【基于pymysql库】
2019/06/04 Python
Jupyter notebook运行Spark+Scala教程
2020/04/10 Python
pycharm 2018 激活码及破解补丁激活方式
2020/09/21 Python
Scrapy中如何向Spider传入参数的方法实现
2020/09/28 Python
Osklen官方在线商店:巴西服装品牌
2019/04/25 全球购物
CheapTickets香港机票预订网站:CheapTickets.hk
2019/06/26 全球购物
房屋转让协议书范本
2014/04/11 职场文书
商场父亲节活动方案
2014/08/27 职场文书
2014年初中班主任工作总结
2014/11/08 职场文书
学前班语言教学计划
2015/01/20 职场文书
2015年信访维稳工作总结
2015/04/07 职场文书
2015年团委副书记工作总结
2015/07/23 职场文书
redis使用不当导致应用卡死bug的过程解析
2021/07/01 Redis
Python实现视频中添加音频工具详解
2021/12/06 Python
科学家测试在太空中培育人造肉,用于未来太空旅行
2022/04/29 数码科技