1、vue简介
1.1简介
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式的js框架
,发布于 2014 年 2 月。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库(如:vue-router,vue-resource,vuex)或既有项目整合。
-
渐进式:明式渲染->组件系统->客户端路由->集中式状态管理->项目构建
-
官网:Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org)
-
优点:
-
易用: 熟悉HTML,CSS,JavaScript知识后,可快速上手Vue
-
灵活: 渐进式框架
-
高效: api20kb,加载快,内部虚拟DOM
-
-
vue2版本(2023.12停更)
-
作者 尤雨溪
1.2MVVM模式的实现者-双向数据绑定 模式
-
Model:模型层,在这里表示 JavaScript 对象
-
View:视图层,在这里表示 DOM(HTML 操作的元素)
-
ViewModel:连接视图和数据的中间件,Vue.js 就是 MVVM 中的 ViewModel 层的实现者
在 MVVM 架构中,是不允许 数据 和 视图 直接通信的,只能通过 ViewModel 来通信,而 ViewModel 就是定义了一个Observer观察者
-
ViewModel 能够观察到数据的变化,并对视图下对应的内容进行更新
-
ViewModel 能够监听到视图的变化,并能够通知数据发生改变
至此,我们就明白了,Vue.js 就是一个 MVVM 的实现者,他的核心就是实现了 DOM 监听
与 数据绑定
1.3其他MVVM实现者
-
AngularJS
简单介绍一下,AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购。是一款优秀的前端JS框架,已经被用于Google的多款产品当中。AngularJS有着诸多特性,最为核心的是:MVVM、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。
-
ReactJS
React引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。
-
微信小程序
微信小程序的视图层和数据层就是通过MVVM进行绑定的。
1.4为什么使用vue.js
-
轻量级,体积小是一个重要指标。Vue.js 压缩后有只有 20多kb (Angular 压缩后 56kb+,React 压缩后 44kb+)
-
移动优先。更适合移动端,比如移动端的 Touch 事件
-
易上手,学习曲线平稳,文档齐全
-
吸取了 Angular(模块化)和 React(虚拟 DOM)的长处,并拥有自己独特的功能,如:计算属性
-
开源,社区活跃度高
1.5vue.js的两大核心要素
1.51数据驱动
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。这里需要注意的问题是浏览器控制台在打印数据对象时 getter/setter 的格式化并不同,所以你可能需要安装 vue-devtools 来获取更加友好的检查接口。
每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新
1.5.2组件化
-
页面上每个独立的可交互的区域视为一个组件
-
每个组件对应一个工程目录,组件所需的各种资源在这个目录下就近维护
-
页面不过是组件的容器,组件可以嵌套自由组合(复用)形成完整的页面
2、vue的初体验
开发工具
-
VScode
-
HBuilder
-
WebStorm
-
IDEA
2.1在页面引入vue的js文件
注意:cdn是一种加速策略,能够快速的提供js文件
也可以自己下载到本地,自己引入vue.js
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
<!-- 官方的: 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
2.2准备dom
<!-- 创建一个div,id是app -->
<div id="app"></div>
2.3创建vue对象,设计对象的内容
其中该vue对象,绑定了页面中id是app的那个div
<script>
new Vue({
el:"#app",
data:{
title:"hello vue!",
nowdate:"hi!",
age:18,
flag:true
}
});
</script>
# el: element的简称,也就是Vue实例挂载的元素节点,值可以是 CSS 选择符,或实际 HTML 元素,或返回 HTML 元素的函数。
# data: 用于提供数据的对象,里面存放json数据
2.4 在页面的元素中使用插值表达式来使用vue对象中的内容
<div id="app">
{{ title }}
</div>
3、插值表达式
插值表达式是{{ }},即双花括号
3.0 运算
<div id="app">
{{ 1 + 1}}<br>
{{ 1 - 1}}<br>
{{ 2 * 2}}<br>
{{ 2 / 2}}<br>
{{ 2 +"--"+ 2}}<br> <!-- 字符串拼接 -->
{{ 2 > 1 ? "2大":"1大"}}<br>
</div>
3.1 取数据
插值表达式的可以是在View中获得Model中的内容
Model中的内容如下:
<body>
<div id="app">
{{ title }},
{{arr}},
{{user}},
{{user.age}},
{{user.username}}
</div>
</body>
<scrip>
new Vue({
el:"#app",
data:{
title:"hello world!",
arr:[11,22,33],
user:{
age:18,
username:"taotie"
}
},
methods:{
sayHello:function(){
return "hello vue";
}
}
});
</script>
3.2 获取数组中的内容
<div id="app">
{{arr[2]}}
</div>
此时,页面上会显示“33”,也就是数组中的第三个元素被获取。
3.3 获取对象中的属性
<div id="app">
{{ user.username }}
</div>
此时,页面上会显示“taotie”,也就是对象中username属性的值
3.4 调用Vue中的方法
<div id="app">
{{ fun1()}} <!-- 注意还要加参数列表() -->
{{ fun2(66) }}
</div>
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
<script>
new Vue({
el: "#app",
data: { // 定义数据
},
methods: { // 定义函数
// key:value
fun1 : function(){
alert("调用fun1执行")
console.log("fun1输出");
},
// 上面函数定义,有简化写法
fun2(a){
console.log("fun2输出" , a)
// 返回值在页面展现
return "fun22222"
}
}
})
</script>
调用了vue对象中的fun2方法,控制台输出内容,页面并展示了方法的返回值
。
4、vue对象总结
Vue.js通过加载js,实现对页面的快速渲染。vue封装的js该如何使用?
就必须了解MVVM双向数据绑定模式。Vue将视图层和数据层分离,通过MVVM建立视图层和数据层的连接。其中,插值表达式是一种连接方式,可以通过插值表达式以多种方式,快速的从数据层获取数据并展示在视图层上。数据层Vue对象,也是由很多部分组成,比如之前介绍的el,data,methods等,以及之后要介绍的mount,computed等。
5、vue的分支 v-if
5.1 v-if
Vue中的分支语句v-if非常好理解,逻辑跟Java中的if-else相同。v-if语句块包含以下内容:
-
v-if
-
v-else
-
v-else-if
接下来以一个简单例子即可理解:
从这个例子可以看出,vue对象中的data提供了分支的条件。根据条件,如果是true,则v-if的内容就会显示
,反之不显示
。
5.2 v-show
v-if和v-show之间有着看似相同的效果,但优化上却有区别。先看下面这个例子:
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<p v-show="rich">
有钱!
</p>
<p v-if="rich">
有钱!
</p>
<button type="button" @click="rich=!rich">今晚彩票开奖</button>
</div>
</body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
rich:false
},
methods:{
}
});
</script>
</html>
通过点击“今晚彩票开奖”按钮,能切换rich的值,此时发现,v-if和v-show的显示状态都会来回切换。看起来是一样的,但通过查看控制台代码发现,**v-show**实际会将p标签的css样式的**display属性设为none**来达到隐藏的效果。
而v-if是直接在页面上添加和删除p标签来达到效果,因此v-show在反复切换的应用场景下,效率比v-if更高
重点来了》》》》》》》》》
6、vue的循环 v-for
Vue中的循环关键字并没有Java的那么多,只有v-for,但用法上有多种。接下来我们来逐一介绍。
6.1 普通的for循环
我们需要定义数据源,然后通过v-for来遍历数据源,再使用插值表达式输出数据。
<body>
<div id="app">
<ul>
<!-- in是关键词,args是下方data中定义的数组,a是遍历出的结果变量 -->
<li v-for="a in args">{{a}}</li>
</ul>
</div>
</body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
args:[1,2,3,4,5,6]
}
});
</script>
在这个例子中,数据源提供了一个数组。视图层通过v-for来循环输出多个li标签,非常简单。
6.2 带着索引的for
<body>
<div id="app">
<ul>
<li v-for=" (a,i) in args" :key='i'>{{i}}{{a}}</li>
</ul>
</div>
</body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
args:[1,2,3,4,5,6]
}
});
</script>
(a,i) 顺序建议不要变,第一个就是遍历的得到的值,第二个就是下标
此时的i就是每次循环的循环变量 ,从0开始一直到元素个数-1
6.3 遍历对象数组填充表格【敲重点!!】
<body>
<div id="app">
<h3>for循环-遍历对象数组</h3>
<table border="2">
<tr>
<td>sid</td>
<td>sname</td>
<td>age</td>
<td>sex</td>
</tr>
<tr v-for="stu in stuArr" >
<td>{{stu.sid}}</td>
<td>{{stu.sname}}</td>
<td>{{stu.age}}</td>
<td>{{stu.sex}}</td>
</tr>
</table>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
<script>
var vue = new Vue({
el:"#app",
data:{
stuArr:[
{
sid:"2020101",
sname:"瑞虎",
age:23,
sex:"男"
},
{
sid:"2020102",
sname:"奇瑞",
age:24,
sex:"男"
},
{
sid:"2020103",
sname:"道奇",
age:24,
sex:"男"
},
{
sid:"2020103",
sname:"冠道",
age:24,
sex:"男"
}
]
}
})
</script>
</body>
页面效果
7、Vue的属性绑定【也是重点】
Vue提供了多个关键字,能快速的将数据对象中的值绑定在视图层中,即MVVM。
7.1 v-model
通过v-model将input标签的value值与vue对象中的data属性值进行绑定。
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model="title">
{{title}}
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
title:"hello vue"
}
})
</script>
</html>
此时input标签中加入了“v-model='title'
”,表示input的value值与vue对象data中的title属性绑定,当在input输入框中输入内容会实时修改title的值。于是{{title}}插值表达式能实时输出input输入框内的值。
页面效果如下:
7.2 v-bind
我们知道插值表达式是不能写在html的标签的属性内的,那如果一定要用vue中的属性作为html标签的属性的内容,就可以通过v-bind进行属性绑定。
换句话,使用v-bind,将html中其他属性都变成变量来绑定
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="app">
<!-- <input v-bind:type="dyncType">
<a v-bind:href="href">点击跳转</a>
<img v-bind:src="src"> -->
<input :type="dyncType">
<a :href="href">点击跳转</a>
<img :src="src">
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
dyncType:"radio",
href:"http://www.jd.com",
src:"../images/1.jpg"
}
})
</script>
</html>
这样,a标签内的href属性就可以使用vue对象中的属性值。
注意: v-bind也可以简写,使用冒号“:
”来代替。
<a v-bind:href='link'></a> 等价于==> <a :href='link'>
8、Vue的事件绑定【怎么还是重点】
8.1事件
语法:v-on:事件名称
可以简写为: @事件名称
注意: v-on都能绑定哪些事件? 其实vue并没提供什么事件,只是换了写法而已.所以之前原生js有哪些dom事件,现在vue就可以使用哪些事件
<button v-on:click="start()">开始</button>
<button @click="begin()">开始</button>
事件中触发的函数,在vue实例中的methods中进行定义,可以按照如下两种方式进行定义:
<script type="text/javascript">
var vue = new Vue({
el : "#app",
data: {
},
methods:{
// 方式1
// 函数名: function(参数)
start : function(){
},
// 方式2
// 函数名(参数)
begin(){
}
}
})
</script>
这里给大家一个练手的练习: 输入A,B值后,点击计算按钮,在结果处展示相加后的结果
输入A,B值后,点击计算按钮,在结果处展示相加后的结果
<div id="app">
<h3>简易加法计算器</h3>
<div>
数字A:<input type="text" v-model="valA"><br>
数字B:<input type="text" v-model="valB"><br>
<button v-on:click="add">计算</button>
结果:<span>{{result}}</span>
</div>
</div>
<script type="text/javascript" src="js/vue.min.js"></script>
<script type="text/javascript">
var app = new Vue({
el:'#app',
data:{
valA:0,
valB:0,
result:0
},
methods:{
add:function(){
this.result = parseInt(this.valA) + parseInt(this.valB);
}
}
});
</script>
扩展: 表单修饰符
练习中涉及到表单数据转字符串问题,获取的表单数据是字符串,需要使用parseInt()转成数字
vue提供了表单修饰符表单输入绑定 — Vue.js (vuejs.org)
其中: .number
,可以使表单的输入的数据直接就是数字,不需要再解析
<input v-model.number="age" type="number">
除了.number修饰符外,还有其他的修饰符, 比如.trim
.lazy
8.2 事件修饰符
事件处理 — Vue.js (vuejs.org)
.stop 阻止事件冒泡
.prevent 阻止默认行为
.capture 实现捕获触发事件的机制
.self 实现只有点击当前元素时候,才会触发事件处理函数,另外只会阻止自己身上冒泡行为的触发
.once 只触发一次事件处理函数
演示: 阻止事件冒泡行为
Vue阻止事件冒泡操作
演示: 阻止事件默认行为
8.3 按键修饰符
参考官方文档:按键事件处理 — Vue.js (vuejs.org)
演示: Vue按键修饰符,按下回车提交数据
9、计算属性: computed
9.1 什么是计算属性
计算属性的重点突出在
属性
两个字上(属性是名词),首先它是个 属性 其次这个属性有 计算 的能力(计算是动词
),这里的 计算 就是个函数;简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;
为什么要用,什么时候用计算属性?
当{{}}表达式内写很多复杂代码时使用计算属性来抽取代码
9.2 演示
官网演示很详细...计算属性 — Vue.js (vuejs.org)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
{{ message.split('').reverse().join('-') }}<br>
{{ message.split('').reverse().join('-') }}<br>
<hr>
{{reverseStr}}<br>
{{reverseStr}}
</div>
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
<script>
new Vue({
el:'#app' ,
data:{
message:'abcdef'
},
methods:{
sayHello(){
alert("hello")
}
},
computed:{ // 计算属性,理解: 将{{}}中重复的代码抽取,复用
reverseStr(){
return this.message.split('').reverse().join('*')
}
}
})
</script>
</body>
</html>
9.3 计算属性与方法的区别
看下面这个例子
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>布局篇 计算属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head>
<body>
<div id="vue">
<p>调用当前时间的方法:{{currentTime1()}}</p>
<p>当前时间的计算属性:{{currentTime2}}</p>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#vue',
data: {
message: 'Hello Vue'
},
methods: {
currentTime1: function () {
return Date.now();
}
},
computed: {
currentTime2: function () {
return Date.now();
}
}
});
</script>
</body>
</html>
说明
-
methods:定义
方法
,调用方法使用 currentTime1(),需要带括号,每次都会重新执行 -
computed:定义计算
属性
,调用属性使用 currentTime2,不需要带括号;
注意:methods 和 computed 里不能重名
测试效果
仔细看图中说明,观察其中的差异
9.4 结论
调用方法时,每次都需要进行计算
,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这一点;计算属性的主要特性就是为了将不经常变化的计算结果进行缓存
,以节约我们的系统开销
计算属性的执行时机是在created钩子函数之前执行!且只执行一次!
-
函数每次调用都会执行
-
计算属性是页面加载时执行一次,后续每次调用都是之前的值不再计算
10、vue的组件化
Vue的组件化设计思想借鉴了Java的面向对象思想。Java认为万物皆对象,在Vue中,万物皆组件。
也就是说,在实际的vue项目中,以及使用了Vue框架的项目中,Vue的对象都会以组件的形式出现,能被反复使用
。
要想实现组件化,需要在页面中注册组件:关于注册的方式有两种,分别是全局注册
和本地注册
。
组件其实就是页面内的部分代码,完成某个功能
10.1 组件的全局注册
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue组件的全局注册</title>
</head>
<body>
<div id="app">
<model1></model1>
<model1></model1>
<model1></model1>
</div>
<hr/>
<div id="app1">
<model1></model1>
<model1></model1>
<model1></model1>
</div>
</body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script>
//通过Vue.component实现组件的全局注册,全局注册后的组件可以被重复使用。
Vue.component("model1",{
template:"<div><h1>{{title}}</h1><button type='button' @click='btnfn'>点我</button></div>",
data:function(){
return {
title:"hello vue"
}
},
methods:{
btnfn:function(){
alert("hello !!!");
}
}
});
new Vue({
el:'#app'
})
new Vue({
el:'#app1'
})
</script>
</html>
10.2 组件的本地注册
vue的全局注册,也就意味着在页面的任意一个被vue绑定过的div中,都可以使用全局注册了的vue组件。
但是,如果是对vue组件进行本地注册,那么在其他被vue绑定的div中,不能使用该组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue组件的本地(局部)注册</title>
</head>
<body>
<div id="app">
<model11></model11>
</div>
<hr/>
<!--在这里使用组件model11会报错-->
<div id="app1">
<model11></model11>
</div>
</body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script>
new Vue({
el:'#app',
components:{
"model11":{
template:"<div><h1>{{title}}</h1><button type='button' @click='btnfn'>点我</button></div>",
data:function(){
return {
title:"hello vue"
}
},
methods:{
btnfn:function(){
alert("hello !!!");
}
}
}
}
})
new Vue({
el:'#app1'
})
</script>
10.3 注意特性【重点】
-
组件是一段完整的页面代码,包括html标签,css样式,js数据和函数
-
组件要设置名字,使用时是将名字作为标签使用
-
componet中注册的组件中的data,必须是以
函数的形式
,且return返回对象
如下:
data:function(){
return {
title:"hello vue"
}
}
// 简化成
data(){
return {
title:"hello vue"
}
}
-
template标签内,必须有且
只能有一个根标签,且一般都是div标签
。 -
template支持模板字符串
11、Vue-Cli搭建Vue项目
11.1 什么是vue-cli
cli: Command Line 命令行工具,vue-cli就是vue的命令行工具,也称之为脚手架
,使用vue-cli提供的各种命令可以拉取、创建、运行我们需要使用到的框架,比如webpack、Element UI、Element Admin等等。那么要想使用vue-cli命令,需要先安装node.js
。
11.2 node.js的介绍及安装
node.js的介绍
node.js提供了前端程序的运行环境,可以把node.js理解成是运行前端程序的服务器。
node.js的安装
从官网下载安装即可: 下载 | Node.js 中文网
不要勾选这个,否则会下载很多东西
测试node.js是否安装成功: 在DOS窗口中输入“node -v” 查看版本,如果看到版本,就表示安装成功。(环境变量已经自动配置好)
node -v 是 查看node的版本
npm -v 是 查看npm版本
npm是安装工具的工具包,类似于Linux中yum,Linux中安装软件 yum install ,node中安装软件使用npm install
设置npm源 , 配置镜像后,下载资源就会很快.
npm config set registry https://registry.npmmirror.com
11.3使用node.js安装vue-cli
(管理员权限)使用如下命令安装vue-cli
npm install @vue/cli -g
# 如果出错,可以卸载,重新执行上一步安装
npm uninstall @vue/cli -g
-
npm: 使用node.js的命令
-
install: 安装
-
@vue/cli: 要安装的vue-cli
-
-g: 全局安装
当出现以下界面,表示正在安装:
安装vue-cli检测
11.4使用vue-cli命令创建项目
进入工作空间,执行命令创建
-
vue create 项目名
注意bug: 创建项目时如果出现报错,提示no permitted
即没有权限在此处创建项目,这个是因为磁盘权限不够,需要修改硬盘权限
选择具体features
选择vue版本
一般选择第一项,为的是将文件分离打包
是否将此操作存储为模板,本例选择n,选择为y就会在下次创建时使用
创建完毕
运行项目
11.5项目结构
文件名 | 解释 |
---|---|
build | webpack的一些配置 |
config | 不同环境的配置,比如开发环境,生产环境等 |
node_modules | npm install下载的依赖包 |
public | 用于存放公共js文件夹、json文件和图片等 |
dist | 存放项目打包后的文件 |
src | 项目的源码 |
src/assets | 存放静态资源文件,如图片等 |
src/components | 存放公共组件 |
src/router | 静态路由表 |
src/store | vuex |
src/views | 开发的页面资源,路由页面相关的 |
src/main.js | 对应App.vue创建vue实例,也是入口文件 |
src/App.vue | 入口页面 |
gitignore | git管理时,忽略的文件或文件夹 |
package.json | 项目的核心配置记录,可以查看当前安装依赖的版本号 |
index.html | 首页的入口 |
vue.config.js | 可选的配置文件,存放在根目录中,@vue/cli-service 启动的时候会自动加载 |
可以在package.json中修改端口
11.7启动项目
进入项目,使用命令行输入npm run serve
启动
12、idea开发vue
idea中安装Vue插件
然后使用idea打开之前创建的vue项目即可
ps: 也可使用idea直接创建vue项目,但是创建的vue版本默认为Vue3,无法改成vue2,暂时先不使用
BUG总结
cmd中可以启动vue项目,但是idea中的终端无法执行npm run serve启动项目,提示npm不是内部或外部命令
解决方案: 以管理员身份启动idea,打开项目运行
12、单文件组件
12.1介绍
以前
在很多 Vue 项目中,我们使用
Vue.component
来定义全局组件,紧接着用new Vue({ el: '#app'})
在每个页面内指定一个容器元素。这种方式在很多中小规模的项目中运作的很好,在这些项目里 JavaScript 只被用来加强特定的视图。但当在更复杂的项目中,或者你的前端完全由 JavaScript 驱动的时候,下面这些
缺点
将变得非常明显:
全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复
字符串模板 (String templates) 缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的
\
不支持 CSS (No CSS support) 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
没有构建步骤 (No build step) 限制只能使用 HTML 和 ES5 JavaScript,而不能使用预处理器,如 Pug (formerly Jade) 和 Babel
现在
文件扩展名为
.vue
的 single-file components (单文件组件) 为以上所有问题提供了解决方法,并且还可以使用 webpack 或 Browserify 等构建工具。单文件组件的组成结构:
template 组件的模块区域(html)
script 业务逻辑区域(js)
style 样式区域(css)
12.2使用
在工程的src/components下创建一个TestSingeVuePage.vue单文件
ps: 命名规则 驼峰版TestSingeVuePage 或者 test-single-vue
填入内容
<template>
<div>
<h1 class="red">这是测试单vue文件组件</h1>
<h3>{{info}}</h3>
<button @click='show()'>show</button>
</div>
</template>
<script>
export default {
name: "TestSingleVuePage",
data:function (){
return {
info:"data-信息"
}
},
methods:{
show(){
alert("单页面内弹出...")
}
}
}
</script>
<style scoped>
.red {
color: red;
}
</style>
注册组件
-
哪里注册? 哪个组件需要使用另一个组件,就在哪注册!
-
例如: A.vue需要使用B.vue的组件内容
-
就在A.vue中
1)导入B组件
,2)注册组件
,3)使用组件
-
-
例如: 下面演示在App.vue文件内注册组件
使用组件
-
在App.vue页面的template内使用组件
启动测试
13、vue组件间的参数传递
13.1父传子
通过子组件的props部分,来指明可以接收的参数,父组件通过在标签中写明参数的键值对来传递参数。
props是表示一个组件的参数部分,那么props的写法有两种:
1)props:[参数列表]
比如: props:['MyProp1','MyProp2',...]
2)props:{参数名1:{type:String,required:true,default:'XX'},参数名2:{...}}
创建子组件,设置参数 等待父组件给其传值
<template>
<div>
<h1>这是 子组件</h1>
<span>{{name}}</span> --
<span>{{age}}</span> --
<span>{{sex}}</span>
</div>
</template>
<script>
export default {
name: "MySon",
props:{
name: {
// 类型
type: String,
// 默认值
default: '无名'
},
age: Number,
sex: Boolean
}
}
</script>
<style scoped>
</style>
创建父组件,给子组件传值
<template>
<div>
<h1>这是 父组件 </h1>
<!-- 父组件使用子组件 -->
<!--
可以通过 v-bind 动态赋值,比如 v-bind:name="",
也可以简写:age=""
也可以静态赋值,比如 messages="" , 注意没有冒号
-->
<MySon v-bind:name="username" :age="age" sex="true"></MySon>
</div>
</template>
<script>
import MySon from "@/components/MySon";
export default {
name: "MyFather",
components: {
MySon
},
data: function () {
return {
username: "小儿砸",
age: 18
}
}
}
</script>
<style scoped>
</style>
在App.vue注册父组件并使用父组件演示效果即可
注意:props支持的类型:String、Number、Boolean、Array、Object、Date、Function、Symbol
13.2子传父
使用组件中的props属性是无法完成子组件向父组件传值的,在Vue的设计中,props是单向数据流,只能是父组件通过props向子组件传递数据.
那么,如果需要子组件向父组件传递值该如何做?
-
Vue提供了方案: 在子组件中使用自定义事件向父组件传递数据.
具体步骤
-
子组件定义一个函数,通过事件触发函数,函数内通过$emit 函数将数据发给父组件
this.$emit('父组件中的函数名', 数据)
-
父组件在使用子组件的时候,通过@emit中的函数名绑定数据,然后再将接收到数据传递给父组件自己的函数即可
子组件
<template>
<div>
<h1>这是 子组件2</h1>
<button @click="sendNum">子组件将值num=10传递给父组件</button>
</div>
</template>
<script>
export default {
name: "MySon2",
props: {},
data: function () {
return {
num: 10
}
},
methods: {
sendNum() {
// 触发父组件的事件,同时给事件传参
this.$emit('addFun', this.num)
}
}
}
</script>
<style scoped>
</style>
父组件
<template>
<div>
<h1>这是 父组件2 </h1>
<span>sum = {{sum}}</span>
<MySon2 @addFun="addSum"></MySon2>
</div>
</template>
<script>
import MySon2 from "@/components/MySon2";
export default {
name: "MyFather2",
components: {
MySon2
},
data: function () {
return {
sum: 0
}
},
methods:{
addSum(v){
this.sum += v;
}
}
}
</script>
<style scoped>
</style>
在App.vue注册父组件并使用父组件演示效果即可
14 、Vue-router 路由
14.1介绍
路由的本质就是一种对应关系,比如说我们在url地址中输入我们要访问的url地址之后,浏览器要去请求这个url地址对应的资源。
那么url地址和真实的资源之间就有一种对应的关系,就是路由。
路由分为前端路由和后端路由
1)后端路由是由服务器端进行实现,并完成资源的分发(我们之前的项目)
2)前端路由是依靠hash值(锚链接)的变化进行实现 (vue官网就是使用这种)
前端路由的基本概念: 根据不同的事件来
显示不同的页面内容,即事件与事件处理函数之间的对应关系 前端路由主要做的事情就是监听事件并分发执行事件处理函数
14.2 vue的路由
Vue默认属于单页面的程序,主要通过URL中的hash来实现不同页面之间的切换。这种切换方式称作前端路由。
Vue Router的核心作用
跳转/切换页面
-
声明式(写标签)
<router-link to="要跳转的组件名称">
-
编程式(写代码)
this.$router.push("要跳转的组件名称")
-
跳转携带数据
-
编程式导航实现传递参数
-
传递 this.$router.push({path:'路径',params:{参数名:值,...}})
-
接收 this.$router.params.参数名
-
-
-
路由模式
-
hash模式:监听浏览器地址hash值变化,执行相应的js切换网页;
-
history模式:利用history API实现url地址改变,网页内容改变;
-
它们最明显的区别就是hash会在浏览器地址后面增加#号
-
14.3安装路由模块
介绍 | Vue Router (vuejs.org)
npm install vue-router
# 如果报错,可能是npm版本过高,存在兼容性问题,那么使用如下命令
npm install --legacy-peer-deps vue-router@3.5.2
npm install --legacy-peer-deps vue-router@3.1.3
14.5声明式路由
14.5.1创建MyInfo.vue
14路由页面建议创建在src/views/下
<template>
<div>
<h1>个人中心</h1>
</div>
</template>
<script>
export default {
name: "MyInfo"
}
</script>
<style scoped>
</style>
14.5.2创建Admin.vue
<template>
<div>
<h1>主页</h1>
<p>主页</p>
<p>主页</p>
<p>主页</p>
<p>主页</p>
<p>主页</p>
<p>主页</p>
<p>主页</p>
<p>主页</p>
</div>
</template>
<script>
export default {
name:'Admin'
}
</script>
<style scoped>
</style>
14.5.3创建静态路由表
在/src下创建router文件夹,
在/src/router/创建index.js文件
填充以下内容
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '../components/HelloWorld'
import MyInfo from "../views/MyInfo";
Vue.use(Router)
// export是导出路由对象,只有在这里导出了,main.js文件头上面才能 import 导入
export default new Router({
routes: [
{
path: '/', // 匹配<router-link to="">中的路径
name: 'HelloWorld', // 这个name属性可写可不写
component: HelloWorld // 要跳转的组件对象
},
{
path: '/MyInfo',
name: 'MyInfo',
component: MyInfo
}
],
// mode: 'history'
mode: 'hash'
})
14.5.4main.js引入路由模块并使用
在main.js中引入路由模块并使用
import Vue from 'vue'
import App from './App'
import router from './router' //引入上一步导出的路由模块,并设置名字为router
Vue.config.productionTip = false
new Vue({
render: h => h(App),
// router:router // 使用路由,可以简写为router
router
}).$mount('#app')
14.5.5App.vue使用路由
<template>
<div id="app">
<ul>
<li>
<!--
<router-link>用于导航,其实就是a标签
to表示要跳转的资源的路径
tag 将router-link渲染成想要的原生标签,默认是a标签,可以改成button
-->
<router-link to="/" tag="button">首页</router-link>
</li>
<li>
<router-link to="/MyInfo">个人信息</router-link>
</li>
</ul>
<!-- router-view 路由填充位,要跳转的组件在此展示,位置任意 -->
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
14.6编程式路由
刚才演示的是声明式路由,也可以使用编程式路由
创建公告页Note.vue
<template>
<div>
<h1>公告页面</h1>
<ol>
<li>老杨不瞌睡了</li>
<li>萌萌也+1</li>
<li>相宇明天好好做操</li>
</ol>
</div>
</template>
<script>
export default {
name: "Note"
}
</script>
<style scoped>
</style>
src/router/index.js 设置路由规则
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/MyInfo',
name: 'MyInfo',
component: MyInfo
},
{
path: '/Note',
name: 'Note',
component: Note
}
],
// mode: 'history'
mode: 'hash'
})
App.vue设置标签,绑定事件,事件触发函数,函数内编写代码实现路由
this.$router.push("/路径") --> <router-link to="/路径">
this.$router.push("/Note")
// 注意!!!!别写错,有个叫做this.$route
14.7参数的传递
14.7.1声明式路由传参
演示App.vue中将数据传递给MyInfo.vue
在路由表中设参
export default new Router({
routes: [
...
{
path:'/MyInfo/:id', //设参
component:MyInfo
}
]
})
在App.vue中传参
<template>
<div id="app">
<ul>
<li>
<router-link to="/" tag="button">首页</router-link>
</li>
<li>
<!-- 跳转至MyInfo,并携带id 1001 -->
<router-link to="/MyInfo/1001">个人信息</router-link>
</li>
</ul>
<!-- router-view 用于显示匹配的组件,类似显示路由到的组件的区域,位置任意 -->
<router-view/>
</div>
</template>
<script>
...
</script>
<style>
...
</style>
在MyInfo.vue中接参
<template>
<div>
<h1>个人信息</h1>
<span>id-->{{id}}</span>
</div>
</template>
<script>
export default {
name: "EmployeeList",
data:function(){
return {
id:this.$route.params.id // 注意是$route不是$router
}
}
}
</script>
<style scoped>
</style>
14.7.2编程式路由传参
演示App.vue中将数据传递给Note.vue
App.vue的编程跳转js中设置要传递的数据
methods:{
toNote(){
//this.$router.push("/Note")
this.$router.push({path:"/Note",query:{username:'老王'}})
}
}
Note.vue中接收参数
<template>
<div>
<h1>网站公告</h1>
<span>id --> {{id}}</span>
</div>
</template>
<script>
export default {
name: "Note",
data:function(){
return {
id:this.$route.query.username
// 注意是query,因为是按照路径方式发送,注意查看浏览器url
}
}
}
</script>
14.8嵌套路由
嵌套路由 | Vue Router (vuejs.org)
多层多级组件嵌套时的路由
需求: 在个人中心组件中,再设置三个链接,可以点击切换[头像|家庭信息|学校信息]
创建三个组件页面Touxiang.vue,Family.vue,School.vue
在MyInfo组件中设置路由链接发出请求路径,并且设置路由填充位
<template>
<div>
<h1>个人中心</h1>
<h3>id = {{id}}</h3>
<!-- /my/tx-->
<!-- /my/family-->
<!-- /my/school-->
<router-link to="/my/tx">头像</router-link>|
<router-link to="/my/family">家庭信息</router-link>|
<router-link to="/my/school">学校信息</router-link>|
<router-view></router-view>
</div>
</template>
在router/index.js中设置myinfo组件的子路由
{
path:'/my',
name:'MyInfo',
component:MyInfo,
children:[
// 子路径要与父类拼接成完整路径,此处不需要加/
{ path:'tx',component:Touxiang},
{ path:'family',component:Family},
{ path:'school',component:School},
]
},
如果有路径中有数据的话,子组件一样可以取值
<!-- MyInfo.Vue-->
<template>
<div>
<h1>个人中心</h1>
<h3>id = {{id}}</h3>
<!-- /my/tx-->
<!-- /my/family-->
<!-- /my/school-->
<router-link to="/my/1001/tx">头像</router-link>|
<router-link to="/my/1002/family">家庭信息</router-link>|
<router-link to="/my/1003/school">学校信息</router-link>|
<router-view></router-view>
</div>
</template>
{
path:'/my/:id',// :id是用来匹配 路由路径中的变量的
name:'MyInfo',
component:MyInfo,
children:[
// 子路径要与父类拼接成完整路径
{ path:'tx',component:Touxiang},
{ path:'family',component:Family},
{ path:'school',component:School},
]
},
子组件Touxiang.vue,Family.vue,School.vue中可以使用this.$route.params.id
取出路径中的数据1001,1002,1003
15、vuex
15.1什么是vuex
Vuex 是什么? | Vuex (vuejs.org)
Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式
。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
说人话: 实现多个组件的数据共享
,即一个数据需要在多个组件中使用,那么就需要把这个数据存储在VueX中
Vuex五大核心要素
-
state
:存放状态,比如需要全局共享的数据 -
getters:可以对state中的数据进行额外处理,类似计算属性的作用
-
mutations
:通过提交mutations来改变state的状态 -
actions:异步的mutations,可以通过dispatch调用mutaitons,从而改变state
-
modules:模块化状态管理,每个模块拥有自己的 state、mutation、action、getter
Vue组件通过dispatch调用Vuex中actions的方法,进行异步操作。
actions中的方法中,通过commit,调用mutations中方法,以保证state中数据的同步
如果不需要异步操作,可以直接在组件通过commit调用mutations中的方法对state中共享的数据进行操作。
15.2 安装
在项目根目录执行如下命令来安装 Vuex
若失败,可使用cnpm
# 本例使用的vue2,所以安装vuex装的是vuex3!!! vue3对应的Vuex4
npm install vuex@3
15.3配置vuex
在 src 目录下创建一个名为 store 的目录并新建一个名为 index.js 文件用来配置 Vuex,代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
}
})
修改 main.js 增加刚才配置的 store/index.js,关键代码如下:
import Vue from 'vue'
import App from './App.vue'
// 引入路由模块
import router from './router'
// 引入Vuex模块
import store from './store'
Vue.config.productionTip = false
// vue2 创建方式
new Vue({
render: h => h(App),
router,
store // 使用Vuex
}).$mount('#app')
-
一个是路由Router,一个是状态管理Vuex
15.4演示
15.4.1存&取
-
在Vuex中设置数据,在任何组件取出
// store/index.js文件的state中定义数据
export default new Vuex.Store({
state: {
username:"无名",
count:443,
tga:"tga"
},
mutations: {
}
})
在任何组件中使用 以下命令取值
this.$store.state.username
// username是state中定义的key
15.4.2计算属性使用state
<template>
<div>
计算属性取值:{{num}}
</div>
</template>
<script>
export default {
name: "TestVueX",
computed:{ // 【注意: 计算属性的写法】
num() {
return this.$store.state.count
}
}
}
</script>
重要用法: state中的数据要放在组件的computed中而不是data中!
为什么?
这是因为data 中的内容只会在 created 钩子触发前初始化一次,具体来说就是data中设置count: this.$store.state.count则count的值是created钩子执行前this.$store.state.count的值,赋值之后属性的值就是纯粹的字面量,之后this.$store.state.count 如何变化均影响不到count的取值。而 computed 则是通过依赖追踪实现的,计算属性在它的相关依赖发生改变时会重新求值。
简而言之就是说,Vuex存储的数据如果有变化,computed中的数据就会变化,但是data中的不会变化
15.4.3 mapState
当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState
辅助函数
帮助我们生成计算属性
<template>
<div>
计算属性取值:{{count}}|
计算属性取值:{{tga}}|
计算属性取值:{{username}}|
</div>
</template>
<script>
// 【注意】 是 {} 引入
// 使用 import mapState from 'vuex' 的方式会将整个 vuex 模块导入,并将其中的 mapState 函数赋值给 mapState 变量。
// 而使用 import { mapState } from 'vuex' 的方式则是只导入 vuex 模块中的 mapState 函数
import {mapState} from 'vuex'
export default {
name: "TestVueX",
// computed:mapState({
// count: function (state) {
// return state.count
// }
// }),
// 如果使用和状态名一样的计算属性名,还可以这样写
// 映射 this.count 为 store.state.count
// computed: mapState(['count','tga','username']),
// 如果有其他的计算属性,并且需要将vuex的state与其混合使用
// 可以使用对象展开运算符'...'
computed: {
// 使用对象展开运算符将此对象混入到外部对象中
// 映射为当前组件的计算属性
...mapState(['count','tga','username']),
},
}
</script>
<style scoped>
</style>
15.4.4 修改数据
-
在任何组件中修改Vuex中的数据
// store/index.js文件的mutations中定义方法修改数据
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
username:"无名"
},
mutations: {
// 参数1 是Vuex-state对象
// 参数2 是其他组件使用时传过来的值,这个参数叫做payload
updateName(state,v){
state.username = v // 修改Vuex中的值
}
}
})
在其他组件中通过事件触发函数,在其中使用Vuex的方法修改数据
<template>
<div id="app">
<!-- 演示Vuex取值 -->
<h1>Vuex --> {{ username }}</h1>
<input v-model="username">
<button @click="editName">修改vuex中的值</button>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: 'App',
methods: {
editName(){
// 修改Vuex数据
// updateName是 src/store/index.js中mutations中定义的函数名
this.$store.commit('updateName', this.username)
}
},
data: function () {
return {
// 从Vuex中取出数据 , 这里数据是不会根据变化而变化,要使用计算属性取值
username1: this.$store.state.username
}
},
// 这里可以追踪到最新的变化
computed:mapState(['username'])
}
</script>
Vue总结
基本语法
插值表达式,用来取出data或者computed中的数据,也可以在其中做运算,甚至调用函数
v-if,v-show 用来决定标签是否展现(场景:分页按钮,权限菜单按钮)
v-for 用来遍历生成表格数据
v-model和v-bind,用来绑定变量,实现双向绑定(数据变化)
v-on或者@ ,用来事件绑定
特性
计算属性
什么时候需要用? 当需要对data中数据运算且重复使用该运算结果时就可以将运算定义在计算属性
侦听器(自学)
组件化
一套完整的代码,包含html,css,js
将代码抽取封装,独立,方便使用和维护,可以实现spa开发
需要特殊语法
template里面只能一个根标签,一般都是div
js中需要使用export将代码内容导出
js中data中的数据需要定义在函数的return中
vue工程化
会使用vue-cli脚手架创建项目
熟悉项目结构
src
asstes 静态资源
components 公共的组件
router 路由表
store vuex管理数据状态
views 路由的页面
App.vue 主页面
main.js 主配置文件
package.json 定义运行脚本,修改端口
node_modules 定义了一些项目运行需要的依赖,一般别人的项目都删除了,我们要运行需要先执行npm install把这些依赖下载
需要掌握路由技术router
页面切换就需要路由
编程式路由
声明式路由
数据共享技术 vuex
当 存储数据时定义vuex中的state存储即可
补充Axios
1 什么是 Axios
Axios 是一个开源的可以用在浏览器端和 NodeJS 的异步通信框架,它的主要作用就是实现 AJAX 异步通信,其功能特点如下:
-
从浏览器中创建 XMLHttpRequests
-
从 node.js 创建
http 请求
-
支持 Promise API
-
拦截请求和响应
-
转换请求数据和响应数据
-
取消请求
-
自动转换 JSON 数据
-
客户端支持防御 XSRF(跨站请求伪造)
-
官网基本用例 | Axios 中文文档 | Axios 中文网 (axios-http.cn)
由于 Vue.js 是一个 视图层框架 并且作者(尤雨溪)严格准守 SoC (关注度分离原则),所以 Vue.js 并不包含 AJAX 的通信功能,为了解决通信问题,作者单独开发了一个名为 vue-resource 的插件,不过在进入 2.0 版本以后停止了对该插件的维护并推荐了 Axios 框架
2 Axios的使用
2.1 安装vue axios
npm install --save axios vue-axios
2.2 在需要使用的页面中引入
比如UserInfo.vue页面需要发请求,那就在页面的script中引入即可
import axios from 'axios'
2.3 发送ajax请求
<template>
<div>
<button @click="getInfo">查询数据</button>
<hr>
{{deptList}}
<hr>
<table>
<th>
部门编号
</th>
<th>
部门名称
</th>
<th>
部门地址
</th>
<tr v-for="dept in deptList">
<td>{{dept.deptno}}</td>
<td>{{dept.dname}}</td>
<td>{{dept.loc}}</td>
</tr>
</table>
</div>
</template>
<script>
// 引入axios
import axios from 'axios'
export default {
name: "TestAxios",
data(){
return {
deptList:null
}
},
methods:{
getInfo(){
// axios.get('/api/dept').then(function(ret){
// console.log(ret)
// this.deptList = ret.data // 【有bug,因为this问题】
// })
axios.get('/api/dept').then((ret)=>{
console.log(ret) // 【注意:这个返回值不一般】
// 详情请见19.4章节【19.4 Axios的响应】
// 可以查看官网https://www.axios-http.cn/docs/res_schema
this.deptList = ret.data.data
})
}
}
}
</script>
<style scoped>
</style>
2.4 服务端解决跨域问题
SpringBoot的controller层类上添加@CrossOrigin
注解即可
2.5 BUG
在axios的回调中,无法使用this.数据
获得vue data中的数据
造成axios取不到值得原因主要是this回调问题。当执行完函数function时,this指向放生变化。导致this指向函数体本身。这时this.data里的数据取不到。
简单直接的解决就是把function写成箭头函数
形式,箭头函数不是构造函数,不会指定this,而是抓取上下文this作为自己的this
3 其他api演示
可以查看官网请求配置 | Axios 中文文档 | Axios 中文网 (axios-http.cn)
也可以看示例
<!-- get请求(1) 路径拼接参数 -->
axios.get('http://localhost:8080/vue/user?id=456').then(function(ret){
console.log(ret.data);
})
<!-- get请求(2) Restful风格参数 -->
axios.get('http://localhost:8080/vue/user/123').then(function(ret){
console.log(ret.data.);
})
<!-- get请求(3) 使用params传递参数 -->
axios.get('http://localhost:8080/vue/user',{
params:{
id:20001
}
}).then(function(ret){
console.log(ret.data);
})
<!-- post请求,发送的是json,后台需要使用@RequestBody -->
axios.post('http://localhost:8080/vue/user/json',{
username:'张三',
password:'987654'
}).then(function(ret){
console.log(ret.data);
})
<!-- put请求 -->
axios.put('http://localhost:8080/vue/user/form',{
username:'张三丰',
password:'11111'
}).then(function(ret){
console.log(ret.data);
}).catch(function (err){
console.log(err)
})
4 Axios的响应
官网: 响应结构 | Axios中文文档 | Axios中文网
响应结果的主要属性:
-
data: 服务器响应回的数据
-
headers: 响应头信息
-
status: 响应状态码
-
statusText: 响应状态信息
需要特别注意,我们后台返回的数据在data中,即data中是后台返回的R,我们ret.data获得到的是R,如果还有继续获得其中的数据,还需要再ret.data.data
5 axios的全局配置
官网: 默认配置 | Axios 中文文档 | Axios 中文网 (axios-http.cn)
我们讲一个特别实用的,我们在项目中调用数十次乃至百次接口是很常见的,后期一旦根域名发生改变,所有接口都需要修改,非常繁琐且容易出错。
axios提供了设置根域名的方法。 在
main.js
全局入口文件中,设置:
import axios from "axios";
axios.defaults.baseURL = 'http://localhost:8888'
在其他vue页面中使用axios发请求的时候
axios.get('/api/dept').then((ret)=>{
console.log(ret)
this.deptList = ret.data.data
})
6 响应拦截
响应拦截可以拦截到axios发请求后的那个回调response对象,然后对其进行处理
将response数据简化后返回
// 添加Axios响应拦截器
axios.interceptors.response.use(function (response) {
//console.log('响应拦截',response)
return response.data;
}, function (error) {
console.log(error)
});
这样,在使用axios的页面,从回调中获得数据时,只需要ret.data,而不需要再ret.data.data