以后工作中都进行封装,所以不再使用传统的方式进行数据请求。记得要在src下的api文件夹下创建.js文件,用promise封装api。
(1)下载axios:npm install --save axios(或者使用cnpm来下载)
(2)在src(别名 @)下新建一个api的文件夹,用来存放请求的.js文件
另外,还可以自定义路径别名,比如把 src/api 用 & 来替代。在项目根目录下新建一个vue.config.js文件,添加以下内容:
(3)对axios请求进行封装,用 promise
//myaxios.js---
import axios from "axios"
export function axioslink() {
return new Promise((resolve, reject) => {
axios({
url: "http://api.artgoer.cn:8084/artgoer/api/v1/user/324380/v3/topic/topicHomeByLabel?pageIndex=1&token=b544cd63-6d42-46fe-a96c-3cf96bae3113&topicId=62187",
method:"get"
}).then((ok)=>{
resolve(ok);
}).catch((err)=>{
reject(err);
})
})
}
(4)在组件中,使用该封装好的模块来进行数据请求
//myaxios.vue---
<template>
<div>
<img src="1.gif" alt="" v-if="!arr.length">
<ul v-else>
输出arr:
<li v-for="(item,index) in arr" :key="index">{
{item.commentTxt}}li>
ul>
div>
template>
<script>
// 因为是用es6模块化export暴露的,所以这里要用花括号解构出来属于commonjs规范
import {
axioslink} from "&/myaxios.js" //&代表 src/api ,自定义别名,下面有介绍
export default {
data(){
return{
arr:'',
}
},
created() {
// 函数axioslink返回的是个promise对象,所以直接执行axioslink函数就相当于new了个新的promise
axioslink().then((ok)=>{
this.arr=ok.data.data.commentList;
console.log(ok);
}).catch((err)=>{
console.log(err);
})
},
}
script>
<style scope>
img{
width: 200px;
height: 200;
margin: 0 auto;
}
style>
(5)然后将组件引入全局根组件里面使用
//myApp.vue 打算将它作为全局根组件---
<template>
<div>
<myaxios/>
div>
template>
<script>
import myaxios from "%/myaxios.vue"
export default {
components:{
myaxios //引入后声明一下这个组件然后再使用
}
}
script>
<style scope>
style>
(6)在main.js文件里更改全局根组件的路径,改成自己现在写的全局根组件的路径,修改后的vue组件就是能够打开的页面。
(7)打开服务:npm run serve
在数据没有请求到时展示"请稍后logo",等数据出来了,就会切换到数据展示页面。
以上就完成了vue工程化的数据的封装请求、数据的渲染。
之前我们都用传统页面跳转,比如 a标签 、JavaScript Window Location、window的history对象。比如我们之前见过的js的跳转方式:
window,location.href() 点返回键能回来
window.location.reload(); 重新加载当前页面
window.history.replaceState() 替换或者修改地址,无法再回到更改之前的url
window.history.go(number|URL) 可加载历史记录中的某个具体的页面。
window.history.forward() 可加载历史列表中的下一个 URL。
window.history.back() 可加载历史列表中的前一个 URL(如果存在)。
调用后两种方法的效果等价于点击前进按钮或调用 history.go(1)。
在使用location.href、a标签的href[非锚点的方式]等,进行页面访问时,页面会刷新。history可以实现页面不刷新,原理是使用浏览器历史记录,虽然不用再次请求数据,但跟路由区别还是挺大的。
所以现在我们学了vue,改用路由进行无缝跳转。 我的文章:路由的两种模式:hash与history 。
路由原理: 利用锚点来完成切换,页面不刷新。或者另一种说法,根据url不同,来分发不同的页面。
路由的作用:
csdn 2019:浅谈前端SPA(单页面应用)
sf 2019:彻底理清前端单页面应用(SPA)的实现原理 【精读源码】(超有价值)
简书 2018:SPA(单页面应用)和MPA(多页面应用)
sf 2015:前端:将网站打造成单页面应用SPA(一)
路由功能引入: 官方推荐 vue-router.js库来引入路由功能模块。但是呢,这都是适用于本地路由开发的。
我们下载既然在用脚手架搭建项目,那就使用脚手架的自动创建路由功能吧。
(1)创建一个项目,比如命名为 myrouter
(2)然后选择自定义选项(光标可以切换选项)
(3)选择路由,光标到Router,然后空格选中。
(4)然后剩下的选项,就一路默认回车了。
(5)当下载完成后,打开项目目录,会发现,跟默认项目创建不同的是,src里多了两个文件,分别是router、views。
(6)现在我们进入项目根目录,把项目运行起来:npm run serve。可以发现,我们可以通过新增的 Home|About 来切换页面,这就是路由的演示。(是不是跟选项卡很像)
用 Vue.js + Vue Router 创建单页面应用,是非常简单的。将组件 (components) 映射到路由 (routes),然后告诉 Vue Router 在哪里渲染它们。
主要分四步:
routes
配置。
标签设置路由跳转(声明式路由导航)。其中to
属性用来设置跳转链接.
表明路由模版显示的位置。
这个标签解析成
标签)就比如初始页面的切换,看浏览器的代码就是被a标签包裹,而不是router-link。另外得注意,在框架里面写的时候,不能用a标签代替router-link,因为不能解析。1、创建路由组件页面
2、定义路由的规则
3、脚手架帮我们完成了两步:实例化路由对象,把路由规则传入路由实例化对象中
4、脚手架又帮我们完成了一步:把路由对象注入到vue实例(main.js中创建的vue实例化对象中)
5、创建路由出口 router-view
6、创建路由导航 router-link
比如写上面这个小例子,每次点击,不跳转更新页面,跟选项卡很像的功能,但又确实链接地址不同了。
(1)在views文件夹
里,新建单组件页面,是用于路由切换时展示的页面。平常组件怎么写,它就怎么写。然后需要切换几个页面,就建立几个页面。
这里我写了电影、图书、广播、小组
五个不同页面,分别命名为movie.vue / book.vue / broadcast.vue / group.vue
;然后里面展示的东西很简单,只有一个词组:
<template>
<div>
小组
div>
template>
(2)在router文件夹
里的index.js
中,路由映射组件。配好后,测试一下。类似于:http://127.0.0.1:3004/group
在index.js文件夹里给那四个页面组件注册路由,一个组件映射一个。
//index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Movie from '../views/movie.vue'
import Book from '../views/book.vue'
import Broadcast from '../views/broadcast.vue'
import Group from '../views/group.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Movie',
component: Movie
},
{
path: '/book',
name: 'Book',
component: Book
},
{
path: '/broadcast',
name: 'Broadcast',
component: Broadcast
},
{
path: '/group',
name: 'Group',
component: Group
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
(3)在全局根组件里面,使用
设置路由跳转(设置路由导航,使用路由path,因为已经映射到组件了嘛),和路由出口
。
(4)或者可以将
设置路由跳转这块儿,再放到另一个组件里面。
我是把路由导航单独放到了一个组件里面,然后导入到全局根组件,这样做是考虑到以后路由很多的话,不会再根组件里面显得太乱。
//routerlink.vue
<template>
<div class="nav_div">
<router-link to="/">电影router-link>
<router-link to="/book666">图书router-link>
<router-link to="/broadcast">广播router-link>
<router-link to="/group">小组router-link>
div>
template>
<script>
export default {
}
script>
<style scope>
a{
padding: 0 10px;
color:#000;
text-decoration: none;
}
a:hover{
color:tomato;
}
.nav_div{
/* text-align:center;*/
border-bottom:1px solid teal;
margin-bottom:10px;
}
style>
然后在全局根组件里面写入路由入口,并导入路由导航。
<template>
<div>
<routerlink>routerlink>
<router-view />
div>
template>
<script>
import routerlink from "@/components/routerlink.vue"
export default {
components:{
routerlink
}
}
script>
(5)运行程序。
1、声明式跳转:使用
(之前练习的小栗子都是声明式跳转方法)
2、编程式跳转:this.$ router.push()
(js使用的跳转方式)
另外还有:
this.$router.replace ("替换的路径");
//也能路由跳转,但是和push的区别是replace跳转完不能回退。它不会向历史url记录中添加新记录,而是替换掉当前的 history 记录。this.$router.go(正数/负数);
//这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。<template>
<div class="nav_div">
<h1>声明式路由导航h1>
<router-link to="/movie">电影router-link>
<router-link to="/book">图书router-link>
<router-link to="/broadcast">广播router-link>
<router-link to="/group">小组router-link>
<h1>编程式路由导航h1>
<button @click="fun(1)">电影button>
<button @click="fun(2)">图书button>
div>
template>
<script>
export default {
methods: {
fun(num) {
switch (num) {
case 1:
// 跳转到电影
// 使用编程式导航进行跳转
this.$router.push("/movie");
break;
case 2:
this.$router.push("/book");
break;
}
}
}
};
script>
当
对应的路由匹配成功,会自动设置 class 属性值 .router-link-active
。通过自动设置的类名方便进行路由导航样式设置。比如给导航选中的标签设置背景颜色:
<style scope>
.router-link-active{
background: pink;
}
style>
*
或者 demo-*
*
代表匹配任意路径,比如当匹配不到正确路径的时候,就走*
下的页面。demo-*
代表匹配任意开头的路径,比如demo开头的全部路由path,匹配到某个页面。当使用通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由 { path: ‘*’ } 通常用于客户端 404 错误。
比如说下面这种效果:404错误 ; 是当用户乱输入内容时,提示找不到信息 ; 然后我就设置 * 全部匹配,一旦出现这种问题,我就跳转到404页面。
首先我们要先新建一个404页面比如命名为"no404.vue"
,然后去index.js页面里面定义路由规则:
import No404 from '../views/no404.vue'
//路由规则里面配置
{
path: '/*', //通配符路径匹配,放最下面,因为优先级,按定义顺序来匹配
name: 'No404',
component: No404
},
同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。
比如下面这个例子,当路由路径匹配到"/"
时,会被重新定位到路径为"/movie"
,而我们从之前的例子中知道,路径"/movie"会展示'../views/movie.vue'
组件页面。
// 路由重定向
{
path:'/', //当路径匹配"/"时,重定向到movie.vue页面
redirect:"/movie"
},
不过现在的APP三级及以上的路由已经很少见了,顶多到二级路由。
1、创建多级路由的路由组件页面。
我在views中新建了二级路由索要切换的页面组件,目录结构如下:
里面写的东西很简单,就一行字而已。比如 er1.vue 里写的是 “二级路由 111”。
2、定义路由的规则:
现在我想在图书这个一级路由下插入二级路由,并展示出来。(跟之前一级路由的那个例子联系起来)
先把这3个页面导入到index.js中,然后在book这个一级路由规则中,通过children属性配置二级路由规则。在设置二级路由path时有两种方法,不加"/",或者加上。
//index.js-------
// 一级路由
import Book from 'vs/book.vue'
// 二级路由
import Er1 from "vs/er/er1.vue"
import Er2 from "vs/er/er2.vue"
import Er3 from "vs/er/er3.vue"
Vue.use(VueRouter)
const routes = [
{
path: '/book',
name: 'Book',
component: Book,
children:[
//path写法一:path:"不加斜杠"
{
path:"er1",name:"Er1",component:Er1},
{
path:"er2",name:"Er2",component:Er2},
//path写法二:path:"加斜杠"
{
path:"/er3",name:"Er3",component:Er3},
]
},
]
//实例化路由对象
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
3、设置二级路由的出口,必须设置在它所依赖的一级路由页面中。
//book.vue------
<template>
<div>
图书
<Erlink/>
<router-view/>
div>
template>
<script>
import Erlink from "%/erlink.vue"
export default {
components:{
Erlink
}
}
script>
4、设置二级路由的路由导航(声明式 || 编程式),然后导入一级路由界面中。
注意:
"/一级路径/二级路径"
"/二级路由路径"
//erlink.vue-------
<template>
<div class="er">
//路由规则配置时path:“不加斜杠”
<router-link to="/book/er1">er1router-link >
<router-link to="/book/er2">er2router-link >
//路由规则配置时path:“加斜杠”
<router-link to="/er3">er3router-link >
div>
template>
<style scope>
.er .router-link-active{
background: teal;
color:white;
}
style>
到此为止,运行程序,是能够展现出二级页面的。
但是,却不会自动展示首个二级路由组件的内容。想到了重定向,但有点麻烦,还有没有更简单的方法?可以设置一级路由导航的to属性,更改成二级路由的路径。
//原来的to属性路径
<router-link to="/book">图书router-link>
//如果index.js配置路由规则的path:"er1",没加斜杠;则更改成如下:
<router-link to="/book/er1">图书router-link>
//如果index.js配置路由规则的path:"/er3",加斜杠;则更改成如下:
<router-link to="/er3">图书router-link>
当我们一点开图书一级路由时,就会转到二级路由的相关路径组件页面。
二级路由展示的小栗子就先到这里了。
this.$route.query.name
和this.$route.params.name
。(1)创建一个数据展示组件页面,命名为getDate.vue,用于以后获取参数并展示出来。
(2)在index.js中配置路由规则。设置接收参数,在规则里面匹配传递的值。
//index.js-----
import GetData from "vs/getData.vue"
// 动态传参 路由匹配
{
path: '/getdata/:xiaoming',
name: 'GetData',
component: GetData
},
(3)在发送数据的页面绑定参数,比如首页。我这里是movie.vue,用的js方法发送参数。
//movie.vue-----
<template>
<div>
电影------------<br>
<button @click="push1()">点击查看 传递过去的数据button>
div>
template>
<script>
export default {
methods:{
push1(){
this.$router.push("/getdata/data参数");//发送参数
}
}
}
script>
(4)在getData.vue页面接收参数并展示数据。
//getData.vue-----
<template>
<div>
<button @click="back()">返回 <button>
<p>获得的数据1:{
{this.$route.params.xiaoming}}p>
div>
template>
<script>
export default {
methods:{
back(){
this.$router.go(-1);//返回到上一个页面,读取历史记录,不刷新页面
}
},
mounted() {
console.log(this.$route.params.xiaoming);
},
}
script>
params与query不同方式的总结及代码示例
友友的博客:动态路由传参、vue动态路由与vue路由传参
Promise是一种异步操作的解决方案,将写法复杂的传统的回调函数和监听事件的异步操作,用同步代码的形式表达出来。避免了多级异步操作的回调函数嵌套。
1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列
简书:Javascript 中的神器——Promise
MDN:Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值.
在处理多个有依赖关系的异步操作时,会出现回调地狱,且程序的可读性变差。
Promise是一个对象,它的内部其实有三种状态。
初始状态( pending )
已完成( fulfilled ): resolve 方法可以使 Promise 对象的状态改变成成功
已拒绝( rejected ): reject 方法则是将 Promise 对象的状态改变为失败
在项目的根路径下vue.config.js的文件中,添加下列代码,configureWebpack与devServer同级。
configureWebpack:{
resolve:{
alias:{
// "自定义别名":"所指向的路径";别名也可以用符号代替,比如&
"com":"@/components"
}
}
}
本篇介绍了axios数据请求封装,一级路由,二级路由,动态路由数据传参,另外还有promise的简介。
也有一些小技巧,比如改变全局跟组件的指向,自定义文件夹引用别名,404页面的路由跳转,路由重定向等。