• VUE SSR服务器端渲染NUXT采坑总结


    初始化创建项目

    yarn create nuxt-app <项目名>

    css预编译

    安装 yarn add node-sass scss-loader sass-loader --save-dev

    路由管理

    在nuxt中路由已经被集成到框架中,所以不需要再单独引入配置,而且当页面文件创建后, router会生成响应的路由,路由文件在.nuxt/router.js文件,用法上基本不变, 与vue-router用法不同部分记录如下

    跳转与传参

    • nuxt路由跳转同样是分为两种方式(声明式和编程式),不同的是在nuxt中用跳转标签nuxt-link而不是router-link
    • 传参demo如下
     1  <nuxt-link :to="{name:'home',params:{newsId:3306}}">home1</nuxt-link>
     2     接收参数
     3     asyncData({ params }) {
     4         console.log('home1', params);
     5     },
     6     <nuxt-link :to="{path:'home',query:{newsId:3306}}">home2</nuxt-link>
     7     接收参数
     8     asyncData({ query }) {
     9         console.log('home2', query);
    10     },

    页面切换动效

    路由动效分为全局动效和单独页面动效

    • 创建动效文件,在asset文件下创建动效样式文件(这里定义文件名changePage.css)
    • 定义动画效果,这里定义简单的淡入淡出效果
    // 页面默认的页面切换类名为page-enter、page-enter-active、page-leave-active
    .page-enter-active,
    .page-leave-active {
      transition: opacity 1s;
    }
    
    .page-enter,
    .page-leave-active {
      opacity: 0;
    }

    引入定义的动效文件,在nuxt.config.js文件中配置中引入该css文件

     定义单独页面动效

    • 在页面文件中定义样式类名
    1 export default {
    2     transition: 'home'
    3 }

    在css文件中定义动画效果

    .home-enter-active,
    .home-leave-active {
      transition: all 2s;
      font-size: 12px;
    
    }
    
    .home-enter,
    .home-leave-active {
      opacity: 0;
      font-size: 40px;
    }

    嵌套路由

    开发业务中,有时难免会遇到需要二级甚至多层路由嵌套,官方文档中的二级路由介绍也是过于简单,为此又多掉了几根头发 这里就拿官网文档的例子作为讲解

     1 第一:假设要创建一个user的二级路由,文件结构如:
     2 
     3 pages/
     4 --| users/  //2、最容易创建与user.vue文件同名的文件夹,这样nuxt就会识别出我们的意图,原来是要创建嵌套路由
     5             //假如文件夹与user.vue不同名,那么该文件夹下的文件同样被生成一级路由
     6 -----| _id.vue
     7 -----| index.vue
     8 --| users.vue // 1、首先要有user.vue文件
     9 
    10 第二:Nuxt.js 自动生成的路由配置如下:
    11 router: {
    12   routes: [
    13     {
    14       path: '/users',
    15       component: 'pages/users.vue',
    16       children: [
    17         {
    18           path: '',
    19           component: 'pages/users/index.vue',
    20           name: 'users'
    21         },
    22         {
    23           path: ':id',
    24           component: 'pages/users/_id.vue',
    25           name: 'users-id'
    26         }
    27       ]
    28     }
    29   ]
    30 }
    31 第三:在一级页面中显示二级页面
    32 <template>
    33     <div class="page-me">
    34         <div>一级页面的相关内容、、、</div>
    35         <nuxt-child /> //二级页面的视图窗口,相当于Vue Router的<router-view></router-view>
    36     </div>
    37 </template>

    路由拦截/鉴权

    nuxt的路由拦截与Vue Router不同,需要引入中间件 的概念,好在文档介绍比较容易理解,现梳理如下

    • 需要在指定的文件夹middleware/ 下创建路由拦截文件(文件不限数量)
    • 一个中间件接收 context 作为第一个参数,context包含了包括vuex等在内相关数据信息,以此通过数据执行相关逻辑
    export default function (context) {
      context.userAgent = process.server ? context.req.headers['user-agent'] : navigator.userAgent
    }

    在nuxt.config.js为全局页面定义路由拦截

    module.exports = {
      router: {
        middleware: 'stats'//中间件文件名
      }
    }

    当然不想全局定义路由拦截也可以为单独的页面定义路由拦截

    //具体的页面
    export default {
      middleware: 'stats'
    }

    错误页设置

    一个完成项目,404或其他错误页面总是要有的,对此nuxt已经封装了404页面跳转,在layouts文件夹下创建error.vue文件(文件名必须是error.vue),组件接收error对象参数,通过参数的状态码判断页面错误原因

    <template>
        <div class="container">
            <h2 v-if="error.statusCode == 404">这是404页面</h2>
            <h2 v-else>这是500页面</h2>
        </div>
    </template>
    <script>
    export default {
        props: ['error'], //nuxt已经封装好返回的
        mounted() {
            console.log('error', this.error);
        }
    };
    </script>

    接口请求

    安装

    • 安装:yarn add @nuxtjs/axios
    • 同正常的axios用法相同,不做详细解释

    本地代理

    • npm i @nuxtjs/proxy -D
    • 在 nuxt.config.js 配置文件中添加对应的模块,并设置代理
    • 配置了代理,本地开发时axios就不能使用baseURL(打包时,baseURL还是需要放开)
     1 modules: ['@nuxtjs/axios','@nuxtjs/proxy'],
     2 axios: {
     3     proxy: true
     4 },
     5 proxy: {//代理可以设置多个
     6     '/api': {//  /api是指真实接口域名后的一个层级
     7         target: 'http://example.com',//真实接口域名
     8         pathRewrite: {
     9             '^/api' : '/'// "/api"与上面的api相同
    10         }
    11     }
    12 }

    axios API封装

    • axios的封装与常规vue项目相同,不同的区别是需要在配置文件中将封装文件引入
    plugins: ["@/plugins/element-ui", "~/plugins/api.js"]

    api访问本地开发

    通过设置IP地址,这样就可以通过IP访问本地项目环境

    //package.json中配置
    "devDependencies": {},
      "config": {
        "nuxt": {
          "host": "0.0.0.0",
          "port": "5000"
        }
      }

    asyncData

    用于服务端或路由更新之前被调用(如果这里进行接口请求,页面会等接口返回结果后才发生跳转),方法的第一个参数被设定为当前页面的上下文对象(即包含路由、参数等等的一些列信息),可用于请求一个或多个接口,并将返回的数据融合到组件的data中,改方法与mounted函数同级,只在页面模块的文件内生效,在组件模块文件内不生效,由于asyncData方法是在组件 初始化 前被调用的,所以在方法内是没有办法通过 this 来引用组件的实例对象。

    写法一
    asyncData(context) {
        return (
            axios.get('https://api.myjson.com/bins/8gdmr1').then(res => {
                return { info: res.data };
                //注意,return返回的最好是key:value对象,直接return导致不利于从实例data中查找使用,如:
                //return (res.data),因为没有设定key,返回的数据虽然融合到实例的data上,但没有key则没法通过key值查找使用
            }),
            axios.get('https://api.myjson.com/bins/8gdmr').then(res => {
                return { info: res.data };
            })
        );
    },
    写法二
    async asyncData({ params }) {
        const { data } = await axios.get('https://api.myjson.com/bins/8gdmr');
        return { info: data };
    },

    Vuex

    nuxt中集成了vuex,不需要新安装插件,Nuxt.js 会尝试找到应用根目录下的 store 目录,并引用 vuex 模块,将 vuex 模块 加到 vendors 构建配置中去,设置 Vue 根实例的 store 配置项。

    以上是官方文档原话,大白话翻译就是:nuxt已经集成了vuex不需要手动安装,nuxt会直接找到vuex文件,并把vuex配置到项目中,然后就想正常vue一样使用即可

    创建与使用

    • 1、vuex不需要新创建实例,即不需要new Vuex.Store({})
    • 2、state的值应该始终是function,为了避免返回引用类型,会导致多个实例相互影响,即
    //正确写法
    export const state = () => ({
      counter: 0
    })
    //错误写法
    export const state = {
      counter: 0
    }

    数据持久化

    为避免页面刷新数据状态丢失,需要对vuex数据持久化,nuxt的vuex数据持久化与vue项目稍有不同,这里推荐的是nuxt-vuex-localstorage

    • 安装
    • 配置文件引入
    //nuxt.config文件中引入
    modules: ["nuxt-vuex-localstorage"]

    欢迎大佬指教

    项目中虽然在使用vuex,但遇到的问题依然很多,使用起来总是磕磕绊绊,欢迎留言指教

    部分配置介绍

    meta标签设置

    既然是为了SEO优化,那么总是少不了mate标签关键字设定,mate标签分为定义全局和单个页面配置

    • 配置文件定义全局
    head: {
        title: process.env.npm_package_name || "",
        meta: [
            { charset: "utf-8" },
            {
                name: "viewport",
                content: "width=device-width, initial-scale=1"
            },
            {
                hid: "description",
                name: "description",
                content: process.env.npm_package_description || ""
            }
        ],
        link: [{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" }]
    },

    设置页面独有关键字

    export default {
      data () {
        return {
          title: 'Hello World!'
        }
      },
      head () {
        return {
          title: this.title,
          meta: [
            { hid: 'description', name: 'description', content: 'My custom description' }
          ]
        }
      }
    }
  • 相关阅读:
    第一次作业:阅读与准备作业
    第一阶段意见总结
    第一冲刺阶段总结与评审
    第一冲刺阶段总结
    第一冲刺阶段第七天
    第一冲刺阶段第六天
    第一冲刺阶段第五天
    第一冲刺阶段第四天
    第一冲刺阶段第三天
    第一冲刺阶段第二天
  • 原文地址:https://www.cnblogs.com/weichen913/p/12132948.html
Copyright © 2020-2023  润新知