使用Nuxt模仿掘金第一天
一直以来使用的技术栈都是Vue,然而服务端相关的知识一直还未接触过,所以开始接触Vue的SSR渲染最火的框架——Nuxt,并且打算就用它来仿站掘金。
开始
第一遍先简单读了一下文档,发现中文文档写的并不是很详细,很多还要去百度,但从文档还是能知道Nuxt
的一个大致概念。
文档读再多不用也没用(而且很多估计也不懂),所以打算一边实战一边学习来获得战果。
安装
- npm:
$ npx create-nuxt-app <项目名>
- yarn:
$ yarn create nuxt-app <项目名>
输入命令后,安装过程有很多选项,根据官方文档提供的安装步骤,逐一选择即可,只是Rendering mode
这一项一定要选择SSR
的模式,不然使用Nuxt
就么有意义了。
当安装完成之后,打开项目可以看到项目的初始目录是这样的:
然后在当前目录的命令行里面输入:npm run dev
,即可启动项目,项目启动后看到如下页面,就说明Nuxt
项目成功跑起来了:
干活儿
新建布局
既然项目能够跑起来了,就开始仿站掘金。在简单分析了一些掘金的页面之后,首页一系列的标签栏切换都有一个共同的头部,那说明这肯定是一个布局,所以就先建一个布局。
-
新建一个
layouts
目录,然后再在下面新建一个模板文件(随便命名),然后像写vue
文件一样的写法编写就行:<template> <header>Header</header> </template>
-
因为这仅仅只是一个布局,显示的主题依然是页面,所以我们需要通过使用
<nuxt />
组件来显示主题内容,引用该布局的页面都会显示在<nuxt />
的位置。<template> <header>Header</header> <div class="main"> <nuxt /> </div> </template>
经过一阵折腾,算是把头部的样式做好了(喵的,自己撸样式挺累的):
踩了个坑
因为要使用到sass
语法,所以我在安装node-sass
和sass-loader
后,发现项目报错,后来发现最新安装的sass-loader
是12的版本了,降到6即可。
自定义SvgIcon组件
在制作页面头部的时候,发现要使用到图标,于是就新建了一个自定义的SvgIcon
组件,来方便使用和管理图标,实现过程:
- 在
assets
目录下新建一个icons
目录用于存放svg
文件:
-
在
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
标记了。
-
-
接着,在
plugins
文件里面新建一个svg-icon.ts
文件,进行文件的批量引入,如果使用的是ts
的话,需要安装@types/webpack-dev
,并且在tsconfig.json
的types
里面引入:const ctx = require.context('@/assets/icons', false, /.svg$/) const requireAll = (requireContext:__WebpackModuleApi.RequireContext) => requireContext.keys().map(requireContext) requireAll(ctx)
-
因为
nuxt
没有入口文件,所以我们引入插件需要到nuxt.config.js
的plugins
项进行引入,以前通过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
跳转方式,就认定了是使用动态路由的方式来编写的,干活儿~
-
修改目录结构(编写路由)
因为
Nuxt
的路由是通过目录结构生成的,所以这里我在pages
下新建了一个_category
目录,把之前的index.vue
放到这个目录下:
这样的话,Nuxt
就会给我生成等同如下的路由:
const routes = [
{
name: 'category',
path: '/:category',
component: 'pages/_category/index.vue'
}
]
这样使用后,通过访问/recommend
或者/follow
这样路径的页面时,就会跳转到_category/index.vue
这个组件来,并且可以通过this.$route.params
来获得关键词。
但是现在又发现了一个问题,当直访问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
对象,用来重定向路由,此时就不会出现页面丢失的效果了:
到这里,基本的一些页面结构就完成部分了,现在就可以着手来考虑数据的请求了。Nuxt
在安装时,提供了内置的Axios
库,所以可以基于此进行数据请求。
To be continue...