Nuxt.js教程(入门篇)

目录
一、路由
二、视图
三、异步数据
四、插件

系列教程
Nuxt.js教程(初识篇)


一、路由

1、基础路由
pages/
--| user/
-----| index.vue
-----| one.vue
--| index.vue

//自动转换成以下路由配置,因此,管理pages目录内容,就相当于配置路由

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
    {
      name: 'user',
      path: '/user',
      component: 'pages/user/index.vue'
    },
    {
      name: 'user-one',
      path: '/user/one',
      component: 'pages/user/one.vue'
    }
  ]
}
2、动态路由
pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue    //users没有路由组件,_id是可选路由
--| index.vue

//加上‘_’前缀,即可配置动态路由

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
    {
      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'
    }
  ]
}
3、动态路由校验
//动态路由的层级名,是由相应组件的validate函数,通过名称验证来决定的

//  user/_id.vue
export default {
    validate ({ params }) {
    // 规定改层级名,必须是数字
    // localhost:3000/user/任意数字串,才可以访问该组件
    return /^\d+$/.test(params.test)
    }
}
4、嵌套路由
pages/
--| users/
-----| _id.vue
-----| index.vue
--| users.vue

//将页面级的路由组件,抽离成单独组件,内部存在小型路由组件

router: {
  routes: [
    {
      path: '/users',
      component: 'pages/users.vue',
      children: [
        {
          path: '',
          component: 'pages/users/index.vue',
          name: 'users'
        },
        {
          path: ':id',
          component: 'pages/users/_id.vue',
          name: 'users-id'
        }
      ]
    }
  ]
}
5、动态嵌套路由
pages/
--| _category/
-----| _subCategory/
--------| _id.vue
--------| index.vue
-----| _subCategory.vue
-----| index.vue
--| _category.vue
--| index.vue

router: {
  routes: [
    {
      path: '/',
      component: 'pages/index.vue',
      name: 'index'
    },
    {
      path: '/:category',
      component: 'pages/_category.vue',
      children: [
        {
          path: '',
          component: 'pages/_category/index.vue',
          name: 'category'
        },
        {
          path: ':subCategory',
          component: 'pages/_category/_subCategory.vue',
          children: [
            {
              path: '',
              component: 'pages/_category/_subCategory/index.vue',
              name: 'category-subCategory'
            },
            {
              path: ':id',
              component: 'pages/_category/_subCategory/_id.vue',
              name: 'category-subCategory-id'
            }
          ]
        }
      ]
    }
  ]
}
6、未知路由
pages/
--| people/
-----| index.vue
--| _.vue    //localhost:3000、localhost:3000/people以外的路径,都会匹配到_.vue这一页面级路由组件
--| index.vue

//可用作错误页
7、命名视图
//使用<nuxt name="top"/>或<nuxt-child name="top"/>命名视图,需要先配置

//nuxt.config.js
export default {
  router: {
    extendRoutes(routes, resolve) {
      let index = routes.findIndex(route => route.name === 'main')
      routes[index] = {
        ...routes[index],
        components: {
          default: routes[index].component,
          top: resolve(__dirname, 'components/mainTop.vue')
        },
        chunkNames: {
          top: 'components/mainTop'
        }
      }
    }
  }
}
8、过渡效果
//全局过渡

//assets/main.css
.page-enter-active, .page-leave-active {
  transition: opacity .5s;
}
.page-enter, .page-leave-active {
  opacity: 0;
}

//nuxt.config.js
css: [
  'assets/main.css'
]


//局部过渡

//assets/test.css
.test-enter-active, .test-leave-active {
  transition: opacity .5s;
}
.test-enter, .test-leave-active {
  opacity: 0;
}

//nuxt.config.js
css: [
  'assets/test.css'
]

//test.vue
export default {
  transition: 'test'
}
9、中间件???????????????


二、视图

??????????????嵌套关系

1、模板
//根目录下,新建app.html

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

//插值表达式受配置文件控制

PS:新建app.html后,重启服务器,才有模板效果。

2、布局
//默认布局

//  layouts/default.vue
<template>
  <div>
    <nuxt/>    //page
  </div>
</template>


//自定义布局

//  layouts/myLayout.vue
<template>
  //div内,加入自定义内容
  <div>
    <nuxt/>
  </div>
</template>

//标识需要套用myLayout.vue的page组件
export default {
  layout: 'myLayout'
}


//错误布局(存放在layout目录的page)

//  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: 'myLayout' // 你可以为错误页面指定自定义的布局
}
</script>
4、页面

特殊配置项

名称 功能
asyncData 最重要的一个键, 支持异步数据处理,另外该方法的第一个参数为当前页面组件的上下文对象
fetch 与asyncData方法类似,用于在渲染页面之前获取数据填充应用的状态树(store)。不同的是fetch方法不会设置组件的数据
head 配置当前页面的 Meta 标签
layout 指定当前页面使用的布局(layouts根目录下的布局文件)
loading 如果设置为false,则阻止页面自动调用this.$nuxt.$loading.finish()和this.$nuxt.$loading.start()
transition 指定页面切换的过渡动效
scrollToTop 布尔值,默认false。 用于判定渲染页面前是否需要将当前页面滚动至顶部
validate 校验方法用于校验动态路由
middleware 指定页面的中间件,中间件会在页面渲染之前被调用
5、html头部
//nuxt.js使用vue-meta管理html头部

//nuxt.config.js
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' }
  ]
}

三、异步数据

1、asyncData方法

(1)触发时刻
asyncData方法会在组件(限于页面组件)每次加载之前被调用,它可以在服务端或路由更新之前被调用。

(2)案例

export default {
  //参数:当前页面的上下文对象
  async asyncData ({ params }) {
    let { data } = await axios.get(`https://my-api/posts/${params.id}`)
    return { title: data.title }
  }
}
2、上下文对象

(1)使用 req / res 对象

//服务器端调用asyncData
export default {
  async asyncData ({ req, res }) {
    // 请检查您是否在服务器端
    // 使用 req 和 res
    if (process.server) {
     return { host: req.headers.host }
    }

    return {}
  }
}

(2)访问动态路由数据

//访问路由对象的params
export default {
  async asyncData ({ params }) {
    return { params }
  }
}
3、错误处理
export default {
  asyncData ({ params, error }) {
    return axios.get(`https://my-api/posts/${params.id}`)
    .then((res) => {
      return { title: res.data.title }
    })
    .catch((e) => {
      error({ statusCode: 404, message: 'Post not found' })
    })
  }
}

四、插件

1、Vue插件
//vue插件使用前,必须做相应的配置

//nuxt.config.js
//plugins目录的vue插件
plugins: ['plugins/插件名']

//node_modules目录的vue插件
build: {
  transpile: ['插件名']
}
2、注入

(1)注入到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']
}

//example-component.vue
export default {
  mounted(){
    this.$myInjectedFunction('test')
  }
}

(2)注入到context

//  plugins/ctx-inject.js
export default ({ app }, inject) => {
  app.myInjectedFunction = (string) => console.log('Okay, another function', string)
}

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

//ctx-example-component.vue
export default {
  asyncData(context){
    context.app.myInjectedFunction('ctx!')
  }
}

(3)注入到Vue实例、context、Vuex

//  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']
}

//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)
  }
}
3、只在客户端使用的插件
//规定插件使用环境,客户端/服务器端

//nuxt.config.js
//旧版本
plugins: [
  { src: '~/plugins/both-sides.js' },
  { src: '~/plugins/client-only.js', ssr: 'false' },
  { src: '~/plugins/server-only.js', ssr: 'true' }
]

//Nuxt.js 2.4+
plugins: [
  { src: '~/plugins/both-sides.js' },
  { src: '~/plugins/client-only.js', mode: 'client' },
  { src: '~/plugins/server-only.js', mode: 'server' }
]

模块

介绍
Nuxt.js模块列表
基本模块
异步模块
常见模块


Vuex状态树

使用状态树
fetch方法
nuxtServerInit方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342