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 相关文章推荐
在页面上点击任一链接时触发一个事件的代码
Apr 07 Javascript
ASP.NET jQuery 实例3 (在TextBox里面阻止复制、剪切和粘贴事件)
Jan 13 Javascript
导航跟随滚动条置顶移动示例代码
Sep 11 Javascript
xmlhttp缓存清除的2种解决方法
Dec 13 Javascript
JS实现单行文字不间断向上滚动的方法
Jan 29 Javascript
JQuery球队选择实例
May 18 Javascript
jQuery form 表单验证插件(fieldValue)校验表单
Jan 24 Javascript
详解Node.js包的工程目录与NPM包管理器的使用
Feb 16 Javascript
js实现select二级联动下拉菜单
Apr 17 Javascript
利用vue实现模态框组件
Dec 19 Javascript
vue 使用ref 让父组件调用子组件的方法
Feb 08 Javascript
发布一款npm包帮助理解npm的使用
Jan 03 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
PHP4中session登录页面的应用
2008/07/25 PHP
php开发文档 会员收费1期
2012/08/14 PHP
PHP中spl_autoload_register()和__autoload()区别分析
2014/05/10 PHP
php实现面包屑导航例子分享
2015/12/19 PHP
对字符串进行HTML编码和解码的JavaScript函数
2010/02/01 Javascript
jQuery图片滚动图片的效果(另类实现)
2013/06/02 Javascript
浅谈javascript中call()、apply()、bind()的用法
2015/04/20 Javascript
前端框架Vue.js中Directive知识详解
2016/09/12 Javascript
js仿微博动态栏功能
2017/02/22 Javascript
JS+html5 canvas实现的简单绘制折线图效果示例
2017/03/13 Javascript
jQuery ajax实现省市县三级联动
2021/03/07 Javascript
vue自定义移动端touch事件之点击、滑动、长按事件
2018/07/10 Javascript
详解vue通过NGINX部署在子目录或者二级目录实践
2018/09/03 Javascript
微信小程序自定义组件components(代码详解)
2019/10/21 Javascript
[00:36]DOTA2上海特级锦标赛 Archon战队宣传片
2016/03/04 DOTA
[46:20]DOTA2-DPC中国联赛 正赛 PSG.LGD vs LBZS BO3 第二场 1月22日
2021/03/11 DOTA
python的re模块应用实例
2014/09/26 Python
Python语言的面相对象编程方式初步学习
2016/03/12 Python
python绘制铅球的运行轨迹代码分享
2017/11/14 Python
Python对数据进行插值和下采样的方法
2018/07/03 Python
Python 访问限制 private public的详细介绍
2018/10/16 Python
Python函数和模块的使用总结
2019/05/20 Python
Python+Pyqt实现简单GUI电子时钟
2021/02/22 Python
np.random.seed() 的使用详解
2020/01/14 Python
详解python常用命令行选项与环境变量
2020/02/20 Python
Python GUI库PyQt5图形和特效样式QSS介绍
2020/02/25 Python
python3.8.1+selenium实现登录滑块验证功能
2020/05/22 Python
matplotlib bar()实现多组数据并列柱状图通用简便创建方法
2021/02/24 Python
CSS3的Border-radius轻松制作圆角
2012/12/24 HTML / CSS
国际知名设计师时装商店:Coggles
2016/09/05 全球购物
火山咖啡:Volcanica Coffee
2019/10/29 全球购物
运动会解说词50字
2014/01/18 职场文书
院系推荐意见
2015/06/05 职场文书
24句精辟的现实社会语录,句句扎心,道尽人性
2019/08/29 职场文书
python双向链表实例详解
2022/05/25 Python
MySQL实现字段分割一行转多行的示例代码
2022/07/07 MySQL