Nuxt.js项目开发

最近小编新接手了两个项目,这两个项目均是使用nuxt.js框架进行开发的,这对小编来说又是一个新的大陆,故而和各位小伙伴们絮叨絮叨这个东西。
首先先说明一下这个东西是个啥。
Nuxt.js 是一个基于 Vue.js 的通用应用框架,如同Next.js之于React一样(Next.js 是一个轻量级的 React 服务端渲染应用框架)
通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI渲染。
Nuxt.js 预设了利用Vue.js开发服务端渲染的应用所需要的各种配置。
小编的个人看法是,nuxt.js相对于vue而言确实便捷一些。
创建:npx create-nuxt-app 项目名 (npx在安装npm的时候已经安装,因此不用担心,直接使用就好)
创建
各项配置的选择:
在这里插入图片描述
在这里插入图片描述
这些配置如果没有有特殊需要的话,直接按回车键就好,如果前两项需要填写也可以进行填写,第三项是使用nuxt默认的服务器端框架。
创建成功之后,是需要进入的文件夹中还是可以直接进行运行均会有提示,按照提示操作即可,之后打开提供的链接进行访问即可。

1、路由
①一般路由
在vue中,路由的跳转使用的是vue-router,路由的跳转需要开发人员自己进行编写配置,nuxt.js不需要自行编写,它会根据开发者page文件夹下的结构自动生成路由配置。
假设 pages 的目录结构如下:

pages/
--| user/
-----| index.vue
-----| one.vue
--| index.vue

那么,Nuxt.js 自动生成的路由配置如下:

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

②子路由
在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录。如果想生成的路由为二级(/index/1)、三级(/index/1/2)或是更多级,以及需要url后添加id等皆可使用子路由实现。
目录结构:

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

Nuxt.js 生成对应的路由配置表为

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
   {
      name: 'users',
      path: '/users/:id?',//url为/users/id
      component: 'pages/users/_id.vue'
   }
}

注:_id.vue中可以什么都不写

nuxt.js中还有其他的路由,在此我就不一一介绍了,毕竟除了以上的两种,其他的路由小编在此次项目中并没有使用到,了解的不是很多,故而就不在这里多说了,有兴趣或是需要的小伙伴可以自行到官网中了解。

2、asyncData
①在组件(限于页面组件)每次加载之前被调用。返回的数据融合组件 data 方法返回的数据一并返回给当前组件。
②例子1.get请求:let [request1Data] = await Promise.all([ axios.get(url1), axios.get(url2), ])
例子2:post请求,如果post请求的参数传递和get请求一样是直接使用?连接在url后边的话便可使用
let [request1Data] = await Promise.all([ axios.postForm(url1), axios.postForm(url2), ])

 注:请求的函数,例如get和postForm可以自行封装在一个js中,小编封装的js函数是http.js,并把它放在plugins文件夹下。
 http.js

import axios from ‘axios’;
import qs from ‘qs’;
import config from ‘…/conf/config.service’;
// 超时时间
// axios.defaults.timeout = 5000
axios.defaults.headers.post[‘Content-Type’] = ‘application/x-www-form-urlencoded;’;
// response.addHeader( “Cache-Control”, “no-cache” );
axios.defaults.headers[‘Cache-Control’] = “no-cache”;
axios.defaults.withCredentials = true;
axios.defaults.baseUrl = config.proxyUrl;
axios.postByQs = function (url, data) {
return axios.post(url, qs.stringify(data), {
headers: {
‘Content-Type’: ‘application/x-www-form-urlencoded’,
‘Cache-Control’: ‘no-cache’,
}
})
}
axios.GET = function (url) {
return axios.get(url, {
headers: {
‘Cache-Control’: ‘no-cache’,
}
})
}
axios.postForm = function (url, data) {
return axios.post(url, data, {
headers: {
‘Content-Type’: false,
‘Cache-Control’: ‘no-cache’,
}
})
}

axios.postFile = function (url, data) {
return axios.post(url, data, {
headers: {
‘Content-Type’: ‘multipart/form-data’,
‘Cache-Control’: ‘no-cache’
}
})
}
axios.interceptors.response.use(
response => {
if (response.data.status == 401) {
window.location.hash = ‘login’;
window.location.reload()
}
return response;
},
error => {
return Promise.reject(error.response.data) // 返回接口返回的错误信息
});
export default axios

③使用asyncData获取数据可以更好的进行SEO优化。但若该页面的数据是随时改变的,小编不建议该页面使用此方法,因为数据随时的改动,今日收录的数据对于明日来说并没有多大的用处。所以小编推荐,当确认该页面显示的数据并不是时时更新再使用此方法。使用此方法获取数据时,只有数据获取成功并完成后客户端才会显示并进行渲染,否则,页面将一直处于加载状态。
3、关于plugins文件夹
plugins文件夹为插件目录,顾名思义,是用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。这么说也比较模糊,在此和大家举个例子吧。比如,在此次项目中,小编要用到swiper插件,于是到npm中找到了vue-awesome-swiper插件。通过npm安装依赖成功之后,并不能够直接使用,需要进行以下几个步骤:
①在plugins文件夹中新建js文件,例如取名为swiper.js。此js文件是说明该项目使用vue-awesome-swiper/dist/ssr插件。
swiper.js:

import Vue from 'vue'

export default () => {
  if (process.browser) {
    //console.log('浏览器端渲染');
    Vue.use(require('vue-awesome-swiper/dist/ssr'), /* { default global options } */)
  }else{
    //console.log("非浏览器端渲染");
  }
}

②到nuxt.config.js文件中添加

....
  plugins: [
    {src:'@/plugins/swiper.js',ssr:false}
  ]
  ....

③通过以上两步,该插件才叫做可以使用了。在components文件夹中新建文件,例如:slider.vue。
slider.vue:

<template>
  <div class="swiper_container swiper-no-swiping">
    <div class="swiper_wrapper_content">
      <no-ssr>
        <div v-swiper:mySwiper="swiperOption" @someSwiperEvent="swiperEvent" class="swiper_wrapper_content_con">
          <div class="swiper-wrapper">
            <div class="swiper-slide img1"><span></span></div>
          </div>
<!--          <div class="swiper-pagination"></div>-->
        </div>
      </no-ssr>
    </div>
  </div>
</template>

<script>
  export default {
    name: '',
    layout: 'welcomeIndex',
    data() {
      return {
        swiperOption: {
          pagination: {
            el: '.swiper-pagination',
            clickable: false
          },
          autoplay: {
            delay: 5000,
          },
          effect: 'slide',
          paginationClickable: true,
          speed: 800,
          loop:true,
          observer: true,
          observeParents: true,
          autoplayDisableOnInteraction: false
        }
      }
    },
    computed: {},
    created() {
         },
    mounted() {

    },
    methods: {
    
    }
  }
</script>

<style lang="scss" scoped>
  .swiper_container{
    width: 100%;
    height: 100%;
    .swiper_wrapper_content{
      width: 100%;
      height: 100%;
      .swiper_wrapper_content_con{
        width: 100%;
        height: 100%;
        .swiper-wrapper{
          width: 100%;
          height: 100%;
          .swiper-slide {
            width: 100%;
            height: 100%;
            span {
              width: 100%;
              height: 100%;
              display: inline-block;
              background-color: #00dad7;
              background: url("../static/images/banner/banner1.jpg") no-repeat top center;
            }
          }
          img{
            width: 100%;
            height: 100%;
          }
        }
      }
    }
  }

</style>

在此,小编将轮播图作为背景图是为了适配,防止图片由于屏幕大小、分辨率问题导致图片变形。
④在页面中使用该组件

<template>
  <div class="container">
    <div class="banner">
      <Slider></Slider>
    </div>
  </div>
</template>

<script>
  import Slider from "~/components/slider.vue"
  export default {
	  name:"index",
	  data() {
		  return{
		  }
	  },
	  components: {
	    Slider,
	  },
 }
 </script>

注:引入bootstrap、jq等插件时,小编不推荐直接在页面中的head里直接引用,即最好不要使用以下方式引用

<script>
export default {
	data(){
		return{
		}
	},
	head(){
      return {
        title: '',
        meta: [
          { hid: 'description', name: 'description', content: '' },
          { hid: 'keywords', name: 'keywords', content: '' }
        ],
        srcipt:[
        	{src:'xxxxx.js'}
        ]
      }
    },
}
</script>

温馨提示:
1、若想使用asyncData进行异步获取数据,页面的跳转建议不使用nuxt-router,若使用nuxt-router进行路由跳转,当用户点击浏览器返回箭头时会报错,需要进行手动刷新。当页面停留时间过长,进行刷新时也会报错,这时建议在使用asyncData前先判断是否是服务端渲染,若是服务端则再进行数据的请求,这样就不会出现以上问题。
2、使用asyncData异步获取数据时,除了return所需的数据字段,不要在其他的地方使用return,否则会导致数据无法正常返回而造成数据渲染显示异常。
3、若项目中使用element-ui的NavMenu组件,循环渲染el-dropdown-item标签时,不要使用v-text进行数据渲染,页面会报虚拟DOM的警告,虽然只是警告,但作为一名合格的程序员,控制台报红都是分分钟刺眼的事。

官方文档:https://zh.nuxtjs.org/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章