使用Nuxt模仿掘金第一天

1,498 阅读4分钟

使用Nuxt模仿掘金第一天

一直以来使用的技术栈都是Vue,然而服务端相关的知识一直还未接触过,所以开始接触Vue的SSR渲染最火的框架——Nuxt,并且打算就用它来仿站掘金。

开始

第一遍先简单读了一下文档,发现中文文档写的并不是很详细,很多还要去百度,但从文档还是能知道Nuxt的一个大致概念。

文档读再多不用也没用(而且很多估计也不懂),所以打算一边实战一边学习来获得战果。

安装

  • npm:
$ npx create-nuxt-app <项目名>
  • yarn:
$ yarn create nuxt-app <项目名>

输入命令后,安装过程有很多选项,根据官方文档提供的安装步骤,逐一选择即可,只是Rendering mode这一项一定要选择SSR的模式,不然使用Nuxt就么有意义了。

当安装完成之后,打开项目可以看到项目的初始目录是这样的:

image-20210920000054221.png

然后在当前目录的命令行里面输入:npm run dev,即可启动项目,项目启动后看到如下页面,就说明Nuxt项目成功跑起来了:

image-20210920000225075.png

干活儿

新建布局

既然项目能够跑起来了,就开始仿站掘金。在简单分析了一些掘金的页面之后,首页一系列的标签栏切换都有一个共同的头部,那说明这肯定是一个布局,所以就先建一个布局。

  1. 新建一个layouts目录,然后再在下面新建一个模板文件(随便命名),然后像写vue文件一样的写法编写就行:

    <template>
      <header>Header</header>
    </template>
    
  2. 因为这仅仅只是一个布局,显示的主题依然是页面,所以我们需要通过使用<nuxt />组件来显示主题内容,引用该布局的页面都会显示在<nuxt />的位置。

    <template>
      <header>Header</header>
      <div class="main">
          <nuxt />
      </div>
    </template>
    

经过一阵折腾,算是把头部的样式做好了(喵的,自己撸样式挺累的):

niceab.gif

踩了个坑

因为要使用到sass语法,所以我在安装node-sasssass-loader后,发现项目报错,后来发现最新安装的sass-loader是12的版本了,降到6即可。

自定义SvgIcon组件

在制作页面头部的时候,发现要使用到图标,于是就新建了一个自定义的SvgIcon组件,来方便使用和管理图标,实现过程:

  1. assets目录下新建一个icons目录用于存放svg文件:

image-20210920114404709.png

  1. components目录下新建SvgIcon组件,代码如下:

    <template>
      <i class="icon">
        <!-- aria-hidden, 帮助残障人士阅读(设备读取内容时会跳过这个标签以免混淆) -->
        <svg aria-hidden="true" :width="size" :height="size" :fill="fillColor">
          <use :xlink:href="'#' + iconName"></use>
        </svg>
      </i>
    </template><script lang="ts">
    import Vue, { PropType } from 'vue'export default Vue.extend({
      props: {
        size: {
          type: String as PropType<string>,
          default: '16px'
        },
        fillColor: {
          type: String as PropType<string>,
          default: '#333'
        },
        iconName: {
          type: String as PropType<string>,
          default: ''
        }
      }
    })
    </script>
    

    这里的svg是用过使用symbol标记来实现的,所以我们需要使用到svg-sprite-loader来处理加载的svg文件:

    • 安装:npm install --save-dev svg-sprite-loader

    • 配置:进入到nuxt.config.js里面,找到build项,Nuxt似乎并没有提供chainWebpack那种配置方式,而是用的下面这样的操作:

      build: {
          extend(config) {
              const svgRule = config.module.rules.find(rule => rule.test.test('.svg'))
              svgRule.exclude = [resolve(__dirname, 'assets/icons')]
              config.module.rules.push({
                  test: /.svg$/, //匹配.svg
                  include: [resolve(__dirname, 'assets/icons')], //将存放svg的目录加入到loader处理目录
                  use: [{
                      loader: 'svg-sprite-loader',options: {symbolId: 'icon-[name]'}
                  }]
              })
          }
      }
      

      这样,打包icons目录下的svg文件时,就会给我们生成对应的symbol标记了。

  2. 接着,在plugins文件里面新建一个svg-icon.ts文件,进行文件的批量引入,如果使用的是ts的话,需要安装@types/webpack-dev,并且在tsconfig.jsontypes里面引入:

    const ctx = require.context('@/assets/icons', false, /.svg$/)
    
    const requireAll = (requireContext:__WebpackModuleApi.RequireContext) => requireContext.keys().map(requireContext)
    requireAll(ctx)
    
  3. 因为nuxt没有入口文件,所以我们引入插件需要到nuxt.config.jsplugins项进行引入,以前通过main引入插件的方式都改为在这里来使用了:

    plugins: [
        '@/plugins/svg-icon'
    ]
    
页面和路由

上面已经把布局建好了,那么就可以在pages下新建一个页面index.vue,再引入布局:

<template>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  layout: 'container'
})
</script>

因为nuxt路由是根据页面目录结构自动生成的,所以不需要配置,直接在浏览器上访问:http://localhost:3000即可看到效果。

注:方位路径时,会默认寻找名称为index的文件。

页面新建后,琢磨了一下主页的交互:主要内容页面分为左右两块,左边是根据点击tab显示不同数据,右边固定的格式,再看了一下官网的url跳转方式,就认定了是使用动态路由的方式来编写的,干活儿~

  1. 修改目录结构(编写路由)

    因为Nuxt的路由是通过目录结构生成的,所以这里我在pages下新建了一个_category目录,把之前的index.vue放到这个目录下:

image-20210920150103860.png

这样的话,Nuxt就会给我生成等同如下的路由:

const routes = [
    {
        name: 'category',
        path: '/:category',
        component: 'pages/_category/index.vue'
    }
]

这样使用后,通过访问/recommend或者/follow这样路径的页面时,就会跳转到_category/index.vue这个组件来,并且可以通过this.$route.params来获得关键词。

niceac.gif

但是现在又发现了一个问题,当直访问http://localhost:3000时,页面会找不到,这是因为pages根目录没有index.vue了,所以得再在pages目录下新建一个index.vue文件。

并且,访问该页面时,应该重定向到/recommend这个路径去。

<template>
</template><script lang="ts">
import Vue from 'vue'export default Vue.extend({
  asyncData({ redirect }) {
    redirect('/recommend')
  }
})

通过asyncData解构赋值,可以得到redirect对象,用来重定向路由,此时就不会出现页面丢失的效果了:

nicead.gif

到这里,基本的一些页面结构就完成部分了,现在就可以着手来考虑数据的请求了。Nuxt在安装时,提供了内置的Axios库,所以可以基于此进行数据请求。

To be continue...