nuxt.js

Posted 古墩古墩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nuxt.js相关的知识,希望对你有一定的参考价值。

英文官网地址:https://zh.nuxtjs.org/

中文官网地址:https://www.nuxtjs.cn/

github上的一个基于nuxt的服务端渲染项目:https://github.com/Sandop/NuxtPC

 创建一个nuxt项目:确保安装了npx(npx在NPM版本5.2.0默认安装了):

npx create-nuxt-app nuxtDemo

之后会让选择ui框架,服务器什么的,我选择的element-ui和express服务器,我喜欢做spa项目,就选择了搭建一个spa项目(后面才发现,用nuxt的目的是解决seo的问题,就不要用spa模式了,用这个框架就用那个universal模式就行)

安装之后,生成项目目录如下,无选择的spa页面

 

 和vue-cli相似

 cd到创建好的项目,npm run dev  运行项目

 assets:资源目录:放置用于组织未编译的静态资源如 LESSSASS 或 javascript

components:组件目录

layouts:布局目录,刚创建项目自带一个default.vue的自定义目录,什么内容都没有,就放了个<nuxt/>视图容器,这是所有组件页面都默认的布局,当然可以自定义布局,可以在具体页面通过layout指定页面使用的布局

middleware:中间件目录

pages:页面目录,nuxt会根据这个文件目录自动生成路由!!

plugins:插件目录,根vue.js应用 实例化之前需要运行的 Javascript 插件。

static:静态文件目录,用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。 服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下

store:Store目录,用于组织应用的 Vuex 状态树 文件。 Nuxt.js 框架集成了 Vuex 状态树 的相关功能配置,在 store 目录下创建一个 index.js 文件可激活这些配置。

nuxt.config.js :用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置。

package.json:用于描述应用的依赖关系和对外暴露的脚本接口。

 

配置:

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

配置文档:https://zh.nuxtjs.org/guide/configuration

路由:

 文档地址:https://zh.nuxtjs.org/guide/routing

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

要在页面之间使用路由,我们建议使用<nuxt-link> 标签。

视图:

 

 

 

模板

 定制化默认的 html 模板,只需要在应用根目录下创建一个 app.html 的文件。

默认模板为:可以在模板中添加ie条件表达式

<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
  <head {{ HEAD_ATTRS }}>
    {{ HEAD }}
  </head>
  <body {{ BODY_ATTRS }}>
    {{ APP }}
  </body>
</html>

布局

默认布局是创建项目时自动生成的layouts/default.vue

 

 

 layouts 目录中的每个文件 (顶级) 都将创建一个可通过页面组件中的 layout 属性访问的自定义布局。

 

 

错误页面

你可以通过编辑 layouts/error.vue 文件来定制化错误页面.

 

 

 这个布局文件不需要包含 <nuxt/> 标签。你可以把这个布局文件当成是显示应用错误(404,500等)的组件。

举一个个性化错误页面的例子 layouts/error.vue:

<template>
  <div class="container">
    <h1 v-if="error.statusCode === 404">页面不存在</h1>
    <h1 v-else>应用发生错误异常</h1>
    <nuxt-link to="/">首 页</nuxt-link>
  </div>
</template>

<script>
export default {
  props: [\'error\'],
  layout: \'blog\' // 你可以为错误页面指定自定义的布局
}
</script>

 

页面:

 页面组件实际上是 Vue 组件,只不过 Nuxt.js 为这些组件添加了一些特殊的配置项(对应 Nuxt.js 提供的功能特性)以便你能快速开发通用应用。

 

 

 

 

HTML 头部:

 Nuxt.js 使用了 vue-meta 更新应用的 头部标签(Head) and html 属性

Nuxt.js 允许你在 nuxt.config.js 里定义应用所需的所有默认 meta 标签,在 head 字段里配置就可以了:

一个使用自定义 viewport 和 谷歌字体 的配置示例:

head: {
  meta: [
    { charset: \'utf-8\' },
    { name: \'viewport\', content: \'width=device-width, initial-scale=1\' }
  ],
  link: [
    { rel: \'stylesheet\', href: \'https://fonts.googleapis.com/css?family=Roboto\' }
  ]
}

当然也可以引入jquery、bootstrap等第三方库

引入第三方库,有npm引入方式和CDN引入方式两种,可以自己选择,我一般用CDN引入第三方库,有利于减少项目体积;

 

异步数据

 Nuxt.js 扩展了 Vue.js,增加了一个叫 asyncData 的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。

asyncData 方法:

https://zh.nuxtjs.org/guide/async-data/

asyncData方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。 在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用 asyncData方法来获取数据,Nuxt.js 会将 asyncData 返回的数据融合组件 data 方法返回的数据一并返回给当前组件。

注意:由于asyncData方法是在组件 初始化 前被调用的,所以在方法内是没有办法通过 this 来引用组件的实例对象。

 此方法是服务端渲染的关键之一,它是在组件初始化之前调用的,方法的第一个参数是上下文对象,里面包括好多对象,如store,res,req,params,query,isDev,route,redirect,error等很有用的信息供我们使用;在这个方法内,要return出一个对象,这个对象会和data合并,能够直接绑定到模板中,作用方面和data是一样的;记住,这里面的有数据完成后才会初始化组件,这个很重要,一些DOM操作就不要在这个方法中进行了,因为这个方法进行的时候,还没有DOM,主要用于拿到初始数据就行。

资源文件

默认情况下 Nuxt 使用 vue-loader、file-loader 以及 url-loader 这几个 Webpack 加载器来处理文件的加载和引用。对于不需要通过 Webpack 处理的静态资源文件,可以放置在 static目录中。

静态文件

 如果你的静态资源文件需要 Webpack 做构建编译处理,可以放到 assets 目录,否则可以放到 static 目录中去。

Nuxt 服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下,像 robots.txt 或 sitemap.xml 这种类型的文件就很适合放到 static 目录中。

你可以在代码中使用根路径 / 结合资源相对路径来引用静态资源:

<!-- 引用 static 目录下的图片 -->
<img src="/my-image.png"/>

<!-- 引用 assets 目录下经过 webpack 构建处理后的图片 -->
<img src="~/assets/my-image-2.png"/>

插件

 https://zh.nuxtjs.org/guide/plugins

Nuxt.js允许您在运行Vue.js应用程序之前执行js插件。这在您需要使用自己的库或第三方模块时特别有用。

 

 

使用第三方模块

我们可以在应用中使用第三方模块,一个典型的例子是在客户端和服务端使用 axios 做 HTTP 请求。略

使用 Vue 插件

假如我们想使用 vue-notifications 显示应用的通知信息,我们需要在程序运行前配置好这个插件。

安装:npm install --save vue-notification

首先增加文件 plugins/vue-notifications.js

import Vue from \'vue\'
import VueNotifications from \'vue-notification\'

Vue.use(VueNotifications)

然后, 在 nuxt.config.js 内配置 plugins 如下:

module.exports = {
  plugins: [\'~/plugins/vue-notifications\']
}

使用:

在vue文件中:

<notifications group="foo" />
this.$notify({
  group: \'foo\',
  title: \'Important message\',
  text: \'Hello user! This is a notification!\'
});

效果:

 

ES6 插件

 如果插件位于node_modules并导出模块,需要将其添加到transpile构建选项:

module.exports = {
  build: {
    transpile: [\'vue-notifications\']
  }
}

注入 $root 和 context

 有时您希望在整个应用程序中使用某个函数或属性值,此时,你需要将它们注入到Vue实例(客户端),context(服务器端)甚至 store(Vuex)。按照惯例,新增的属性或方法名使用$作为前缀。

注入 Vue 实例

plugins/vue-inject.js:

import Vue from \'vue\'

Vue.prototype.$myInjectedFunction = string => console.log(\'This is an example\', string)

nuxt.config.js:

export default {
  plugins: [\'~/plugins/vue-inject.js\']
}

这样,您就可以在所有Vue组件中使用该函数。

这样,您就可以在所有Vue组件中使用该函数。

export default {
  mounted () {
    this.$myInjectedFunction(\'test\')
  }
}

注入 context

context注入方式和在其它vue应用程序中注入类似。

plugins/ctx-inject.js:

export default ({ app }, inject) => {
  // Set the function directly on the context.app object
  app.myInjectedFunction = string => console.log(\'Okay, another function\', string)
}

nuxt.config.js:

export default {
  plugins: [\'~/plugins/ctx-inject.js\']
}

现在,只要您获得context,你就可以使用该函数(例如在asyncDatafetch中)。 ctx-example-component.vue:

export default {
  asyncData (context) {
    context.app.myInjectedFunction(\'ctx!\')
  }
}

同时注入

如果您需要同时在contextVue实例,甚至Vuex中同时注入,您可以使用inject方法,它是plugin导出函数的第二个参数。 将内容注入Vue实例的方式与在Vue应用程序中进行注入类似。系统会自动将$添加到方法名的前面。

plugins/combined-inject.js:

export default ({ app }, inject) => {
  inject(\'myInjectedFunction\', string => console.log(\'That was easy!\', string))
}

nuxt.config.js:

export default {
  plugins: [\'~/plugins/combined-inject.js\']
}

现在您就可以在context,或者Vue实例中的this,或者Vuexactions/mutations方法中的this来调用myInjectedFunction方法。 ctx-example-component.vue:

export default {
  mounted () {
    this.$myInjectedFunction(\'works in mounted\')
  },
  asyncData (context) {
    context.app.$myInjectedFunction(\'works with context\')
  }
}

store/index.js:

export const state = () => ({
  someValue: \'\'
})

export const mutations = {
  changeSomeValue (state, newValue) {
    this.$myInjectedFunction(\'accessible in mutations\')
    state.someValue = newValue
  }
}

export const actions = {
  setSomeValueToWhatever ({ commit }) {
    this.$myInjectedFunction(\'accessible in actions\')
    const newValue = \'whatever\'
    commit(\'changeSomeValue\', newValue)
  }
}

只在客户端使用的插件

 不支持ssr的系统,插件只在浏览器里使用,这种情况下下,你可以用 ssr: false ,使得插件只会在客户端运行。

举个例子:

nuxt.config.js:

module.exports = {
  plugins: [
    { src: \'~/plugins/vue-notifications\', ssr: false }
  ]
}

plugins/vue-notifications.js:

import Vue from \'vue\'
import VueNotifications from \'vue-notification\'

Vue.use(VueNotifications)

 

 例子:

nuxt.config.js:

export default {
  plugins: [
    { src: \'~/plugins/both-sides.js\' },
    { src: \'~/plugins/client-only.js\', mode: \'client\' },
    { src: \'~/plugins/server-only.js\', mode: \'server\' }
  ]
}

传统命名插件

 如果假设插件仅在 客户端 或 服务器端 运行,则 .client.js 或 .server.js可以作为插件文件的扩展名应用,该文件将自动包含在相应客户端或者服务端上。

例子:

nuxt.config.js:

export default {
  plugins: [
    \'~/plugins/foo.client.js\', // only in client side
    \'~/plugins/bar.server.js\', // only in server side
    \'~/plugins/baz.js\' // both client & server
  ]
}

 

模块

 https://zh.nuxtjs.org/guide/modules

模块是Nuxt.js扩展,可以扩展其核心功能并添加无限的集成。

 

 

 

 

 

 

 

 

 模块列表: https://github.com/topics/nuxt-module 

有兴趣可以看一下,比较深奥,不适合初级开发者

Vuex 状态树

 对于每个大项目来说,使用状态树 (store) 管理状态 (state) 十分有必要。这就是为什么 Nuxt.js 内核实现了 Vuex

普通方式

Nuxt.js允许您拥有一个 store 目录,其中包含与模块对应的每个文件。

首先,只需将状态导出为 函数,将变量和操作作为 store/index.js 中的对象导出:

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

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

然后,您可以拥有 store/todos.js 文件:

export const state = () => ({
  list: []
})

export const mutations = {
  add (state, text) {
    state.list.push({
      text,
      done: false
    })
  },
  remove (state, { todo }) {
    state.list.splice(state.list.indexOf(todo), 1)
  },
  toggle (state, todo) {
    todo.done = !todo.done
  }
}

Vuex将如下创建:

new Vuex.Store({
  state: () => ({
    counter: 0
  }),
  mutations: {
    increment (state) {
      state.counter++
    }
  },
  modules: {
    todos: {
      namespaced: true,
      state: () => ({
        list: []
      }),
      mutations: {
        add (state, { text }) {
          state.list.push({
            text,
            done: false
          })
        },
        remove (state, { todo }) {
          state.list.splice(state.list.indexOf(todo), 1)
        },
        toggle (state, { todo }) {
          todo.done = !todo.done
        }
      }
    }
  }
})

在您的 pages/todos.vue 中,使用 todos 模块:

 

 


 

以上是关于nuxt.js的主要内容,如果未能解决你的问题,请参考以下文章

nuxt.js服务端渲染中如何实现路由的跳转

NUXT.js 和 Axios 运行时如何避免代码重复?

如何在 nuxt.js 中定义路由

Nuxt学习笔记

如何在 nuxt.js 中挑选 bootstrap-vue.js 模块?

Nuxt.js 集成 koa2