认识Vue.js
Vue (读音 /vjuː/,类似于 view),不要读错。
Vue是一个渐进式的框架,什么是渐进式的呢?
渐进式意味着你可以将Vue作为你应用的一部分嵌入其中,带来更丰富的交互体验。
或者如果你希望将更多的业务逻辑使用Vue实现,那么Vue的核心库以及其生态系统。
比如Core+Vue-router+Vuex,也可以满足你各种各样的需求。
Vue有很多特点和Web开发中常见的高级功能 :
解耦视图和数据
可复用的组件
前端路由技术
状态管理
虚拟DOM
Vue.js安装
安装Vue的方式有很多:
方式一:直接CDN引入
你可以选择引入开发环境版本还是生产环境版本。
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
方式二:下载和引入。
开发环境 https://vuejs.org/js/vue.js
生产环境 https://vuejs.org/js/vue.js
方式三:NPM安装
后续通过webpack和CLI的使用。
Vue中的MVVM
什么是MVVM呢? 通常我们学习一个概念,最好的方式是去看维基百科(对,千万别看成了百度百科) https://zh.wikipedia.org/wiki/MVVM
我们直接来看Vue的MVVM。
View层:
视图层 在我们前端开发中,通常就是DOM层。
主要的作用是给用户展示各种信息。
Model层:
数据层 数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。
VueModel层:
视图模型层 视图模型层是View和Model沟通的桥梁。
一方面它实现了Data Binding,也就是数据绑定,将Model的改变实时的反应到View中 。
另一方面它实现了DOM Listener,也就是DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data。
创建Vue实例传入的options
options中可以包含哪些选项呢? 详细解析: https://cn.vuejs.org/v2/api/#%E9%80%89%E9%A1%B9-%E6%95%B0%E6%8D%AE
el:
类型:string | HTMLElement
作用:决定之后Vue实例会管理哪一个DOM。
data:
类型:Object | Function (组件当中data必须是一个函数)
作用:Vue实例对应的数据对象。
methods:
类型:{ [key: string]: Function }
作用:定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中使用。
Vue的生命周期
基础语法
Mustache
将data中的文本数据,插入到HTML中, 可以通过Mustache语法(也就是双大括号)。
<h2>{{message}}</h2>
v-once
v-once:
该指令后面不需要跟任何表达式。
该指令表示元素和组件只渲染一次,不会随着数据的改变而改变。
<h2 v-once>{{count}}</h2>
v-html
某些情况下,我们从服务器请求到的数据本身就是一个HTML代码 ,如果我们直接通过{{}}来输出,会将HTML代码也一起输出。
但是我们可能希望的是按照HTML格式进行解析,并且显示对应的内容。 如果我们希望解析出HTML展示,可以使用v-html指令。
该指令后面往往会跟上一个string类型,会将string的html解析出来并且进行渲染 。
<div id="demo">
<h2 v-html="url">{{message}}</h2>
</div>
<script>
const app=new Vue({
el:'#demo',
data:{
url:`<a href='http://www.baidu.com'>百度一下</a>`
}
})
</script>
v-text
v-text作用和Mustache一致。
v-text通常情况下,接受一个string类型。
<div id="demo">
<h2 v-text="url">{{message}}</h2>
<h2>{{message}}</h2>
</div>
<script>
const app=new Vue({
el:'#demo',
data:{
message:'你好'
}
})
</script>
v-pre
v-pre用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法。
比如下面的代码:
<div id="demo">
<h2 v-pre="url">{{message}}</h2>
<h2>{{message}}</h2>
</div>
<script>
const app=new Vue({
el:'#demo',
data:{
message:'你好'
}
})
</script>
第一个h2元素中的内容会被编译解析出来对应的内容
第二个h2元素中会直接显示{{message}}
v-cloak
当网络较慢,网页还在加载 Vue.js ,而导致 Vue 来不及渲染,我们浏览器可能会直接显然出未编译的Mustache标签。我们可以使用 v-cloak 指令来解决这一问题。
<style>
[v-cloak]{
display: none;
}
</style>
v-bind
作用:动态绑定属性
缩写::
预期:any (with argument) | Object (without argument)
参数:attrOrProp (optional)
v-bind用于绑定一个或多个属性值,或者向另一个组件传递props值。
在开发中,有哪些属性需要动态进行绑定呢? 还是有很多的,比如图片的链接src、网站的链接href、动态绑定一些类、样式等等。
<div id="demo">
<img v-bind:src="imgUrl" alt="">
</div>
<script>
const app=new Vue({
el:'#demo',
data:{
imgUrl:'url',
}
})
</script>
v-bind语法糖
v-bind有一个对应的语法糖,也就是简写方式。
在开发中,我们通常会使用语法糖的形式,因为这样更加简洁。 简写方式如下:
<img :src="imgUrl" alt="">
v-bind绑定class
很多时候,我们希望动态的来切换class,比如: 当数据为某个状态时,字体显示红色。 当数据另一个状态时,字体显示黑色。
绑定class有两种方式: 对象语法和数组语法。
绑定方式:对象语法
对象语法的含义是:class后面跟的是一个对象。 对象语法有下面这些用法:
用法一:直接通过{}绑定一个类
<h2 :class="{'active': isActive}">Hello World</h2>
用法二:也可以通过判断,传入多个值
<h2 :class="{'active': isActive, 'line': isLine}">Hello World</h2>
用法三:和普通的类同时存在,并不冲突
注:如果isActive和isLine都为true,那么会有title/active/line三个类
<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>
用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello World</h2>
绑定方式:数组语法
数组语法的含义是:class后面跟的是一个数组。 数组语法有下面这些用法:
用法一:直接通过{}绑定一个类
<h2 :class="['active']">Hello World</h2>
用法二:也可以传入多个值
<h2 :class=“[‘active’, 'line']">Hello World</h2>
用法三:和普通的类同时存在,并不冲突
注:会有title/active/line三个类
<h2 class="title" :class=“[‘active’, 'line']">Hello World</h2>
用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello World</h2>
v-bind绑定style
我们可以利用v-bind:style来绑定一些CSS内联样式。
在写CSS属性名的时候,比如font-size ,我们可以使用驼峰式 (camelCase) fontSize 或短横线分隔 (kebab-case,记得用单引号括起来) ‘font-size’。
绑定class有两种方式: 对象语法 数组语法
绑定方式一:对象语法
:style="{color: currentColor, fontSize: fontSize + 'px'}"
style后面跟的是一个对象类型,对象的key是CSS属性名称,对象的value是具体赋的值,值可以来自于data中的属性。
绑定方式二:数组语法
<div v-bind:style="[baseStyles, overridingStyles]"></div>
style后面跟的是一个数组类型,多个值以”,“分割即可。
计算属性
可以对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示。计算属性是写在实例的computed选项中的。
计算属性的setter和getter
每个计算属性都包含一个getter和一个setter ,使用getter来读取,setter用来写入。 在需要写setter的时候,代码如下:
<div id="box">{{fullName}}</div>
<script>
const app=new Vue({
el:'#box',
data:{
firstName:'阿瑟',
lastName:'柯南.道尔'
},
computed:{
fullName:{
set:function(newName){
const name=newName.split('.')
this.firstName=name[0]
this.lastName=name[1]
},
get:function(){
return this.firstName+'.'+this.lastName
}
}
}
})
</script>
计算属性的缓存
计算属性会进行缓存,如果多次使用时,计算属性只会调用一次。
事件监听
v-on
作用:绑定事件监听器
缩写:@
预期:Function | Inline Statement | Object
参数:event
v-on参数
当通过methods中定义方法,以供@click调用时,需要注意参数问题:
情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。 但是注意:如果方法本身中有一个参数,那么会默认将原生事件event参数传递进去
情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。
v-on修饰符
在某些情况下,我们拿到event的目的可能是进行一些事件处理。 Vue提供了修饰符来帮助我们方便的处理一些事件:
.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
<!-- 停止冒泡
<button @click.stop="doThis"></button>
<!-- 阻止默认行为-- >
<button @click.prevent="doThis"></button>
<!-- 阻止默认行为,没有表达式-- >
<form @submit.prevent></ form>
<!--串联修饰符-->
<button @click.stop.prevent="doThis"></button>
<!-- 键修饰符,键别名-->
<input @keyup.enter= "onEnter">
<!--键修饰符,键代码-->
<input @keyup.13="onEnter">
<!--点击回调只会触发一次-->
<button @click.once="doThis"></button>
v-if、v-else-if、v-else
v-if、v-else-if、v-else 这三个指令与JavaScript的条件语句if、else、else if类似。
Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件。
简单的案例演示:
if(this.score>=90){
myscore='优秀'
}else if(this.score>=80){
myscore='良好'
}else if(this.score>=70){
myscore='中等'
}else if(this.score>=60){
myscore='及格'
}else if(this.score<60){
myscore='不及格'
}
v-if的原理: v-if后面的条件为false时,对应的元素以及其子元素不会渲染。 也就是根本没有不会有对应的标签出现在DOM中。
小问题:
如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。 但是按道理讲,我们应该切换到另外一个input元素中了。 在另一个input元素中,我们并没有输入内容。 为什么会出现这个问题呢?
问题解答: 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。 在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了。
解决方案: 如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key 并且我们需要保证key的不同。
v-show
v-show的用法和v-if非常相似,也用于决定一个元素是否渲染。
v-if和v-show对比:
v-if和v-show都可以决定一个元素是否渲染,那么开发中我们如何选择呢?
v-if当条件为false时,压根不会有对应的元素在DOM中。
v-show当条件为false时,仅仅是将元素的display属性设置为none而已。
开发中如何选择呢?
当需要在显示与隐藏之间切换很频繁时,使用v-show。
当只有一次切换时,通过使用v-if。
v-for遍历数组
当我们有一组数据需要进行渲染时,我们就可以使用v-for来完成。 v-for的语法类似于JavaScript中的for循环。 格式如下:item in items的形式。
我们来看一个简单的案例: 如果在遍历的过程中不需要使用索引值 v-for="movie in movies" 依次从movies中取出movie,并且在元素的内容中,我们可以使用Mustache语法,来使用movie。
<div>
<button v-for="item in move" @click="btnClick(item)">{{item.name}}</button>
</div>
如果在遍历的过程中,我们需要拿到元素在数组中的索引值呢?
语法格式:
v-for=(item, index) in items
其中的index就代表了取出的item在原数组的索引值。
v-for遍历对象
v-for可以用户遍历对象: 比如某个对象中存储着你的个人信息,我们希望以列表的形式显示出来。
<script src="../js/vue.js"></script>
<div id="app">
<ul>
<li v-for="(value, key, index) in info">
{{value}}-{{key}}-{{index}}
</li>
</ul>
</div>
<script>
let app = new Vue({
el:'#app',
data: {
info: {
name: 'why',
age:18,
height: 1.88
}
}
})
</script>
组件的key属性
key的作用主要是为了高效的更新虚拟DOM。
检测数组更新
因为Vue是响应式的,所以当数据发生变化时,Vue会自动检测数据变化,视图会发生对应的更新。 Vue中包含了一组观察数组编译的方法,使用它们改变数组也会触发视图的更新。
push() pop() shift() unshift() splice() sort() reverse()
表单绑定v-model
表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。
Vue中使用v-model指令来实现表单元素和数据的双向绑定。
v-model原理
v-model其实是一个语法糖,它的背后本质上是包含两个操作:
1.v-bind绑定一个value属性
2.v-on指令给当前元素绑定input事件
<input type="text" v-model="message">
等同于
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
v-model:radio
当存在多个单选框时
<label for="man">
<input type="radio" id="man" value="男" v-model="sex">男
</label>
<label for="woman">
<input type="radio" id="woman" value="女" v-model="sex">女
</label>
<h2>你的性别为:{{sex}}</h2>
v-model:checkbox
复选框分为两种情况:单个勾选框和多个勾选框
单个勾选框: v-model即为布尔值。 此时input的value并不影响v-model的值。
多个复选框: 当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组。 当选中某一个时,就会将input的value添加到数组中。
<---单个复选框--->
<label for="agree">
<input type="checkbox" id="agree" v-model="isAgree">同意协议
</label>
<----多个复选框----->
<label for="lq">
<input type="checkbox" id="lq" v-model="hobby" value="篮球">篮球
</label>
<label for="zq">
<input type="checkbox" id="zq" v-model="hobby" value="足球">足球
</label>
<label for="ymq">
<input type="checkbox" id="ymq" v-model="hobby" value="羽毛球">羽毛球
</label>
<label for="pq">
<input type="checkbox" id="pq" v-model="hobby" value="排球">排球
</label>
<h2>你的爱好是{{hobby}}</h2>
v-model:select
和checkbox一样,select也分单选和多选两种情况。
单选:只能选中一个值。 v-model绑定的是一个值。 当我们选中option中的一个时,会将它对应的value赋值到mySelect中。
多选:可以选中多个值。 v-model绑定的是一个数组。 当选中多个值时,就会将选中的option对应的value添加到数组mySelects中。
<select name="asd" v-model="hodes">
<option value="飞天">飞天</option>
<option value="遮天">遮天</option>
<option value="主宰之王">主宰之王</option>
<option value="完美世界">完美世界</option>
</select>
<h2>你喜欢的小说是:{{hodes}}</h2>
<br>
<select name="asd" v-model="hode" multiple>
<option value="飞天">飞天</option>
<option value="遮天">遮天</option>
<option value="主宰之王">主宰之王</option>
<option value="完美世界">完美世界</option>
</select>
<h2>你喜欢的小说是:{{hode}}</h2>
v-model修饰符
lazy修饰符:
默认情况下,v-model默认是在input事件中同步输入框的数据的。 也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。
lazy修饰符可以让数据在失去焦点或者回车时才会更新。
number修饰符:
默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。
number修饰符可以让在输入框中输入的内容自动转成数字类型。
trim修饰符: 如果输入的内容首尾有很多空格,通常我们希望将其去除 。
trim修饰符可以过滤内容左右两边的空格。
组件化开发
我们将一个完整的页面分成很多个组件。 每个组件都用于实现页面的一个功能块。 而每一个组件又可以进行细分。
Vue组件化思想
组件化是Vue.js中的重要思想
它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
任何的应用都会被抽象成一颗组件树。
组件化思想的应用:
有了组件化的思想,我们在之后的开发中就要充分的利用它。 尽可能的将页面拆分成一个个小的、可复用的组件。 这样让我们的代码更加方便组织和管理,并且扩展性也更强。
注册组件的基本步骤
组件的使用分成三个步骤: 创建组件构造器---> 注册组件----> 使用组件。
注册组件步骤解析
1.Vue.extend():
调用Vue.extend()创建的是一个组件构造器。 通常在创建组件构造器时,传入template代表我们自定义组件的模板。 该模板就是在使用到组件的地方,要显示的HTML代码。 事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资料还是会提到这种方式,而且这种方式是学习后面方式的基础。
2.Vue.component():
调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。 所以需要传递两个参数:1、注册组件的标签名 2、组件构造器
3.组件必须挂载在某个Vue实例下,否则它不会生效。
全局组件和局部组件
当我们通过调用Vue.component()注册组件时,组件的注册是全局的。 这意味着该组件可以在任意Vue示例下使用。
如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件 。
父组件和子组件
在前面我们看到了组件树: 组件和组件之间存在层级关系 ,而其中一种非常重要的关系就是父子组件的关系。
父子组件错误用法:以子标签的形式在Vue实例中使用
因为当子组件注册到父组件的components时,Vue会编译好父组件的模块
该模板的内容已经决定了父组件将要渲染的HTML(相当于父组件中已经有了子组件中的内容了) <child-cpn></child-cpn>是只能在父组件中被识别的。
类似这种用法,<child-cpn></child-cpn>是会被浏览器忽略的。
注册组件语法糖
在上面注册组件的方式,可能会有些繁琐。 Vue为了简化这个过程,提供了注册的语法糖。 主要是省去了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替。 语法糖注册全局组件和局部组件:
Vue.component('cpn',{
template:`#text`,
data(){
return{
title:'288'
}
}
})
模板的分离写法
刚才,我们通过语法糖简化了Vue组件的注册过程,另外还有一个地方的写法比较麻烦,就是template模块写法。 如果我们能将其中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰。
Vue提供了两种方案来定义HTML模块内容: 使用<script>标签 使用<template>标签
<script type="text/x-template" id="text">
<div>
<h2>完美世界</h2>
<p>荒天帝</p>
</div>
</script>
<template id="cpn">
<div>
<h2>当前计数:{{count}}</h2>
<button @click="add">+</button>
<button @click="dec">-</button>
</div>
</template>
组件数据的存放
组件对象也有一个data属性(也可以有methods等属性,下面我们有用到) ,只是这个data属性必须是一个函数,而且这个函数返回一个对象,对象内部保存着数据。
Vue.component('cpn',{
template:`#cpn`,
data(){
return{
count:0
}
}
为什么data在组件中必须是一个函数呢?
首先,如果不是一个函数,Vue直接就会报错。
其次,原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。
父子组件的通信
父组件通过props向子组件传递数据
子组件通过事件向父组件发送消息
props基本用法
在组件中,使用选项props来声明需要从父级接收到的数据。
props的值有两种方式:
方式一:字符串数组,数组中的字符串就是传递时的名称。
方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。
props数据验证
在前面,我们的props选项是使用一个数组。 我们说过,除了数组之外,我们也可以使用对象,当需要对props进行类型等验证时,就需要对象写法了。
验证都支持哪些数据类型呢? String Number Boolean Array Object Date Function Symbol
当我们有自定义构造函数时,验证也支持自定义的类型。
子级向父级传递
props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中。 我们应该如何处理呢?这个时候,我们需要使用自定义事件来完成。 什么时候需要自定义事件呢? 当子组件需要向父组件传递数据时,就要用到自定义事件了。 我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。
自定义事件的流程:
在子组件中,通过$emit()来触发事件。
在父组件中,通过v-on来监听子组件事件。
父子组件的访问方式: $children
有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件。
父组件访问子组件:使用$children或$refs
子组件访问父组件:使用$parent
父子组件的访问方式: $refs
$children的缺陷: 通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。 但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。 有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs 。
$refs的使用: $refs和ref指令通常是一起使用的。
首先,我们通过ref给某一个子组件绑定一个特定的ID。
其次,通过this.$refs.ID就可以访问到该组件了。
父子组件的访问方式: $parent
如果我们想在子组件中直接访问父组件,可以通过$parent 注意事项:
尽管在Vue开发中,我们允许通过$parent来访问父组件,但是在真实开发中尽量不要这样做。
子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了。
如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题。
另外,更不好做的是通过$parent直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于我的调试和维护。
slot
组件的插槽:
组件的插槽也是为了让我们封装的组件更加具有扩展性。
让使用者可以决定组件内部的一些内容到底展示什么。
1. 插槽的基本使用<slot></slot>
2. 插槽的默认值<slot>button</slot>
3.如果有多个值,同时放入到组件进行替换时,一起作为替换元素
具名插槽slot
有时需要在组件模板中使用多个插槽,这时需要使用<slot>的name属性,通过这个属性定义的插槽称为具名插槽。
<slot name='myslot'></slot>
编译作用域
父组件模板的所有东西都会在父级作用域内编译;
子组件模板的所有东西都会在子级作用域内编译。
Vue CLI
CLI是Command-Line Interface, 翻译为命令行界面, 但是俗称脚手架.
Vue CLI是一个官方发布 vue.js 项目脚手架 使用 vue-cli 可以快速搭建Vue开发环境以及对应的webpack配置.
Vue CLI使用前提 - Node
安装NodeJS 可以直接在官方网站中下载安装. 网址: http://nodejs.cn/download/
Vue.js官方脚手架工具就使用了webpack模板 对所有的资源会压缩等优化操作 它在开发过程中提供了一套完整的功能,能够使得我们开发过程中变得高效。
Webpack的全局安装
npm install webpack -g
Vue CLI的使用
安装Vue脚手架
npm install -g @vue/cli
初始化项目
vue create 项目名称
项目运行
npm run serve
项目打包
npm run build
Vue程序运行过程
UI方面的配置 启动配置服务器:
vue ui
自定义配置:起别名
vue-router
什么是路由
路由(routing)就是通过互联的网络把信息从源地址传输到目的地址的活动。
随着Ajax的出现, 有了前后端分离的开发模式.
后端只提供API来返回数据, 前端通过Ajax获取数据, 并且可以通过JavaScript将数据渲染到页面中.
这样做最大的优点就是前后端责任的清晰, 后端专注于数据上, 前端专注于交互和可视化上.
并且当移动端(iOS/Android)出现后, 后端不需要进行任何处理, 依然使用之前的一套API即可. 目前很多的网站依然采用这种模式开发.
单页面富应用:
其实SPA最主要的特点就是在前后端分离的基础上加了一层前端路由. 也就是前端来维护一套路由规则.
URL的hash
URL的hash URL的hash也就是锚点(#), 本质上是改变window.location的href属性.
我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新
HTML5的history模式:pushState
history接口是HTML5新增的, 它有五种模式改变URL而不刷新页面.
history.pushState()
history.replaceState()
history.go()
上面只演示了三个方法 因为
history.back()
等价于
history.go(-1)
history.forward()
则等价于
history.go(1)
这三个接口等同于浏览器界面的前进后退。
认识vue-router
目前前端流行的三大框架, 都有自己的路由实现:
Angular的ngRouter
React的ReactRouter
Vue的vue-router
vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。 我们可以访问其官方网站对其进行学习:http:// https://router.vuejs.org/zh/
vue-router是基于路由和组件的路由用于设定访问路径, 将路径和组件映射起来.
在vue-router的单页面应用中, 页面的路径的改变就是组件的切换.
安装和使用vue-router
安装vue-router
npm install vue-router --save
步骤二: 在模块化工程中使用它(因为是一个插件, 所以可以通过Vue.use()来安装路由功能)
第一步:导入路由对象,并且调用 Vue.use(VueRouter)
第二步:创建路由实例,并且传入路由映射配置
第三步:在Vue实例中挂载创建的路由实例
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
创建router实例 (index.js)
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter) //注入组件
const routes = [] //定义路由
const router = new VueRouter({ }) // 创建router实例
export default router //导出router实例
挂载到Vue实例中(main.js)
import router from './router'
new Vue({
router,
render: h => h(App)
}).$mount('#app')
使用vue-router的步骤:
第一步: 创建路由组件
第二步: 配置路由映射: 组件和路径映射关系
第三步: 使用路由: 通过<router-link>和<router-view>
路由的默认路径
在routes中又配置了一个映射.
path配置的是根路径:
/ redirect是重定向,。将根路径重定向到/home的路径下.
const routes = [
{
path:'',
redirect:'/home',
},
]
HTML5的History模式
我们前面说过改变路径的方式有两种:
URL的hash
HTML5的history
默认情况下, 路径的改变使用的URL的hash. 如果希望使用HTML5的history模式, 非常简单, 进行如下配置即可:
const router = new VueRouter({
mode: 'history', //使用HTML5的history模式
base: process.env.BASE_URL,
routes
})
router-link
属性: to, 用于指定跳转的路径.
<router-link to='/home' tag='li'>
tag: tag可以指定<router-link>之后渲染成什么组件, 比如上面的代码会被渲染成一个<li>元素, 而不是<a>。
replace: replace不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中。
active-class: 当<router-link>对应的路由匹配成功时, 会自动给当前元素设置一个router-link-active的class, 设置active-class可以修改默认的名称。在进行高亮显示的导航菜单或者底部tabbar时, 会使用到该类. 但是通常不会修改类的属性, 会直接使用默认的router-link-active即可.
路由代码跳转
return this.$route.path('路径')
动态路由
一个页面的path路径可能是不确定的,比如我们进入用户界面时.
path和Component的匹配关系,我们称之为动态路由(也是路由传递数据的一种方式)。
路由的懒加载
当打包构建应用时,Javascript 包会变得非常大,影响页面加载。
如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了
懒加载的方式
方式一: 结合Vue的异步组件和Webpack的代码分析.
const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};
方式二: AMD写法
const About = resolve => require(['../components/About.vue'], resolve);
方式三: 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.
const Home = () => import('../components/Home.vue')
认识嵌套路由
嵌套路由是一个很常见的功能 比如在home页面中, 我们希望通过/home/news和/home/message访问一些内容. 一个路径映射一个组件, 访问这两个路径也会分别渲染两个组件.
路径和组件的关系如下:
实现嵌套路由有两个步骤:
创建对应的子组件, 并且在路由映射中配置对应的子路由.
在组件内部使用<router-view>标签.
传递参数的方式
传递参数主要有两种类型: params和query
params的类型:
配置路由格式: /router/:id
传递的方式: 在path后面跟上对应的值
传递后形成的路径: /router/123, /router/abc
query的类型:
配置路由格式: /router, 也就是普通配置
传递的方式: 对象中使用query的key作为传递方式
传递后形成的路径: /router?id=123, /router?id=abc
如何使用它们呢? 也有两种方式: <router-link>的方式和JavaScript代码方式
获取参数
获取参数通过$route对象获取的. 在使用了 vue-router 的应用中,路由对象会被注入每个组件中,赋值为 this.$route ,并且当路由切换时,路由对象会被更新。
$route和$router的区别
$router为VueRouter实例,想要导航到不同URL,则使用$router.push方法
$route为当前router跳转对象里面可以获取name、path、query、params等
导航守卫
vue-router提供的导航守卫主要用来监听路由的进入和离开的.
vue-router提供了beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发.
导航钩子的三个参数解析:
to: 即将要进入的目标的路由对象.
from: 当前导航即将要离开的路由对象.
next: 调用该方法后, 才能进入下一个钩子.
keep-alive
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
它们有两个非常重要的属性:
include - 字符串或正则表达,只有匹配的组件会被缓存
exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存:
通过create声明周期函数来验证
Promise
Promise是异步编程的一种解决方案。
Promise三种状态
首先, 当我们开发中有异步操作时, 就可以给异步操作包装一个Promise
new Promise((resolve,reject)=>{
}).then((data)=>{
}).catch((err)=>{
})
异步操作之后会有三种状态:
pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()
Promise链式调用
Promise.resovle():将数据包装成Promise对象,并且在内部回调resolve()函数
Promise.reject():将数据包装成Promise对象,并且在内部回调reject()函数