Cap1 前言
由于公司业务所需,再加上之前掌握Vue.js相关知识,正好趁着业务的需求,大致学习下Nuxt.js框架。
Nuxt.js是Vue.js通用框架,其实它就是Vue.js的SSR简化版,无非把配置调整更加简单。
具体可以去官网查看下:https://zh.nuxtjs.org/
Cap2 环境搭建
首先搭建基础环境:
npm install vue-cli -g
npm install create-nuxt-app -g
nuxt -v #输出版本则安装成功
初始化项目:
npx create-nuxt-app <项目名>
#或者
yarn create nuxt-app <项目名>
如果npx提示不存在执行:
npm install -g npx
根据终端提示自行选择配置。
Cap3 目录详解
|-- .nuxt // Nuxt自动生成,临时的用于编辑的文件,build
|-- assets // 用于组织未编译的静态资源入LESS、SASS 或 JavaScript
|-- components // 用于自己编写的Vue组件,比如滚动组件,日历组件,分页组件
|-- layouts // 布局目录,用于组织应用的布局组件,不可更改。
|-- middleware // 用于存放中间件
|-- pages // 用于存放写的页面,我们主要的工作区域
|-- plugins // 用于存放JavaScript插件的地方
|-- static // 用于存放静态资源文件,比如图片
|-- store // 用于组织应用的Vuex 状态管理。
|-- .editorconfig // 开发工具格式配置
|-- .eslintrc.js // ESLint的配置文件,用于检查代码格式
|-- .gitignore // 配置git不上传的文件
|-- nuxt.config.json // 用于组织Nuxt.js应用的个性化配置,已覆盖默认配置
|-- package-lock.json // npm自动生成,用于帮助package的统一性设置的,yarn也有相同的操作
|-- package.json // npm包管理配置文件
Cap4 路由配置和参数传递
参考文件:路由
其实就是根据文件夹自动生成路由配置,文档说的很清楚。其次注意SPA链接:
参数传参实现很简单,修改首页pages/index.vue
:
<nuxt-link class="button--grey" :to="{name: 'about',params: {aboutID: 123,aboutTitle: 'About'}}">about</nuxt-link>
修改pages/about/index.vue
:
<template>
<div class="about">
<h2>about</h2>
<p>参数:{{$route.params.aboutID}}</p>
<p>参数:{{$route.params.aboutTitle}}</p>
<p>
<nuxt-link :to="{name: 'index'}">首页</nuxt-link>
</p>
</div>
</template>
这样实现了简单的参数传递。
Cap5 动态路由和参数校验
例如从一个数据列表跳转到详细页,新闻列表到新闻详细页这样一个过程:pages/news
=>pages/news/:id
,其次:id
类型为Number
类型,不可出现其它字符类型,所以需要做个参数校验。大致这样一个实现过程。具体可以查看文档:动态路由。
pages/news/index.vue
:
<template>
<div class="news">
<h2>新闻列表</h2>
<ul>
<nuxt-link tag="li" to="/news/1"><a>新闻1</a></nuxt-link>
<nuxt-link tag="li" to="/news/2"><a>新闻2</a></nuxt-link>
<nuxt-link tag="li" to="/news/我的"><a>新闻3(路由校验)</a></nuxt-link>
</ul>
<nuxt-link class="button--grey" :to="{name: 'index'}">首页</nuxt-link>
</div>
</template>
pages/news/_id.vue
:
<template>
<div class="news-detail">
<h2>新闻详细页</h2>
<p>
新闻ID:{{$route.params.id}}
</p>
<p>
<nuxt-link :to="{name: 'news'}">新闻列表</nuxt-link>
</p>
<p>
<nuxt-link :to="{name: 'index'}">首页</nuxt-link>
</p>
</div>
</template>
<script>
export default {
validate({ params }) {
//只适配数字的路由
return /^\d+$/.test(params.id)
}
}
</script>
Cap6 过渡动画
Nuxt.js提供两种方法为路由提供动画效果,一种是全局的,一种是针对单独页面制作:页面过渡动画。
文档讲得还算可以,我这里实现的是新闻列表到详细页是右滑动进入,而详细页到列表页是左滑动推出,实现如下:pages/news/index.vue
:
<template>
<div class="news">
<h2>新闻列表</h2>
<ul>
<nuxt-link tag="li" to="/news/1"><a>新闻1</a></nuxt-link>
<nuxt-link tag="li" to="/news/2"><a>新闻2</a></nuxt-link>
<nuxt-link tag="li" to="/news/我的"><a>新闻3(路由校验)</a></nuxt-link>
</ul>
<nuxt-link class="button--grey" :to="{name: 'index'}">首页</nuxt-link>
</div>
</template>
<script>
export default {
head() {
return {
title: '新闻列表'
}
},
transition(to, from) {
//console.log("列表页", to);
if (to.name === 'news') {
//设置动画名称
return 'slide-left'
} else {
return 'slide-right'
}
}
}
</script>
pages/_id.vue
:
<template>
<div class="news-detail">
<h2>新闻详细页</h2>
<p>
新闻ID:{{$route.params.id}}
</p>
<p>
<nuxt-link :to="{name: 'news'}">新闻列表</nuxt-link>
</p>
<p>
<nuxt-link :to="{name: 'index'}">首页</nuxt-link>
</p>
</div>
</template>
<script>
export default {
validate({ params }) {
//只适配数字的路由
return /^\d+$/.test(params.id)
},
head() {
return {
title: "新闻详细页"
}
},
transition(to, from) {
//console.log("详细页", to);
if (to.name === 'news-id') {
//设置动画名称
return 'slide-right'
} else {
return 'slide-left'
}
}
}
</script>
然后在全局样式表添加:
/*自定义动画*/
.slide-right-enter-active,
.slide-right-leave-active,
.slide-left-enter-active,
.slide-left-leave-active {
will-change: transform;
transition: all .5s;
position: absolute;
}
.slide-right-enter {
opacity: 0;
transform: translate3d(-100%, 0, 0);
}
.slide-right-leave-active {
opacity: 0;
transform: translate3d(100%, 0, 0);
}
.slide-left-enter {
opacity: 0;
transform: translate3d(100%, 0, 0);
}
.slide-left-leave-active {
opacity: 0;
transform: translate3d(-100%, 0, 0);
}
Cap7 获取数据
文档:异步数据
文档写得比较详细,获取数据使用的是axios类库,在安装脚手架可以选择是否安装它,如果你没有安装的请根据这里步骤安装。
asyncData这个方法返回的就是设定好data()里的数据。
所以实现获取方法很简单:
<template>
<div>
{{ip}}
</div>
</template>
<script>
export default {
asyncData(context) {
return context.$axios.get('http://icanhazip.com').then((res) => {
return {
ip: res.data
}
})
}
}
</script>
但上面的方法比较过时,可以利用异步获取数据编写:
<template>
<div>
{{ip}}
</div>
</template>
<script>
export default {
async asyncData({ app }) {
const ip = await app.$axios.$get('http://icanhazip.com')
return { ip }
}
}
</script>
根据文档上面有三种方法,建议使用异步获取数据方法更好。
Cap8 自定义路由
可以参考这里的实例:自定义路由
我在列表页填写:
<template>
<div class="blog">
<h2>Hello My Blog</h2>
<ul>
<li v-for="item in blog">
<nuxt-link :to="'/blog/'+item.post_id">{{ item.title }}</nuxt-link>
</li>
</ul>
<p>
<nuxt-link :to="{name: 'index'}">首页</nuxt-link>
</p>
</div>
</template>
<script>
export default {
async asyncData({ app }) {
let api = 'http://spider.dcloud.net.cn/api/news';
const blog = await app.$axios.$get(api);
return { blog };
}
}
</script>
详细页:
<template>
<div class="blog-detail">
<h2>博文详细页</h2>
<p>
博文ID:{{$route.params.id}}
</p>
<p v-html="blogInfo.content"></p>
<p>
<nuxt-link :to="{name: 'blog'}">新闻列表</nuxt-link>
</p>
<p>
<nuxt-link :to="{name: 'index'}">首页</nuxt-link>
</p>
</div>
</template>
<script>
export default {
validate({ params }) {
//只适配数字的路由
return /^\d+$/.test(params.id)
},
async asyncData(context) {
let api = 'http://spider.dcloud.net.cn/api/news/36kr/' + context.params.id;
const blogInfo = await context.$axios.$get(api);
return { blogInfo };
}
}
</script>
大概这样效果就出来了。