前端学习篇 -- Nuxt 学习

1、Nuxt.js 简介

主要用来做 SSR(服务端渲染),vue 的 SPA(单页应用)对搜索引擎是不友好的(抓取不了),如 新闻类网站主要流量来自搜索引擎

1.1 SSR

在服务器端把 .vue文件渲染成html 返回给浏览器

**优点:**对 SEO 支持非常友好、比 SPA 渲染速度更快

1.2 特点

  • 基于 Vue.js
  • 自动代码分层
  • 服务端渲染
  • 强大的路由功能,支持异步数据
  • 静态文件服务
  • ES6/ES7 语法支持
  • 打包和压缩 JS 和 CSS
  • HTML头部标签管理
  • 本地开发支持热加载
  • 集成ESLint
  • 支持各种样式预处理器: SASS、LESS、 Stylus等等

1.3 与 thymeleafevue.js的区别

  • thymeleafe

这种属于模版引擎类型,也就是把数据跟html结合到一起。展示给用户看。可以在服务端完成渲染,也可以在客户端通过JS完成异步渲染

优点:有利于SEO,源码也很规整

缺点:不能前后端分离开发,前端人员写好了样式和html,交给后台开发人员整合到web中

  • vue.js

优点:客户端渲染,减少服务端的性能开支;可以前后端分离开发,相互独立,提高开发效率和有利于项目管理。数据双向绑定,渲染非常方便

缺点:不利于SEO 应用场景:一般开发管理后台

  • nuxt.js

基于vue.js的一个框架。它支持服务端渲染,也支持客户端渲染。这样子就解决了vue.js的seo问题了

优点:有利于seo优化,可以前后端分离开发

缺点:需要占用较多的服务端资源,高并发访问。优化思路:可以做一些缓存处理,或者可以根据用户登录状态判断,没登录的服务端渲染,登录了客户端渲染,可以减轻一下服务器的负担

2、使用

2.1 安装

# npx(npx 在 NPM 版本 5.2.0 默认安装了)
npx create-nuxt-app <项目名>

2.2 目录结构

├─nuxt-demo
|     ├─.editorconfig    -- 默认规则 
|     ├─.gitignore
|     ├─.prettierrc
|     ├─nuxt.config.js   -- 组织 Nuxt.js 应用的个性化配置
|     ├─package.json
|     ├─README.md
|     ├─store            -- 状态管理
|     ├─static           -- 静态资源(打包后是原样)
|     ├─plugins          -- 插件目录
|     ├─pages            -- 页面目录
|     ├─middleware       -- 中间件目录
|     ├─layouts          -- 布局目录
|     ├─components       -- 组件目录
|     ├─assets           -- 资源目录

2.3 配置

2.3.1 配置主机端口
// package.json
"config": {
    
    
  "nuxt": {
    
    
    "host": "127.0.0.1", // 可以选自己的域名
    "port": "8080"       // 改端口
  }
}
2.3.2 配置全局css
// nuxt.config.js
module.exports = {
    
    
  css: [
    // 项目里要用的 CSS 文件
    '@/assets/css/main.css',
    // 项目里要使用的 SCSS 文件
    '@/assets/css/main.scss'
  ]
}
2.3.3 webpack 配置

build选项中进行相关配置

// nuxt.config.js
module.exports = {
    
    
  build: {
    
    
  }
}
2.3.4 配置代理
  1. 安装

    npm install @nuxtjs/proxy
    
  2. nuxt.config.js 中添加配置:

    modules: [
      '@nuxtjs/proxy'
    ],
    
    axios: {
          
          
      proxy: true,        // 开启 axios 代理
      prefix: '/union',   // 请求前缀
      credentials: true   // 开启验证
    },
    
    proxy: {
          
          
      '/union': {
          
          
        target: 'https://api.sunofbeach.net/shop',
        pathRewrite: {
          
          
          changeOrigin: true, // target 是域名,需设置为true
          '^/union': ''
        }
      }
    }
    

2.4 路由

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

2.4.1 基础路由

假设 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'
    }
  ]
}
2.4.2 nuxt-link 标签

与 router-link 使用方法一致,最终渲染成 a标签

<template>
  <nuxt-link to="/">首页</nuxt-link>
  <nuxt-link to="/about">关于</nuxt-link>
  <nuxt-link to="/news">新闻</nuxt-link>
</template>
2.4.3 动态路由传参

带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录

pages/
--| news/
-----| _id.vue
--| index.vue

# 路由配置表
{
    
    
  name: 'news-id',
  path: '/news/:id?',
  component: 'pages/news/_id.vue'
}
query拿参(参数名可以改)
// index.vue
<li><nuxt-link :to="{path: '/news', query: {newsId: 3306}}">新闻</nuxt-link></li>
  
// news/_id.vue
<p>newsId:{
    
    {
    
     $route.query.newsId }}</p>
params拿参
// index.vue
<li><nuxt-link :to="'/news/lisi'">新闻</nuxt-link></li>

// news/_id.vue
<p>newsId:{
    
    {
    
     $route.params.id }}</p>
2.4.4 路由过渡动效

Nuxt.js 默认使用的过渡效果名称为 page , 在全局样式文件 assets/main.css 里添加一下样式:

.page-enter-active,
.page-leave-active {
    
    
  transition: opacity 0.5s;
}
.page-enter,
.page-leave-active {
    
    
  opacity: 0;
}

某个页面过渡:

// main.css
.test-enter-active,
.test-leave-active {
    
    
  transition: opacity 0.5s;
}
.test-enter,
.test-leave-active {
    
    
  opacity: 0;
}
// 需要过渡效果的页面配置
export default {
    
    
  transition: 'test'
}

2.5 视图

2.5.1 定制模板

定制化默认的 html 模板

  1. 在 src 文件夹下(默认是应用根目录)创建一个 app.html 的文件
  2. 或者在 .nuxt/views/app.template.html配置

注意:需要重启服务器

<!-- {
    
    { HEAD }} 是 nuxt.config.js 配好的头部 -->
<!DOCTYPE html>
<html>
  <head>
    {
   
   { HEAD }}
  </head>
  <body>
    <p>这是一个寂寞的天 -- app.html</p>
    {
   
   { APP }}
  </body>
</html>
2.5.2 定制布局
默认布局

通过编辑 layouts/default.vue 文件来扩展应用的默认布局,一般都是定制默认布局

<!-- layouts/default.vue -->
<template>
  <p>这是一个寂寞的天 -- layouts</p>
  <nuxt /> <!-- 被默认布局包裹的组件 -->
</template>

<script>
// 渲染结果:
/*  
 * 这是一个寂寞的天 -- app.html  -> 定制模板
 * 这是一个寂寞的天 -- layouts   -> 默认布局
 * 路由出口
 */
</script>

自定义布局

可以覆盖默认布局,但不能覆盖定制模板

<!-- layouts/blog.vue -->
<template>
  <div>
    <div>我的博客导航栏在这里</div>
    <nuxt />
  </div>
</template>
// pages/blog.vue
export default {
    
    
  layout: 'blog',
  // 或
  layout(context) {
    
    
    return 'blog'
  }
}

pages/blog.vue会使用 layouts/blog.vue 作为当前页面组件的布局文件

2.5.3 定制错误页

通过添加layouts/error.vue 文件来扩展应用的错误请求页

<!-- layouts/error.vue -->
<template>
   <div class="container">
    <h1>应用发生错误异常</h1>
    <nuxt-link to="/">首 页</nuxt-link>
  </div>
</template>

2.6 资源文件

2.6.1 Webpack 构建

所有的资源 URL 例如 img src="..."> background: url(...) 和 CSS 中的 @import 均会被解析成模块通过 require 引用

目录结构:

-| assets/
----| image.png
-| pages/
----| index.vue

使用 url('~assets/image.png'), 那么编译后它将被转换成 require('~/assets/image.png')

2.6.2 静态文件
  1. 静态资源文件需要 Webpack 做构建编译处理,可以放到 assets 目录
  2. 不需要 Webpack 做构建可以放到 static 目录中去
<!-- 引用 static 目录下的图片 -->
<img src="/my-image.png" />

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

2.7 Vuex 状态树

自动找到 src 目录下的 store 目录引用 vuex

Nuxt.js 支持两种使用 store 的方式 :

  1. 模块方式: store 目录下的每个 .js 文件会被转换成为状态树指定命名的子模块 (当然,index 是根模块)
// store/state.js
export default () => ({
    
    
  counter: 0
})

// store/mutations.js
export default {
    
    
  increment(state) {
    
    
    state.counter++
  }
}
  1. Classic(不建议使用): store/index.js返回创建 Vuex.Store 实例的方法
// store/index.js
export const state = () => ({
    
    
  counter: 0
})

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

// store/todos.js 模块文件(moudles)
export const state = () => ({
    
    
  list: []
})

// todo.vue 访问 todos.js 里的 state
this.$store.state.todos.list

无论使用那种模式,state的值应该始终是function,为了避免返回引用类型,会导致多个实例相互影响

2.8 配置环境变量

  1. 根目录下新建env.js文件

    // env.js
    module.exports = {
          
          
      dev: {
          
          
        MODE: 'development',
        ENV_API: 'http://xxxxxxxx:8000'   //测试服务器地址
      },
      prod: {
          
          
        MODE: 'production',
        ENV_API: 'https://xxxxxxxxx'  // 正式服务器地址
      }
    }
    
  2. nuxt.config.js 配置

    // nuxt.config.js
    import env from './env'
    export default {
          
          
      env: {
          
          
        BASE_URL: env[process.env.MODE].ENV_API
      }
    }
    
  3. package.json 修改

    // package.json
    "scripts": {
          
          
      "dev": "cross-env MODE=dev nuxt",
      "build": "cross-env MODE=prod nuxt build",
      "start": "nuxt start",
      "generate": "nuxt generate"
    }
    
  4. 使用

    console.log(process.env.BASE_URL)
    

3、API

3.1 validate 动态路由校验

如果校验方法返回的值不为 true, Nuxt.js 将自动加载显示 404 错误页面

// index.vue
<li><nuxt-link :to="'/news/123'">新闻</nuxt-link></li>

// news/_id.vue
<p>newsId:{
   
   { $route.params.id }}</p>

export default {
  validate({ params }) {
    // 参数必须是数字(出现1次或以上)
    return /^\d+$/.test(params.id)
  }
}

3.2 transition 路由过渡动效

默认值:

{
    
    
  name: 'page',
  mode: 'out-in'
}

指定页面过渡:

export default {
    
    
  layoutTransition: 'layout'
  // or
  transition: {
    
    
    name: 'layout',
    mode: 'out-in'
  }
}
// 全局 CSS
.layout-enter-active,
.layout-leave-active {
    
    
  transition: opacity 0.5s;
}
.layout-enter,
.layout-leave-active {
    
    
  opacity: 0;
}

3.3 asyncData 组件加载前调用

能够在渲染组件之前异步获取数据 ,内部无法使用this获取组件实例asyncData是在组件加载之前被调用

类型: Function

  • 第一个参数被设定为当前页面的上下文对象
<li>{
    
    {
    
     project }}</li>
<p>{
    
    {
    
     info }}</p>
export default {
    
    
  data() {
    
    
    return {
    
     project: 'default' }
  },
  asyncData(context) {
    
    
    return {
    
     project: 'nuxt' }
    // return { info: 'about' }
  }
}
// nuxt
// about

3.4 layout 布局

export default {
    
    
  layout: 'blog',
  // 或
  layout(context) {
    
    
    return 'blog'
  }
}

Nuxt.js 会使用 layouts/blog.vue 作为当前页面组件的布局文件

3.5 head 设置头部

设置当前页面的头部标签 , 可通过 this 关键字来获取组件的数据,可以利用页面组件的数据来设置个性化的 meta 标签

export default {
    
    
  data() {
    
    
    return {
    
    
      title: 'Hello World!'
    }
  },
  head() {
    
    
    return {
    
    
      title: this.title,
      meta: [
        {
    
    
          hid: 'description',
          name: 'description',
          content: 'My custom description'
        }
      ]
    }
  }
}

hid: 为了避免子组件中的 meta 标签不能正确覆盖父组件中相同的标签而产生重复的现象,建议利用 hid 键为 meta 标签配一个唯一的标识编号

content: 描述信息

3.6 fetch 组件加载前调用

fetch 方法的第一个参数是页面组件的上下文对象context, 与asyncData方法类似,不同的是fetch 不会设置组件的数据

注意:内部无法使用this获取组件实例fetch是在组件初始化之前被调用

获取异步信息

export default {
  async fetch({ store, params }) {
    let { data } = await axios.get('http://my-api/stars')
    store.commit('setStars', data)
  }
}

4、安装第三方插件

  1. 下包

    npm i element-ui -S
    
  2. 导包

    // plugins 目录下新建 element.js
    import Vue from 'vue'
    import ElementUI from 'element-ui'
    
    Vue.use(ElementUI)
    
  3. 配置

    // nuxt.config.js
    css: [
      'element-ui/lib/theme-chalk/index.css'
    ],
    plugins: [
      {
          
          
        src: '~plugins/element',
        ssr: true
      }
    ],
    
  4. 用包

    <el-button>默认按钮</el-button>
    <el-button type="primary">主要按钮</el-button>
    

猜你喜欢

转载自blog.csdn.net/weixin_44257930/article/details/109068356
今日推荐