零基础上手nuxt

最近抽空看了一下nuxt觉着挺有意思,于是打算写一篇文章总结,顺便说一些遇到的一些问题

官方介绍

  • Nuxt.js 是一个基于 Vue.js 的通用应用框架。 通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI渲染。它的优点如下:
  • 基于 Vue.js
  • 自动代码分层
  • 服务端渲染
  • 强大的路由功能,支持异步数据
  • 静态文件服务
  • ES6/ES7 语法支持
  • 打包和压缩 JS 和 CSS
  • HTML头部标签管理
  • 本地开发支持热加载
  • 集成ESLint
  • 支持各种样式预处理器: SASS、LESS、 Stylus等等

安装

  • 如果没安装vue-cli,先安装cli
npm install vue-cli -g


  • 初始化项目
vue init nuxt/starter


  • 安装依赖
npm install


  • 启动服务
npm run dev


目录结构

  • 直接看结构
|-- .nuxt                            // Nuxt自动生成,临时的用于编辑的文件,build
|-- assets                           // 用于组织未编译的静态资源入LESS、SASS 或 JavaScript
|-- components                       // 用于自己编写的Vue组件,比如滚动组件,日历组件,分页组件
|-- layouts                          // 布局目录,用于组织应用的布局组件,不可更改。
|-- middleware                       // 用于存放中间件
|-- pages                            // 用于存放写的页面,我们主要的工作区域
|-- plugins                          // 用于存放JavaScript插件的地方
|-- static                           // 用于存放静态资源文件,比如图片
|-- store                            // 用于组织应用的Vuex 状态管理。
|-- .editorconfig                    // 开发工具格式配置
|-- .eslintrc.js                     // ESLint的配置文件,用于检查代码格式
|-- .gitignore                       // 配置git不上传的文件
|-- nuxt.config.json                 // 用于组织Nuxt.js应用的个性化配置,已覆盖默认配置
|-- package-lock.json                // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作
|-- package-lock.json                // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作
|-- package.json                     // npm包管理配置文件


常用配置

配置IP和端口

  • 只需在 /package.json 中,配置完成后npm run dev重启项目。
"config":{
    "nuxt":{
      "host":"127.0.0.1",
      "port":"1818"
    }
  },


配置全局CSS

  • 全局css几乎每个项目都需要初始化,这时候我们可以先在assets文件夹中新建一个css文件夹,放入初始化css的文件,例如base.css。然后打开nuxt.config.js,配置一下:
css:['~assets/css/base.css'],


配置webpack的loader

  • 在nuxt.config.js里是可以对webpack的基本配置进行覆盖的,比如现在我们要配置一个url-loader来进行小图片的64位打包。就可以在nuxt.config.js的build选项里进行配置。
build: {
    //多个就是loaders
    loader:[
      {
        test:/.(png|jpe?g|gif|svg)$/,
        loader:"url-loader",
        query:{
          limit:10000,
          name:'img/[name].[hash].[ext]'
        }
      }
    ],

    /*
    ** Run ESLint on save
    */
    extend (config, { isDev, isClient }) {
      if (isDev && isClient) {
        config.module.rules.push({
          enforce: 'pre',
          test: /.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/
        })
      }
    }
  }


nuxt路由

简单路由

  • pages中新建news.vueabout.vue,并且写入以下模版:
//news.vue
  <template>
    <div>
        <h2>News  page</h2>
        <ul>
          <li><a href="/">Home</a></li>
        </ul>
    </div>
  </template>

  //about
  <template>
    <div>
        <h2>about  page</h2>
        <ul>
          <li><a href="/">Home</a></li>
        </ul>
    </div>
  </template>


  • index.vue中加入a标签
<li><a href="/about">ABOUT</a></li>
  <li><a href="/news">NEWS</a></li>


  • 这时候可以发现这样写也没啥问题,但nuxt不提倡使用这种方式进行转跳,它也为我们提供了<nuxt-link>标签。

nuxt-link标签使用

  • 我们把之前的a标签替换成<nuxt-link>标签:
<nuxt-link :to="{name:'about'}">about</nuxt-link>
  <nuxt-link :to="{name:'news'}">NEWS</nuxt-link>


  • 也可以进行转跳,nuxt.js推荐我们使用<nuxt-link>进行页面之间的跳转。

参数传递

  • 在项目中经常会用到路由传参,在nuxt中我们可以使用params进行参数传递。直接看代码:
  • 在index.vue中给news加参数,传递一个newsId
<nuxt-link :to="{name:'news',params:{newsId:1234}}">NEWS</nuxt-link>


  • 然后在news.vue中通过$route.params接收一下参数:
<li>传递过来的id为:{{$route.params.newsId}}</li>


动态路由

  • 首先,先整理一下之前pages下的目录结构,我们新建立一个news文件夹,然后把之前创建的news.vue移入进去,改名字为index.vue,接着在这个文件夹中建立_id.vue文件,并且编辑模版如下:
<template>
    <div>
        <h2>新闻详情页面id为:[{{$route.params.id}}]</h2>
        <ul>
          <li><a href="/">Home</a></li>
        </ul>
    </div>
  </template>


  • news文件夹下的index.vue中加入转跳:
<li><a href="/news/123">新闻1</a></li>
  <li><a href="/news/456">新闻2</a></li>


  • 这样动态路由就好了,在Nuxt.js里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue文件或目录。

路由参数校验

  • 进入一个页面,对参数传递的正确性校验是必须的,可以使用nuxt为我们提供的校验方法validate()。在上面创建的_id.vue加入校眼:
export default {
  validate ({ params }) {
    // Must be a number
    return /^d+$/.test(params.id)
  }
}


  • 我们使用了validate方法,并把params传递进去,然后用正则进行了校验,如果正则返回了true正常进入页面,如果返回false进入404页面。这里如果我们参数传递一个中文进去,就会进入到404页面。

错误页面配置

  • 我们可以在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>


  • 接着在news文件夹下的index.vue中加入一个错误转跳:
<li><a href="/news/你好">错误转跳</a></li>


  • 这时候点击过去,就会跳转到错误页面。

过渡动画

  • 路由的动画效果,也叫作页面的更换效果。Nuxt.js提供两种方法为路由提供动画效果,一种是全局的,一种是针对单独页面制作。

全局路由动画

  • 我们在/assets/css文件夹中创建main.css,加入以下css:
.page-enter-active, .page-leave-active {
      transition: opacity 1s;
  }
  .page-enter, .page-leave-active {
      opacity: 0;
  }


  • 然后在nuxt.config.js中加入全局css:
css:['~assets/css/base.css','~assets/css/main.css'],


  • 这时候页面转跳就会有了1秒的过渡动画,但我们进入about页面中,点击返回却发现没有这个效果,因为返回home我们是用的a标签进行转跳的,这时候我们可以改成<nuxt-link>转跳:
<nuxt-link :to="{name:'index'}">返回首页</nuxt-link>


  • 同样,之前的转跳到新闻详情页面也可以改一下:
<li><nuxt-link :to="{name:'news-id',params:{id:123}}">新闻1</nuxt-link></li>
  <li><nuxt-link :to="{name:'news-id',params:{id:123}}">新闻2</nuxt-link></li>


局部动画

  • 如果想加个字体先放大后缩小的效果,在之前的main.css文件中加入:
.test-enter-active, .test-leave-active {
    transition: all 2s;
    font-size:12px;
}
.test-enter, .test-leave-active {
    opacity: 0;
    font-size:40px;
}


  • 然后在about.vue中设置:
export default {
    transition:'test'
  }


  • 这时候就是单个页面有动画效果了,更多请看官网api:transition API

默认模版和默认布局

  • 平时开发时候,有很多公共元素,我们可以把它做成组件,或者就是修改模版,nuxt中也提供了模版修改。

默认模版

  • 直接在根目录下创建app.html,然后编辑一下:
<!DOCTYPE html>
  <html lang="en">
  <head>
    {{HEAD}}
  </head>
  <body>
      <h1 style="text-align: center;">默认模版就是这样</h6>
      {{APP}}
  </body>
  </html>


  • 其中HEAD就是nuxt.config.js中配置的head信息,必须大写,APP就是/pages/下的主体文件。
  • 重新启动服务才可以生效。

默认布局

  • 默认布局与默认模版类似,默认布局主要针对于页面的统一布局使用,在layouts/default.vue中可以进行修改,比如,我们加点东西看一下:
<template>
    <div>
      <p>LonJin</p>
      <nuxt/>
    </div>
  </template>


  • 再看一下其他页面,页面中出现了我们输入的内容。

个性meta设置

  • 很多时候,网站某些meta并不少统一的,比如新闻页面,可能需要单独设置一下方便搜索引擎抓取。拿新闻页面举例子,打开之前的新闻列表页面,参数再多加一个title
<li><nuxt-link :to="{name:'news-id',params:{id:123,title:'这是一篇新闻'}}">新闻2</nuxt-link></li>


  • 然后在/pages/news/_id.vue中接收一下:
data(){
    return{
      title:this.$route.params.title,
    }
  },
  //独立设置head信息
  head(){
      return{
        title:this.title,
        meta:[
          {hid:'description',name:'news',content:'This is news page'}
        ]
      }
    }


asyncData获取数据

  • 首先安装axiosproxy
npm install axios --save
  npm i @nuxtjs/proxy -D


  • 然后在/nuxt.config.js中配一下接口代理,因为我使用的是https://api.binstd.com/这个网站的api,所以要进行接口代理。
modules: [
    '@nuxtjs/axios',
    '@nuxtjs/proxy'
  ],
  axios: {
    proxy: true,
    prefix: '/api', // it only work when proxy is enabled
    credentials: true,
  },
  proxy: {
    '/api': {
      target: 'https://api.binstd.com',
      changeOrigin : true,
      secure: true,
      pathRewrite: {
        '^/api' : ''
      }
    }
  },


  • 然后在/pages/news/index.vue里面测试一下接口:
import axios from 'axios'
export default {
  data(){
    return{

    }
  },
  async asyncData () {
    let { data } = await axios.get('/api/recipe/class?appkey=xxx')
    console.log(data)
    return { info: data }
  },
}


  • 然后送首页进入到这页面,没有什么问题,数据正常拿到


nuxt3能用nginx部署吗_css


  • 但是再刷新一下,就会报错:connect ECONNREFUSED 127.0.0.1:80 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1113:14)


nuxt3能用nginx部署吗_ios_02


  • 我发现如果页面没有使用async asyncData方法去请求后台地址刷新页面就没问题,如果使用了该方法去请求后台刷新页面就报上面的异常,看了网上一些回答,我一直怀疑我的代理配置的有问题,还有说请求接口的时候让域名+端口+api进行访问。但我进行了代理,讲道理不应该出现这种问题。
  • 最后我是通过配置package.jsonconfig解决的。
"config": {
    "nuxt": {
      "host": "0.0.0.0",
      "port": "80"
    }
  }


静态资源

  • 静态资源引用需要注意要使用~符号,这个符号代表根目录,在css中引入同理
<div><img src="~static/lonjin.png" /></div>
.box{
    width: 300px;
    height: 100px;
    background-image: url('~static/lonjin.png')
  }


打包上线

  • 只需输入一行命令即可:
npm run generate


总结

总体来说, nuxt还是很不错的,但是文档感觉不怎么样,在处理跨域时候遇到的第二次刷新页面返回的报错,查了半天资料,一直以为是配置的代理有问题导致的,后来才发现是修改 package.jsonconfig。本人也是尝试的看了一下nuxt,并没有太过深入的应用过 nuxt.js,如果不对,欢迎指正!