Nuxt简述

3,752 阅读5分钟
为什么使用nuxt.js?

vue单页面应用渲染是从服务器获取所需js,在客户端将其解析生成html挂载于 id为app的DOM元素上,这样会存在两大问题。

  1. 由于资源请求量大,造成网站首屏加载缓慢,不利于用户体验。

  2. 由于页面内容通过js插入,对于内容性网站来说,搜索引擎无法抓取网站内容,不利于SEO。 Nuxt.js 是一个基于Vue.js的通用应用框架,预设了利用Vue.js开发服务端渲染的应用所需要的各种配置。可以将html在服务端渲染,合成完整的html文件再输出到浏览器。

除此之外,nuxt与vue还有一些其他方面的区别。

  1. 路由 nuxt按照 pages 文件夹的目录结构自动生成路由 vue需在 src/router/index.js 手动配置路由

  2. 入口页面 nuxt页面入口为 layouts/default.vue vue页面入口为 src/App.vue

  3. webpack配置 nuxt内置webpack,允许根据服务端需求,在 nuxt.config.js 中的build属性自定义构建webpack的配置,覆盖默认配置 vue关于webpack的配置存放在build文件夹下

下图为关于nuxt的简单概述

nuxt是关于服务端渲染的,如若想让组件在客户端渲染,可以使用 <no-ssr></no-ssr>将其包裹起来(该标签最多只能包含一个子组件/元素)。 这样在未获取到内容时,页面先采用 <divclass="no-ssr-placeholder"data-v-2a183b29=""></div>占位,然后将获取到的html覆盖该占位

安装sass

    npm i node-sass sass-loader scss-loader --save-dev

vue文件中可直接使用

    <style lang="scss" scoped>

    </style>

sass文件如需解析,nuxt.config.js中配置css属性

    css: [

       {

         src: '~/assets/style/reset.scss',

         lang: 'scss'

       }

    ],

使用axios并跨域
  1. package.json npm install @nuxtjs/ proxy  nuxt 项目默认安装axios, 所以只需安装proxy即可

    "dependencies": {

       "@nuxtjs/axios": "^5.0.0",

       "@nuxtjs/proxy": "^1.2.4",

    }

  1. nuxt.config.js

    modules: [

       '@nuxtjs/axios',

       '@nuxtjs/proxy'

     ],

     proxy: {

       '/api': {

         target: 'http:www.xxx.com',

         changeOrigin: true,

         pathRewrite: {

           '^/api ': ''

         }

       }

     },

  1. index.vue

    import axios from 'axios'

    export default {

       data () {

           return {

             page: 0

           }

       },

       async asyncData () {

           let data = await axios.get('http://localhost:3000/api/admin/list')

           return {

             page: data.data.page

           }

     },

    }

注意采用 importaxiosfrom'axios' 方式引入axios时,接口参数前须加baseURL -> http://localhost:3000 如果采取 axios.get('/api/admin/game') 调用接口返回nuxt服务器错误,如下图

封装axios,解决每个请求前加baseURL plugins/axios.js

    import * as axios from 'axios'

    let options = {}

    // The server-side needs a full url to works

    if (process.server) {

     options.baseURL = `http://${process.env.HOST || 'localhost'}:${process.env.PORT || 3000}`

    }

    export default axios.create(options)

index.vue

    import axios from '~/plugins/axios'

    axios.get('/api/admin/game')

引入第三方插件(vue-awesome-swiper)
  1. npm install vue-awesome-swiper--save

  2. plugins文件夹下新建awesome-swiper.js

    import Vue from 'vue'

    import VueAwesomeSwiper from 'vue-awesome-swiper/dist/ssr'

    Vue.use(VueAwesomeSwiper)

  1. nuxt.config.js引入css及js

    css: [

       'swiper/dist/css/swiper.css',

    ],

    plugins: [

       { src: "~/plugins/awesome-swiper.js", ssr: false },

    ],

  1. 页面初始化

    <div v-swiper:mySwiper="swiperOption">

       <div class="swiper-wrapper">

            <div class="swiper-slide" v-for="(banner, index) in banners" :key="index">

               <img :src="banner">

            </div>

       </div>

       <div class="swiper-pagination swiper-pagination-bullets"></div>

    </div>

    export default {

     data () {

       return {

         banners: [

           require('~/assets/img/1540892214119.jpg'),

           require('~/assets/img/1540892214119.jpg'),

           require('~/assets/img/1540892214119.jpg')

         ],

         swiperOption: {

           autoplay: true,

           loop: true,

           pagination: {

             el: '.swiper-pagination',

           },

         }

       }

     },

    }

引入第三方模块(moment.js)
  1. npm install moment --save

  2. vue页面

    import moment from 'moment'

    export default {

       mounted() {

         moment.locale('zh-cn') // moment.js 默认为英文,可通过此方法设置中文

         console.log(moment().format('dddd')) // 星期三

       },

    }

为避免每个页面都引入moment,执行 moment.locale('zh-cn'),可将其定义为全局方法

  1. 在plugins文件夹下新建common.js

    import Vue from 'vue'

    import moment from 'moment'

    let common = {

     install (Vue) {

       Vue.prototype.$op = {

         'moment': (date) => {

           let newMoment = new moment(date)

           newMoment.locale('zh-cn')

           return newMoment

         }

       }

     }

    }

    Vue.use(common)

  1. nuxt.config.js

    plugins: [

       { src: '~/plugins/common.js', ssr: false },

    ],

  1. vue页面

    this.$op.moment().format('dddd')

修改网站icon

icon.png文件存放在static文件夹下,nuxt.config.js中配置head属性

    head: {

       link: [

         { rel: 'icon', type: 'image/png', href: '/icon.png' }

       ]

     },

关于中间件

中间件存放于middleware文件夹下,按使用场景可分为全局中间件和单页面中间件

    //全局使用

    module.exports = {

     router: {

       middleware: '中间件名称'

     }  

    }

    //页面单独使用

    export default {

       middleware: '中间件名称'

    }

中间件执行流程顺序: nuxt.config.js -> 匹配布局 -> 匹配页面

PS.关于查看NUXT 官网插件demo时遇到的问题

按照index.vue通过 require('mini-toastr')引入miniToastr,运行程序报错如下

打印miniToastr发现为一Module对象,init挂载在其default属性上

所以修改引入方法为

    miniToastr = require('mini-toastr').default

为什么需要require().default

When using ES6 imports (export default HeaderBar), the exported module is of the format {"default" : HeaderBar}. The import statement handles this assignment for you, however, you have to do the require("./mycomponent").default conversion yourself. The HMR interface code cannot use import as it doesn't work inline.

If you want to avoid that, use module.exports instead of export default.

关于如上介绍,测试关于两种模块的导出方法 方式一:export default 新建test.js文件

    export default {

     test: function () {

       console.log('test')

     }

    }

vue页面导入

    let obj = require('~/plugins/con.js').default

    obj.test() // 打印‘test’

    let obj = require('~/plugins/con.js')

    obj.default.test() // 打印‘test’

此时 require('~/plugins/con.js') 打印

方式二:module.exports

    const obj = {

     test: function () {

       console.log('test')

     }

    }

    module.exports = obj

    let obj = require('~/plugins/con.js')

    obj.test() // 打印‘test’

此时 require('~/plugins/con.js') 打印为

最后:感谢 点思的May小姐姐提供的干货文章~

识别二维码,关注我们

点思成今

研发服务|顾问服务|测试服务