Skip to content

Latest commit

 

History

History
413 lines (300 loc) · 10.4 KB

nuxt.md

File metadata and controls

413 lines (300 loc) · 10.4 KB

NUXT基本用法介绍

nuxt.jsvue.js的一个服务端渲染(SSR)框架,vue.js官方有提供一个SSR文档,但是需要自己去配置开发环境,也挺繁琐的。而nuxt.js,配置好了开发环境,并且扩展了一些额外功能,能够开箱即用。不过在使用nuxt.js之前最好能够看一下官方的SSR教程,对理解原理和掌握nuxt.js都会有很大的帮助。

nuxt的使用

# 使用vue-cli工具进行初始化
$ vue init nuxt-comminity/start-template <project-name>​

$ cd <project-name>

$ npm install​

# 启动开发服务
$ npm run dev

项目目录结构

nuxt.js对项目目录有一定的规定,某些文件或者目录是必须保留的,这也是官方SSR和nuxt.js不同点之一,官方SSR可以自己定制目录结构。弄清了每个目录存放什么样的文件,学习nuxt.js的旅程也就完成了一大半了。

 ├── assets # 用于组织未编译的静态资源如Less、SCSS和JavaScript
 │   
 ├── components # 存放vue组件,不会有`asyncData`的方法
 │   
 ├── layouts # 布局组件,不能更改
 │   └── default.vue
 ├── middleware # 存放应用的中间件
 │   
 ├── nuxt.config.js # 个性化配置文件,覆盖默认配置,不可更改
 ├── pages # 组织应用的路由和视图,不可更改
 │   
 ├── plugins # 组织那些需要在根vue应用实例化之前需要运行的JavaScript插件,不可更改
 │   
 ├── static # 存放静态文件,此文件不会被webpack编译处理,不可更改
 │   └── favicon.ico
 └── store # vuex状态树,包含index.js文件的话,就会激活vuex配置,不可更改    
     └── index.js

列举常见的开发需求了解nuxt.js的目录结构和配置

官网中有对每个目录和配置进行详细介绍,这里通过实际开发需求进行巩固。

配置路由

nuxt.js中不用我们在浏览器渲染的那这样自己定义router对象,nuxt.js会根据pages下面的文件名进行路由解析。

  • 普通路由
pages
---| index.vue
---| users/
------| index.vue

nuxt会根据以上目录结构渲染出类似下面配置的路由

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
    {
      name: 'user',
      path: '/user',
      component: 'pages/users/index.vue'
    },
  ]
}
  • 动态路由
pages
----| users/
-------| _id.vue
----| _slug/
--------| comments.vue
--------| index.vue

解析后的路由

router: {
  routes: [
    {
      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'
    }
  ]
}
  • 嵌套路由

嵌套路由,需要创建一个.vue文件,然后创建一个同名的文件夹存放子组件,父级组件需要添加<nuxt-child/>

比如现在有一个用户页面,然后这个页面中间部分显示用户信息,根据不同的id显示不同的用户信息。

pages
----| users.vue
----| users/
-------| _id.vue

记住users.vue页面中记得添加<nuxt-child/>,比如

<template>
  <div>users</div>
  <nuxt-child/>
</template>

<nuxt/><nuxt-child/>类似于<router-view/>

最终渲染的路由为

router: {
  routes: [
    {
      path: '/users',
      component: 'pages/users.vue',
      children: [
        {
          path: ':id',
          component: 'pages/users/_id.vue',
          name: 'users-id'
        }
      ]
    }
  ]
}

布局

自定义布局在layouts目录下,有一个默认布局文件default.vue

<template>
  <div>
    <nuxt/>
  </div>
</template>

这里的<nuxt/>类似于<router-view/>,比如我们想要添加一个公用的头部导航组件和一个底部组件

<template>
  <div>
    <head-nav/>
    <nuxt/>
    <footer/>
  </div>
</template>

使用第三方UI库或者组件

在实际开发中经常会使用一些第三方库,有些库需要在vue根实例进行初始化,比如element-ui或者一些组件,也有一些不需要在根实例之前运行的,比如axios。

以使用element-ui为例,我们会在vue实例化之前引入element-ui,一般在main.js中引用

//main.js

import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'

Vue.use(ElementUI)

new Vue({/*...*/})

那么在nuxt.js则需要将引用element-ui的文件放在plugins中,前面在目录树中对plugins目录进行介绍,目录主要用于组织那些需要在根vue应用实例化之前需要运行的JavaScript插件。

所以可以在目录下新建一个文件用于初始化element-ui

// element.js

import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'

Vue.use(ElementUI)

然后在nuxt.config.js进行配置

plugins: [
  '~/plugins/element'
]

如果插件只在浏览器中使用,则可以添加ssr: false,如下

plugins: [
  {src: '~/plugins/vue-notifications' ssr: false}
]

使用axios

axios也是第三方插件,但是和element-ui不同的是,axios不用在vue根实例之前创建。但是如果在每个页面都进行import axios from 'axios的话,会导致axios打包多次,因此再添加额外的配置,即在nuxt.config.js中添加如下配置即可

// nuxt.config.js

build: {
  vendor: ['axios']
}

这样的话,即使在多个页面进行import也不会进行打包多次

引用CSS资源

nuxt提供了两个资源文件目录,分别是assetsstatic,两者的区别在于前者会进行wbepack构建编译,后者不会。

assets的资源文件会进行构建编译,所有的资源URL例如 <img src="...">background: url(...) 和 CSS中的 @import 均会被解析成模块通过 require 引用

CSS代码中使用 url('~assets/image.png'), 那么编译后它将被转换成 require('~assets/image.png')

static为静态文件,不会进行编译,nuxt启动时,该目录下的文件会映射至应用的根路径/下,所以在代码中使用根路径/ 结合资源相对路径来引用静态资源

<img src="/my-image.png"/>

现在回到如何引用CSS资源的问题上,CSS资源有多种,有需要编译的(less、scss、stylus)和不需要编译的,也有使用外链的。

很多情况下我们会把样式写在单个vue组件中,但是也不可避免需要引用css资源。在nuxt中有多种引用css资源的方式,常用的通过import@import和配置nuxt.config.js

  • import

vue根实例之前通过import导入样式文件,样式将可以在全局引用。比如之前使用element-ui,就是在根实例导入import 'element-ui/lib/theme-default/index.css'样式库的。所以如果有多个样式库需要引用,根据按照引用三方库的形式,写一个插件,用来专门引用css样式。

并且,通过import引入的样式库,如果使用了预处理器比如scss会自动编译。所以通过这种方式引用css资源,css文件可以不放在assetsstatic文件夹中,可以自定义文件夹用来专门存放css文件,比如styles文件夹。

  • @import

这是css文件专用的引用方式,可以在vue组件的style标签下面引用。如

// vue组件

<style>
@import "~/styles/variables.scss"

</style>
  • nuxt.config.js

nuxt配置文件中有两种方式来引用css资源,一种是通过配置head对象的link属性,一种是配置CSS对象

配置link的一般用来引用外链资源,比如引用一个normalize.css

// nuxt.config.js

head {
  link: [
    { rel: 'stylesheet', href: '//cdn.bootcss.com/normalize/8.0.0/normalize.css'}
  ]
}

当然也可以使用项目内部css文件,但是css文件德放在static文件下,并且是不需要编译的css

// nuxt.config.js

head: {
  link: [
    
    // 只需要写`/`路径即可
    { rel: 'stylesheet', href: '/normalize.css'}
  ]
}

如果想使用内部的或者需要编译的scss文件,需要将资源放在assets文件夹下,并且配置CSS对象

// nuxt.config.js

css: [
  '~/assets/styles/global.scss'
]

引用外部js文件

也是用过配置nuxt.config.jshead对象

// nuxt.config.js

head: {
  script: [
    // static文件下的
    { src: '/js/qrcode.js' },
    // CDN
    { src: 'https://cdn.bootcss.com/babel-polyfill/7.0.0-beta.44/polyfill.js' }
  ]
}

使用预处理器

只需要安装对应的loader即可,比如使用scss

$ npm i node-sass scss-loader -D

数据获取

服务端渲染需要在页面组件渲染之前处理好数据,所以需要特殊的方式获取这些数据。nuxt为每一个页面组件(pages文件夹下)提供了一个方法asyncData用来获取数据。

export default {
  async asyncData ({ params }) {
    let { data } = await axios.get(`https://my-api/posts/${params.id}`)
    return { title: data.title }
  }
}

asyncData方法的第一个参数为上下文对象,具体变量

并且该方法返回的数据融合组件 data 方法返回的数据一并返回给当前组件

vuex

nuxt中集成了vuex,只要store文件有index.js便可激活

  • 普通方式

index.js文件中暴露Vuex.Store实例

// store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = () => new Vuex.Store({
  state: {
    counter: 0
  },
  mutations: {
    increment (state) {
      state.counter++
    }
  }
})
export default store
  • 模块方式

store/index.js不需要返回Vuex.Store实例,而应该直接将statemutationsactions暴露出来

// store/index.js

export const state = () => ({
  counter: 0
})

export const mutations = {
  increment (state) {
    state.counter++
  }
}

其他模块文件类似