一篇文章带你快速入门 Nuxt.js 服务端渲染

在这里插入图片描述

1. Nuxt.js 概述

1.1 我们一起做过的SPA

  • SPA(single page web application)单页 Web 应用,Web 不再是一张张页面,而是一个整体的应用,一个由路由系统、数据系统、页面(组件)系统等等,组成的应用程序。

  • 我们之前学习的Vue就是SPA中的佼佼者。

  • SPA 应用广泛用于对SEO要求不高的场景中

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.2 什么是SEO

  • SEO:搜索引擎优化(Search Engine Optimization), 通过各种技术(手段)来确保,我们的Web内容被搜索引擎最大化收录,最大化提高权重,最终带来更多流量。

  • 非常明显,SPA程序不利于SEO

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • SEO解决方案:提前将页面和数据进行整合

    • 前端:采用SSR
  • 后端:页面静态化 (freemarker 、thymeleaf、velocity)

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.3 什么是SSR技术

  • 服务端渲染(Server Side Render),即:网页是通过服务端渲染生成后输出给客户端。

    • 在SSR中,前端分成2部分:前端客户端、前端服务端
    • 前端服务端,用于发送ajax,获得数据
    • 前端客户端,用于将ajax数据和页面进行渲染,渲染成html页面,并响应给调用程序(浏览器、爬虫)

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 如果爬虫获得html页面,就可以启动处理程序,处理页面内容,最终完成SEO操作。

1.4 SPA和SSR对比

SPA单页应用程序SSR服务器端渲染
优势1.页面内容在客户端渲染
2. 只关注View层,与后台耦合度低,前后端分离
3.减轻后台渲染画面的压力
1.更好的SEO,搜索引擎工具可以直接查看完全渲染的画面
2.更快的内容到达时间 (time-to-content),用户能更快的看到完整渲染的画面
劣势1.首屏加载缓慢
2.SEO(搜索引擎优化)不友好
1.更多的服务器端负载
2.涉及构建设置和部署的更多要求,需要用Node.js渲染
3.开发条件有限制,一些生命周期将失效
4.一些常用的浏览器API无法使用

1.5 什么是Nuxt.js

  • Nuxt.js 是一个基于 Vue.js 的通用应用框架。

    • Nuxt支持vue的所有功能,此类内容为前端客户端内容。
    • Nuxt特有的内容,都是前端服务端内容。
  • 通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI 渲染

  • Nuxt.js 预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置。

2 入门案例

2.1 create-nuxt-app 介绍

  • Nuxt.js 提供了脚手架工具 create-nuxt-app

  • create-nuxt-app 需要使用 npx

  • npx 命令为 NPM版本5.2.0默认安装组件

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.2 安装

npx create-nuxt-app <project-name>
  • 例如
npx create-nuxt-app demo_nuxt02

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.3 启动

npm run dev

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • nuxtjs改善

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.4 访问

http://localhost:3000

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3. 目录结构

3.1 目录

目录名称描述
assets资源目录,用于存放需要编译的静态资源。例如:LESS、SASS等
默认情况下,Nuxt使用Webpack若干加载器处理目录中的文件
componentsvue组件目录,Nuxt.js 不会增强该目录,及不支持SSR
layouts布局组件目录
pages页面目录,所有的vue视图,nuxt根据目录结构自动生成对应的路由。
plugins插件目录
static静态文件目录,不需要编译的文件
storevuex目录
nuxt.config.jsnuxt个性化配置文件,内容将覆盖默认
package.json项目配置文件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.2 别名

  • assets 资源的引用:~ 或 @

    // HTML 标签
    <img src="~assets/13.jpg" style="height:100px;width:100px;" alt="">
    <img src="~/assets/13.jpg" style="height:100px;width:100px;" alt="">
    <img src="@/assets/13.jpg" style="height:100px;width:100px;" alt="">
    
    // CSS
    background-image: url(~assets/13.jpg);
    background-image: url(~/assets/13.jpg);
    background-image: url(@/assets/13.jpg);
    
  • static 目录资源的引用:/ 直接引用

    //html标签
    <img src="/12.jpg" style="height:100px;width:100px;" alt="">
    
    //css
    background-image: url(/12.jpg);
    
  • 实例

    <template>
      <div>
        <!-- 引用 assets 目录下经过 webpack 构建处理后的图片 -->
        <img src="~assets/13.jpg" style="height:100px;width:100px;" alt="">
    
        <!-- 引用 static 目录下的图片 -->
        <img src="/12.jpg" style="height:100px;width:100px;" alt="">
    
        <!-- css -->
        <div class="img1"></div>
        <div class="img2"></div>
      </div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style>
      .img1 {
        height: 100px;
        width: 100px;
        background-image: url(~assets/13.jpg);
        background-size: 100px 100px;
        display: inline-block;
      }
      .img2 {
        height: 100px;
        width: 100px;
        background-image: url(/12.jpg);
        background-size: 100px 100px;
        display: inline-block;
      }
    </style>
    

4 路由

4.1 路由概述

  • Nuxt.js 依据 pages 目录结构自动生成 vue-router 模块的路由配置。
  • 要在页面之间切换路由,我们建议使用<nuxt-link> 标签。
标签名描述
<nuxt-link>nuxt.js中切换路由
<Nuxt />nuxt.js的路由视图
<router-link>vue默认切换路由
<router-view/>vue默认路由视图

4.2 基础路由

  • 自动生成基础路由规则
路径组件位置及其名称规则
/pages/index.vue默认文件 index.vue
/userpages/user/index.vue默认文件 index.vue
/user/onepages/user/one.vue指定文件
  • 实例

    情况1:访问路径,由pages目录资源的名称组成(目录名称、文件的名称)
      - 资源位置: ~/pages/user/one.vue
      - 访问路径:http://localhost:3000/user/one
    
    
    情况2:每一个目录下,都有一个默认文件 index.vue
      - 资源位置: ~/pages/user/index.vue
      - 访问路径:http://localhost:3000/user
    
  • 思考:/user 可以匹配几种文件?

    • pages/user.vue 文件 【优先级高】
    • pages/user/index.vue 文件

4.3 动态路由

  • 在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录。
路由中路径匹配组件位置及其名称
/pages/index.vue
/user/:idpages/user/_id.vue
/:slugpages/_slug/index.vue
/:slug/commentspages/_slug/comments.vue
  • 实例1:获得id值,创建资源 user/_id.vue
<template>
  <div>
    查询详情 {{this.$route.params.id}}
  </div>
</template>

<script>
export default {
  transition: 'test',
  mounted() {
    console.info(this.$route)
  },
}
</script>

<style>

</style>

4.4 动态命名路由

  • 路径 /news/123 匹配_id.vue还是_name.vue

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 我们可以使用<nuxt-link>解决以上问题

    • 通过name 确定组件名称:“xxx-yyy”
    • 通过params 给对应的参数传递值
<nuxt-link :to="{name:'news-id',params:{id:1002}}">第2新闻</nuxt-link>
<nuxt-link :to="{name:'news-name',params:{name:1003}}">第3新闻</nuxt-link>

4.5 默认路由

路径组件位置及其名称
不匹配的路径pages/_.vue
  • 404页面,可以采用 _.vue进行处理

4.6 嵌套路由(知道)

  • 创建嵌套子路由,你需要添加一个 父组件Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。

    • 要求:父组件 使用<nuxt-child/> 显示子视图内容
    pages/
    --| book/						//同名文件夹
    -----| _id.vue
    -----| index.vue
    --| book.vue					//父组件
    
  • 步骤1:编写父组件 pages/child/book.vue

    <template>
      <div>
          <nuxt-link to="/child/book/list">书籍列表</nuxt-link> |
          <nuxt-link to="/child/book/123">书籍详情</nuxt-link> |
          <hr>
          <nuxt-child />
      </div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style>
    
    </style>
    
    
  • 步骤2:编写子组件 pages/child/book/list.vue

    <template>
      <div>书籍列表</div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style>
    
    </style>
    
    
  • 步骤3:编写子组件 pages/child/book/_id.vue

    <template>
      <div>书籍详情{{$route.params.id}} </div>
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style>
    
    </style>
    
    

4.7 过渡动效(了解)

4.7.1 全局过渡动效设置

  • Nuxt.js 默认使用的过渡效果名称为 page

    • .page-enter-active样式表示进入的过渡效果。
    • .page-leave-active样式表示离开的过渡效果。
  • 步骤1:创建 assets/main.css,编写如下内容:

    .page-enter-active, .page-leave-active {
      transition: opacity .5s;
    }
    .page-enter, .page-leave-active {
      opacity: 0;
    }
    
  • 步骤2:nuxt.config.js 引入main.css文件

    module.exports = {
      css: [
        'assets/main.css'
      ]
    }
    

4.7.1 自定义动画

  • 如果想给某个页面自定义过渡特效的话,只要在该页面组件中配置 transition 字段即可:

  • 步骤1:在全局样式 assets/main.css 中添加名称为test的过渡效果

    .test-enter-active, .test-leave-active {
      transition: all 2s;
      font-size:12px;
    }
     .test-enter, .test-leave-active {
      opacity: 0;
      font-size:40px;
    }
    
    
  • 步骤2:需要使用特效的vue页面编写如下:

    export default {
      transition: 'test'
    }
    

4.8 案例:学生管理

  • 需求1:首页

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 需求2:点击,学生管理

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 需求3:点击“添加”按钮

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 需求4:点击修改按钮

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 需求5:详情

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5. 视图

5.1 默认模板(了解)

  • 定制化默认的 html 模板,只需要在应用根目录下创建一个 app.html 的文件。

  • 默认模板:

    <!DOCTYPE html>
    <html {{ HTML_ATTRS }}>
      <head {{ HEAD_ATTRS }}>
        {{ HEAD }}
      </head>
      <body {{ BODY_ATTRS }}>
        {{ APP }}
      </body>
    </html>
    
  • 修改模板,对低版本IE浏览器进行支持(兼容IE浏览器)

    <!DOCTYPE html>
    <!--[if IE 9]><html lang="en-US" class="lt-ie9 ie9" {{ HTML_ATTRS }}><![endif]-->
    <!--[if (gt IE 9)|!(IE)]><!--><html {{ HTML_ATTRS }}><!--<![endif]-->
      <head {{ HEAD_ATTRS }}>
        {{ HEAD }}
      </head>
      <body {{ BODY_ATTRS }}>
        {{ APP }}
      </body>
    </html>
    

5.2 默认布局【掌握】

5.2.1 布局概述

  • 布局:Nuxt.js根据布局,将不同的组件进行组合。

  • 模板:html页面,是布局后所有组件挂载的基础。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.2.2 布局分析

  • layouts/default.vue 默认布局组件
    • 访问路径根据路由,确定执行组件
    • 组件具体显示的位置,有布局来确定

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.2.3 公共导航

  • 修改 layouts/default.vue
<template>
  <div>
    <nuxt-link to="/">首页</nuxt-link> |
    <nuxt-link to="/user/login">登录</nuxt-link> |
    <nuxt-link to="/user/123">详情</nuxt-link> |
    <nuxt-link to="/about">默认页</nuxt-link> |
    <nuxt-link to="/nuxt/async">async</nuxt-link> |
    <hr/>
    <Nuxt />
  </div>
</template>

5.3 自定义布局

  • 在layouts目录下创建组件:layouts/blog.vue

    <template>
    	<div>
            开头<br/>
            <nuxt/>
            结束<br/>
        </div>
      
    </template>
    
    <script>
    export default {
    
    }
    </script>
    
    <style>
    
    </style>
    
    
  • 在需要的视图中使用 blog布局

    <script>
    export default {
      layout: 'blog'
      //...
    }
    </script>
    
    

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.4 错误页面(了解)

  • 编写layouts/error.vue页面,实现个性化错误页面
<template>
  <div>
    <div v-if="error.statusCode == 404">
      404 页面不存在 {{error.message}}
    </div>
    <div v-else>
      应用程序错误
    </div>
    <nuxt-link to="/">首 页</nuxt-link>
  </div>
</template>

<script>
export default {
  props: ['error']
}
</script>

<style>

</style>

  • 解决问题: 404 、500、连接超时(服务器关闭)
  • 总结:所学习的技术中,有2种方式处理错误页面
    • 方式1:默认路径,_.vue (先执行)
    • 方式2:错误页面,~/layouts/error.vue

6 Nuxt组件特殊配置

6.1 概述

  • Nuxt页面组件实际上是 Vue 组件,只不过 Nuxt.js 为这些组件添加了一些特殊的配置项(在Vue组件的基础上,添加了额外功能)
特殊配置项描述
asyncDataSSR进行异步数据处理,也就是服务器端ajax操作区域。
fetch在渲染页面之前获取数据填充应用的状态树(store)
head配置当前页面的head标签,整合第三方css、js等。
layout指定当前页面使用的布局
transition指定页面切换的过渡动效
scrollToTop布尔值,默认: false。 用于判定渲染页面前是否需要将当前页面滚动至顶部。

6.2 模板代码

<template>
  <h1 class="red">Hello {{ name }}!</h1>
</template>

<script>
export default {
  asyncData (context) {					//异步处理数据, 每次加载之前被调用
    return { name: 'World' }
  },	
  fetch () {							//用于在渲染页面之前获取数据填充应用的状态树(store)
    
  },
  head: {								//配置当前页面的 Meta 标签
  },
  layout: '自定义布局名'					//自定义布局
  ...
}
</script>

<style>
.red {
  color: red;
}
</style>

6.3 head - 入门

  • html模板代码

    <html>
    <head>
    	<meta charset="UTF-8" />
    	<title>我是标题</title>
    	<link rel="stylesheet" type="text/css" href="css外部文件"/>
    	<script src="js外部文件" type="text/javascript" charset="utf-8"></script>
    </head>
    <body>
    </body>
    </html>
    
  • 通过nuxt提供head属性,可以给单个也是设置:标题、外部css、外部js 等内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 基本模板

    <script>
    export default {
      head: {
        link: [],       //导入第三方css文件,可以导入多个
        script: []      //导入第三方js文件,可以导入多个
      }
    }
    </script>
    
  • 完整代码

<template>
  <div>
    详情页 {{$route.params.id}} <br/>

    <div class="bg2"></div>
    <div class="bg3"></div>

  </div>
</template>

<script>
export default {
  head: {
    title: '详情页',
    link: [
      {rel:'stylesheet',href:'/style/img.css'},....
    ],
    script: [
      { type: 'text/javascript', src: '/js/news.js' }
    ]
  }
}
</script>

<style>
  .bg2 {
    background-image: url('~static/img/2.jpg');
    width: 300px;
    height: 300px;
    background-size: 300px;
  }
</style>

7. ajax操作

7.1 整合 axios

7.1.1 默认整合

  • 在构建项目时,如果选择axios组件,nuxt.js将自动与axios进行整合

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.1.2 手动整合(可选)

  • 步骤1:package.json有axios的版本

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      "dependencies": {
        "@nuxtjs/axios": "^5.13.1",
      },
    
  • 步骤2:安装

    npm install
    
  • 步骤3:nuxt.config.js 以模块的方式添加axios

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      modules: [
        // https://go.nuxtjs.dev/axios
        '@nuxtjs/axios',
      ],
    

7.1.3 常见配置

  • 修改 nuxt.config.js 进行baseURL的配置

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      // Axios module configuration: https://go.nuxtjs.dev/config-axios
      axios: {
        baseURL:'http://localhost:10010/'
      },
    

7.2 使用axios发送ajax

  • 在vue页面中,通过 this. a x i o s . x x x ( ) 操作 a j a x 。 t h i s . axios.xxx() 操作ajax。this. axios.xxx()操作ajaxthis.axios 与之前 axios等效。

    this.$axios.post("/search-service/search",this.searchMap).then( res => {
        //获得查询结果
        this.searchResult = res.data.data;
    });
    

7.3 使用asyncData发送 ajax

  • asyncData中的ajax将在“前端服务端执行”,在浏览器看到是数据,而不是ajax程序。

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.3.1 发送一次请求

  • 语法:
export default {
	async asyncData( context ) {  //context就相当于其他地方的this
        //发送ajax
        let { data } = await context.$axios.get('路径','参数')
        // 返回结果
        return {变量: 查询结果从data获取 }
	},
}
  • 实例

    <template>
      <div>{{echo}}</div>
    </template>
    
    <script>
    export default {
      async asyncData(context) {
        // 发送ajax
        let {data} = await context.$axios.get('/service-consumer/feign/echo/abc')
        // 返回数据
        return {
          echo: data
        }
      },
    }
    </script>
    
    <style>
    
    </style>
    
    

7.3.2 发送多次请求

  • 语法1:

    export default {
        async asyncData( content ) {
            let [结果1,结果2] = await Promise.all([ ajax请求1, ajax请求2])
            return {
                变量1: 结果1,
                变量2: 结果2
            }
        },
    }
    
  • 语法2:

    export default {
        async asyncData( content ) {
            let [{数据:别名1},{数据:别名2}] = await Promise.all([ ajax请求1, ajax请求2])
            return {
                变量1: 别名1,
                变量2: 别名2
            }
        },
    }
    
    //演化过程
    let response = ajax请求
    let [response,response] = await Promise.all([ajax1,ajax2])
    let [{data},{data}] = await Promise.all([ajax1,ajax2])
    let [{data:别名1},{data:别名2}] = await Promise.all([ajax1,ajax2])
    
  • 实例

<template>
  <div>{{echo}} {{echo2}}</div>
</template>

<script>
export default {
  async asyncData(context) {
    // 发送ajax
    let [{data:echo}, {data:echo2}] = 
                await Promise.all([
                    context.$axios.get('/service-consumer/feign/echo/abc'),
                    context.$axios.get('/service-consumer/client/echo/abc')
                ])

    // 返回数据
    return {
      echo,
      echo2
    }
  },
}
</script>

<style>

</style>

7.4 使用fetch发送 ajax

  • fetch 方法用于在渲染页面前填充应用的状态树(store)数据, 与 asyncData 方法类似,不同的是它不会设置组件的数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 步骤1:创建store/index.js

    export const state = () => ({
      str: 0
    })
    
    export const mutations = {
      setData (state, value) {
        state.str = value
      }
    }
    
  • 步骤2:测试页面

    <template>
      <div>
        <!-- 显示数据 -->
        {{$store.state.str}}
      </div>
    </template>
    
    <script>
    
    export default {
      async fetch( {store, $axios} ) {
        // 发送ajax
        let { data } = await $axios.get('/service-consumer/feign/echo/abc')
        // 设置数据
        store.commit('setData' , data )
      }
    }
    </script>
    
    <style>
    
    </style>
    
    

7.5 插件:自定义axios

7.5.0 分析

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.5.1 客户端

  • 步骤一:在nuxt.conf.js中配置客户端插件,设置 mode 为 client

      plugins: [
        { src: '~plugins/api_client.js', mode: 'client' }
        //{ src: '~plugins/api.js', ssr: false }
      ],
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 步骤二:编写 plugins/api_client.js 对 内置的 $axios进行增强

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    //自定义函数
    const request = {
      test : (params) => {
        return axios.get('/service-consumer/feign/echo/abc',{
          params
        })
      },
    }
    
    var axios = null
    export default ({ $axios }, inject) => {
    
      //3) 保存内置的axios
      axios = $axios
    
      //4) 将自定义函数交于nuxt
      // 使用方式1:在vue中,this.$request.xxx()
      // 使用方式2:在nuxt的asyncData中,content.app.$request.xxx()
    
      inject('request', request)
    }
    
    

7.5.2 服务端

  • 步骤一:配置服务端插件,设置 mode 为 server

      plugins: [
        { src: '~plugins/api_client.js', mode: 'client' },
        { src: '~plugins/api_server.js', mode: 'server' },
        //{ src: '~plugins/api.js', ssr: false },
        //{ src: '~plugins/api.server.js', ssr: true }
      ],
    
  • 步骤二:编写 plugins/api.server.js 对 内置的 $axios进行增强

    const request = {
      test : (params) => {
        return axios.get('/service-consumer/feign/echo/abc',{
          params
        })
      },
      
    }
    
    var axios = null
    export default ({ $axios, redirect, process }, inject) => {
    
      //赋值
      axios = $axios
    
      //4) 将自定义函数交于nuxt
      // 使用方式1:在vue中,this.$requestServer.xxx()
      // 使用方式2:在nuxt的asyncData中,content.app.$requestServer.xxx()
      inject('requestServer', request)
    }
    
    
  • 注意:前端服务端插件,不支持切换路由。也就是说刷新可以访问,使用<nuxt-link>切换不能访问。解决方案:

    • 方案1:修改mode,支持client和service。
    • 方案2:使用 location.href = ‘路径’ 进行跳转

7.5.3 插件配置总结

//方式1:通过src设置文件,通过mode设置模式
plugins: [
	{ src: '~/plugins/apiclient.js', mode: 'client' },		//前端客户端
	{ src: '~/plugins/apiserver.js', mode: 'server' },		//前端服务端
    { src: '~/plugins/api.js' }								//前端客户端 + 前端服务端
]

//方式2:通过命名来确定模式
plugins: [
    '~/plugins/api.client.js',				//前端客户端
    '~/plugins/api.server.js',				//前端服务端
    '~/plugins/api.js',						//前端客户端 + 前端服务端
]

8. Vuex 状态树

8.1 根模块数据操作

  • 步骤一:创建 store/index.js 添加一个 counter变量,并可以继续累加操作

    export const state = () => ({
      counter: 0
    })
    
    export const mutations = {
      increment (state) {
        state.counter++
      }
    }
    
    
  • 步骤二:在页面中,使用

    <template>
      <div>
        首页 {{counter}}
        <input type="button" value="+" @click="increment"/>
      </div>
    </template>
    
    <script>
    import { mapState,mapMutations } from 'vuex'
    export default {
      computed: {
        ...mapState(['counter'])
      },
      methods: {
        ...mapMutations(['increment'])
      },
    }
    </script>
    
    <style>
    
    </style>
    
    

8.2 其他模块数据操作

  • 步骤一:创建其他模块 store/book.js

    export const state = () => ({
      money: 0
    })
    
    export const mutations = {
      addmoney (state) {
        state.money += 5
      }
    }
    
  • 步骤二:使用指定模块中的数据

    <template>
      <div>
        金额:{{money}} <br>
        <input type="button" value="累加" @click="addMoney(5)">
      </div>
    </template>
    
    <script>
    import {mapState, mapMutations} from 'vuex'
    export default {
      methods: {
        // ...mapMutations({'方法名':'模块/action名称'})
        ...mapMutations({'addMoney':'book/addMoney'})
      },
      computed: {
        //...mapState('模块名称',['变量'])
        ...mapState('book',['money'])
      }
    }
    </script>
    
    <style>
    
    </style>
    

8.3 完整vuex模板

// state为一个函数, 注意箭头函数写法
const state = () => ({
  user: 'jack'
})

// mutations为一个对象
const mutations = {
  setUser(state, value) {
    state.counter = value
  }
}
// action执行mutation
const actions = {
  userAction (context,value){
    // 可以发送ajax
    context.commit('setUser',value)
  }

}

// 获取数据
const getters = {
  getUser (state) {
    return state.user
  }
}
export default {
  namespace: true,	// 命名空间,强制要求,在使用时,加上所属的模块名,例如:book/addmoney
  state,
  mutations,
  actions,
  getters
}

9. nuxt流程总结

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

10. Nuxt整合Element UI

11 综合练习

10.1 练习1:学生列表

  • 表结构

    #班级表
    create table tab_class(
      cid int primary key auto_increment,
      cname varchar(50)
    );
    insert into tab_class(cid, cname) values(1,'Java56');
    insert into tab_class(cid, cname) values(2,'Java78');
    
    #学生表
    create table tab_student(
      sid int primary key auto_increment,
      sname varchar(50),
      cid int
    );
    
    insert into tab_student(sname,cid) values('张三',1);
    insert into tab_student(sname,cid) values('李四',1);
    insert into tab_student(sname,cid) values('王五',2);
    insert into tab_student(sname,cid) values('赵六',2);
    
    
  • 需求:查询学生列表信息

    • 要求1:可以进行“班级”条件查询
    • 要求2:对“班级”数据进行SEO
    • 要求3:学生数据不进行SEO

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

10.2 练习2:

10.2.1 表结构:

CREATE TABLE tb_teacher(
  tid INT PRIMARY KEY AUTO_INCREMENT,
  tname VARCHAR(50) COMMENT '老师姓名',
  TYPE INT COMMENT '老师类型:1.授课老师、2.助理老师、3.辅导员老师'
);
INSERT INTO tb_teacher(tid,tname,TYPE) VALUES(1,'梁桐老师',1);
INSERT INTO tb_teacher(tid,tname,TYPE) VALUES(2,'马坤老师',2);
INSERT INTO tb_teacher(tid,tname,TYPE) VALUES(3,'仲燕老师',3);
INSERT INTO tb_teacher(tid,tname,TYPE) VALUES(4,'袁新奇老师',1);
INSERT INTO tb_teacher(tid,tname,TYPE) VALUES(5,'任林达老师',2);
INSERT INTO tb_teacher(tid,tname,TYPE) VALUES(6,'王珊珊老师',3);

CREATE TABLE tb_class(
  cid INT PRIMARY KEY AUTO_INCREMENT,
  cname VARCHAR(50) COMMENT '班级名称',
  teacher1_id INT COMMENT '授课老师',
  teacher2_id INT COMMENT '助理老师',
  teacher3_id INT COMMENT '辅导员老师'
);

INSERT INTO tb_class(cid,cname,teacher1_id,teacher2_id,teacher3_id) VALUES(1,'Java56',1,2,3);
INSERT INTO tb_class(cid,cname,teacher1_id,teacher2_id,teacher3_id) VALUES(2,'Java78',1,2,3);
INSERT INTO tb_class(cid,cname,teacher1_id,teacher2_id,teacher3_id) VALUES(3,'Java12',4,5,6);
INSERT INTO tb_class(cid,cname,teacher1_id,teacher2_id,teacher3_id) VALUES(4,'Java34',4,5,6);

10.2.2 需求:查询

  • 需求:使用“自定义axios”完成
    • 查询班级详情
    • 通过班级名称模糊查询
    • 查询班级的同时,查询老师信息

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

10.2.3 扩展需求:添加

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/229203.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

16mic圆形麦克风阵列电路与声源定位算法设计

16mic圆形麦克风阵列电路与声源定位算法设计 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)&#xff1f;可加我微信hezkz17, 本群提供音频技术答疑服务&#xff0c;群赠送语音信号处理降噪算法&#xff0c;蓝牙耳机音频&#xff0c;DSP音频项目核心开发资料, 1 实…

多线程并发Ping脚本

1. 前言 最近需要ping地址&#xff0c;还是挺多的&#xff0c;就使用python搞一个ping脚本&#xff0c;记录一下&#xff0c;以免丢失了。 2. 脚本介绍 首先检查是否存在True.txt或False.txt文件&#xff0c;并在用户确认后进行删除&#xff0c;然后从IP.txt的文件中读取IP地…

灵活性与可靠性:SaaS云开发与定制开发小程序的优缺点解析

随着移动互联网的快速发展&#xff0c;微信小程序作为一种轻量级的应用程序&#xff0c;逐渐成为了企业开展业务和提升用户体验的重要工具。对于企业而言&#xff0c;选择通过SaaS云开发或定制开发的方式开发小程序&#xff0c;都是为了更好地实现业务目标。在这篇文章中&#…

【数据结构】插入排序,希尔排序,选择排序,堆排序,冒泡排序

1.插入排序 思路&#xff1a;插入排序将一个数插入一个有序的数组里面&#xff0c;将这个数和数组元素挨着比较&#xff0c;直到他插入到合适的位置。 动画演示&#xff1a; 步骤&#xff1a;1.定义一个变量tmp保存要插入的数据 2.在循环中用tmp和有序数组中的元素比较&#…

Spring全面详解

目录 1. Spring 概述 1.1 Spring是什么 1.2 Spring的作用 1.3 Spring IoC是什么 2. Spring 快速入门 3. Spring Bean 3.1 的实例化方式 空参构造器 3.2 的属性注入 全参构造器注入 setter方法注入 策略模式 3.3 注解管理 3.4 注解方式的属性注入 1. Spring 概述 …

聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化

聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化 目录 聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于谱聚类(Spectral Cluster)的聚类算法可视化&#xff08;完…

计算机毕业设计 基于SpringBoot的高校毕业与学位资格审核系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

Facebook自动回复脚本编写教程

在数字时代&#xff0c;社交媒体已经成为人们交流和建立联系的重要渠道&#xff0c;Facebook作为全球最大的社交媒体平台之一&#xff0c;拥有数十亿的用户&#xff0c;为企业和个人提供了无限的社交可能性。 然而&#xff0c;对于企业和个人来说&#xff0c;在Facebook上保持…

整合消息队列RabbitMQ

为什么使用消息队列MQ&#xff1f; 因为使用消息队列有多个好处&#xff1a;可以实现系统服务的解耦、异步和削峰&#xff1a; 异步通信&#xff1a;消息队列提供了一种异步通信的方式&#xff0c;发送方可以将消息发送到队列中&#xff0c;然后继续执行其他任务&#xff0c;…

C++STL的string模拟实现

文章目录 前言string的成员变量成员函数构造函数拷贝构造赋值重载 模拟实现string各种接口print迭代器普通迭代器const迭代器 string比较大小push_backinsert 和 eraseinserterase reserve和resizereserveresize swapfindcout和cincoutcin 前言 今天要讲string的底层实现&…

docker---资源控制

docker的资源控制 对容器使用宿主机的资源进行限制。 三种控制方向&#xff1a;CPU 内存 磁盘I/O docker使用linux自带的功能cgroup&#xff1b;control groups是linux内核系统提供的一种可以限制记录&#xff0c;隔离进程所使用的物理资源机制。 docker借助此…

每日一练 | 华为认证真题练习Day145

1、一台路由器通过RIP、OSPF和静态路由都学习到了到达同一目的地址的路由。默认情况下&#xff0c;VRP将最终选择通过哪种协议学习到的路由&#xff1f; A. 三种协议学习到的路由都选择 B. 静态路由 C. OSPF D. RIP 2、如果网络管理员没有配置骨干区域&#xff0c;则路由器…

el-table 表格多选(后端接口搜索分页)实现已选中的记忆功能。实现表格数据和已选数据(前端分页)动态同步更新。

实现效果&#xff1a;&#xff08;可拉代码下来看&#xff1a;vue-demo: vueDemo&#xff09; 左侧表格为点击查询调用接口查询出来的数据&#xff0c;右侧表格为左侧表格所有选择的数据&#xff0c;由前端实现分页。 两个el-table勾选数据联动更新 实现逻辑&#xff1a; el-…

MQTT协议对比TCP网络性能测试模拟弱网测试

MQTT正常外网压测数据---时延diff/ms如下图&#xff1a; MQTT弱网外网压测数据 TCP正常外网压测数据 TCP弱网外网压测数据 结论&#xff1a; 在弱网场景下&#xff0c;MQTT和TCP的网络性能表现会有所不同。下面是它们在弱网环境中的对比&#xff1a; 连接建立&#xff1a;M…

华清远见嵌入式学习——QT——作业2

作业要求&#xff1a; 代码运行效果图&#xff1a; 登录失败 和 最小化 和 取消登录 登录成功 和 X号退出 代码&#xff1a; ①&#xff1a;头文件 #ifndef LOGIN_H #define LOGIN_H#include <QMainWindow> #include <QLineEdit> //行编辑器类 #include…

Rust测试字符串的移动,Move

代码创建了一个结构体&#xff0c;结构体有test1 字符串&#xff0c;还有指向字符串的指针。一共创建了两个。 然后我们使用swap 函数 交换两个结构体内存的内容。 最后如上图。相同的地址&#xff0c;变成了另外结构体的内容。注意看指针部分&#xff0c;还是指向原来的地址…

想转行IT,有前途吗?

作为一个在工程领域工作了三年的人&#xff0c;我深知转行到 IT&#xff0c;尤其是网络安全领域&#xff0c;不是一件轻松的事。我的经历或许能为你提供一些启示。 在我之前的工作中&#xff0c;虽然工作量大、压力重&#xff0c;但总觉得缺少了某种成就感和动力。我意识到&a…

Flutter代码补全

有的时候属性不经常使用&#xff0c;就想不起来该用啥&#xff0c;只有点点印象&#xff1b;只能用代码补全功能&#xff0c;但我用了AS的默认操作发下并不好使&#xff0c;估计是快捷键冲突了。刚开始是不是下面的效果&#xff1a;这肯定不是我们想要的。 不怕&#xff0c;接下…

XML是什么

XML是是什么&#xff1f; XML&#xff08;Extensible Markup Language&#xff09;&#xff0c;中文是可扩展标记语言&#xff0c;是标准通用标记语言的子集。它是一种标记语言&#xff0c;用于标记电子文档&#xff0c;使其结构化。 XML可以用来标记数据&#xff0c;定义数据…

代码随想录算法训练营第五十九天【单调栈part2】 | 503.下一个更大元素II、42. 接雨水

503.下一个更大元素II 题目链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 求解思路 重点在如何处理循环数组。 方案一&#xff1a; 直接将两个数组拼接在一起&#xff0c;然后使用单调栈求下一个最大值。 方案二&#xff1a; 在遍历的过…