Vue的使用
(1)导入script包,地址:
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
(2)写script文件 (在app的根节点后面写)
<script>
var vm = new Vue({
el: "#app",//要控制的标签id
data: {//数据
msg: '123'
}
})
</script>
二、基本语法使用
(一)显示数据
(1)文本插值 {{msg}},
即显示数据,放在标签里面,里面也可以放一些简单的js
(2)v-tex
v-text=”msg”,放在标签属性内,也是显示数据
总结:
二者都是显示数据,
但第一种不会覆盖本来再标签里写了的内容且在还未加载显示的该内容时,
会直接显示{{msg}}(以文本显示,解决办法:在标签属性加上v-cloak且设置样式:
v-cloak 解决vue页面闪烁的问题
<style>
[v-cloak] {
display: none;
}
</style>
第二种是直接赋值,会直接覆盖标签里的内容,没有懒加载的情况。
(3)v-html=”msg”,
放在标签属性内,如果要显示的内容有html的代码时,
会直接覆盖原本的内容,把msg解析成html的代码显示。
解析一些html代码。有时接口会给我们返回一个标签属性,语法如下。
(二)方法变量的使用
v-bind
为声明该属性为变量 :
等同于v-bind: ,
<button type="button" value="按钮" :title="msg+”123” ”></button>
此时title会变成变量,title里会显示msg的内容,同时里面可以写标准的js代码,如拼接 字符串之类的.
如动态绑定类名,当active为true时,one类名生效,反之不生效
动态绑定类名 :class
格式:
<div :class='{red:false,blue:true}'>
表示类名red生效,blue不生效
动态绑定样式 :style
格式:<div :style = '{Color}'>
Color:{
fontSize:18px,
}
注意vue的style用的是驼峰命名
方法的定义 v-on:
v-on:click(click为可选值,可以是moseover等原先的js事件,缩写为@,show为方法名)
格式:
<button type="button" value="按钮" v-on:click="show"></button>
// Script的vm里:
methods:{
show:function(){
// 里面写方法
}
}
(三)事件机制
每个事件处理程序默认都会有一个事件对象event,如 handler($event,参数)
(1)格式:
.self为可选,可选任意事件修饰符
(2)冒泡行为
指的是事件从里层到外层进行依次触发,如以上例子,div里包括了input标签,二者皆有同一个触发行为,当点击input时,click事件从input的到div的依次出发click事件。若想阻止此事件的发生,可以用.Stop事件修饰符进行阻止,该修饰符会阻止有该修饰符事件往后(即外层)的所有冒泡行为,里面的不能阻止。
(3)默认事件:
如a标签的跳转事件或from表单的提交按钮事件是默认的,当点击时可以跳转,若不想执行跳转,即用prevent事件修饰符进行修饰。
(4)捕获模式capture:
即与冒泡模式相反,从外层到里层进行捕获。在事件捕获时执行,当触发子元素事件时,父元素事件最先触发,再到子元素
(5)Self事件修饰符:
只管自己的触发。如以上例子定义了self事件修饰符后,当input点击时不会触发到div的点击事件,当真正点击到div时才会触发该点击事件,由于div的盒子上有一个input按钮,点击按钮不会触发到。但不会阻止冒泡事件,即当有冒泡事件的发生时,会跳过该有该修饰符的事件往后冒泡。
(6)Once:
只会触发一次,再次点击的时候不会触发,如登录事件等。
(7)passive
滚动事件,一般与srcoll事件连用,当滚动时会一直执行该事件
与keyup事件配合使用的修饰符
.enter、.tab、.delete、.esc、.space、.up、.down、.left、.right
.ctrl、.alt、.shift、.meta
与鼠标事件配合使用的修饰符
.left、.right、
.middle:按下中间滚轮执行这个事件
template
表示当前作用域的插槽
<template slot-scope = 'scope'>
</template>
其中scope为当前作用域的数据,注意写插槽之后一定要用scope变量,否则会报错
scope.row: 拿到当前行的数据
(四)V-model实现双向数据绑定与v-for指令
v-model
v-model的修饰符:
默认情况下,v-model默认是在input事件中同步输入框的数据的。
也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。
.lazy修饰符可以让数据在失去焦点或者回车时才会更新:
.number修饰符在输入框中输入的内容自动转成数字类型:
.trim可以过滤内容左右(首尾)两边的空格
双向数据绑定
即在表单的控件里改变输入变量值msg,可以同步修改变量msg本身,v-bind属性不能实现修改。
<input type='radio' value='male' v-model='stu.gender'>
<input type='radio' value='famale' v-model='stu.gender'>
V-for指令:
使用:
① 循环普通数组
i可选,为索引值,可写可不写。
② 循环对象数组
③ 循环对象
除了以上val与key外,还可以有一个i索引值
④ 迭代数字循环
(3)v-for指令的key使用
在v-for循环中,使用key的属性值来唯一标识当前循环的对象,否则可能会产生对象混乱的情况。因为vue是diff算法,对组件的高效复用。Key的值只能用number或者string类型的值,不能是对象。
例子:
如果没有key的值来唯一标识,那么当我们添加6对像在前面时,之前勾选过的5对象值会变成勾选4的对象值,因为4变成了5,5为增加一个组件到最后一个,这就是组件复用。为避免这种情况,要用key来唯一标识当前的对象是哪个。
(五)v-if与v-show的使用与区别
v-if
当创建的节点不被显示时,会从dom树上进行删除,
应用场景:数据渲染,如果没有数据,就显示暂无数据,有数据显示数据
v-show
当创建的节点不被显示时,那么是当前元素被设置 display = none
总结
当一个元素从初始被创建就从来没被显示过,那么用v-if比较合适,
若要反复进行隐藏与显示,就用v-show。
(六)总结:
三、Vue的进阶语法
Vue过滤器filter
(1).全局过滤器
格式:
在vue的框架中,在main.js里可以声明一个全局过滤器,同时可以使用 | 管道符进行调用.
(2)格式
过滤器vue.filter(过滤器的名字,funtion(data,…){})形式,方法中第一个参数data为必要值,为需要做过滤处理的数值,如上面的例子,是msg需要做过滤处理,即传送时,第一个参数data默认为msg,不会是后面的’疯狂+1’等。在调用的时候用管道符|进行调用,如上:msgFormat为过滤器的名字,格式:要调用过滤器的数值 | 过滤器的名字(参数二,参数三)。可以使用多个过滤器进行过滤,如上进行套娃的形式,直到最后一个过滤器调用完毕后,再渲染数据。
(3).私有过滤器
格式:
写在vm内部。
(三)键盘事件
(1).键盘事件键值修饰符:
使用格式如上,在.之后可以使用按键别名来指定键盘按钮。
(2).自定义按键修饰符
语句Vue.config.keyCodes.f1=112:112为键盘码,如f1的键盘码为112,可以上网查询其他键值的键盘码,该语句在script里面,放在vm外面。位置与过滤器同级。
(四)自定义指令
(1).全局自定义指令。 Vue.directive(‘指令名称’,{})
即自定义一个v-方法,注意这个自定义方法中是原生的js,即原生js的方法可以直接使用。
<div class="content_tow_4 chart_box" v-focus='el,ture'>
格式
focus为指令名称,对象有一些指令相关的函数,函数可以在特定的阶段执行相关的操作。在元素属性中传递的参数均会被bind等钩子函数的参数接受,其中钩子函数的第一个参数必定是el元素本身。其余的是传递过来的参数
参数对象说明
任何节点被渲染在页面上的流程为,编译器编译,这时,编译的程序只会被存储在内存中,再把编译的内容插入到 DOM树中,此时元素才能被实际操作。
bind :
在当指令绑定在元素上的时候执行bind函数,只执行一次,
操作节点的样式可以写在此,
inserted:
在元素插入到dom时会执行inserted函数,只会触发一次
操作节点本身需要写在此,和js行为有关的操作写在此
update:
当vueNode更新的时候会执行update,可能会触发多次
钩子函数的参数说明
第一个参数 el 元素本身
永远位于第一个参数,里面存放的是元素节点本身,对节点的原生操作可使用
例:el.style.color = 'red';
第二个参数 binding 对象
对象中包含一下属性:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode:
Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
oldVnode:
上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
私有自定义指令:
directives: {
"fontWeight": { //方法名
bind: function (el, binding) { //方法的钩子函数
}
}
}
(4).自定义方法里要写的钩子函数与参数
(6).el为该自定义函数的用第一个参数(一定时第一个);binding为第二个参数(一定为第二个),binding参数可以用来传值,用法如下,可以把blue传给自定义方法。(注意:Blue为第二个参数,第一个参数仍是el)
自定义函数简写
在写自定义函数的过程中,如果只用到bind与update两个钩子函数,可以直接省略钩子函数的名字,直接写function(el)即可。
(五)生命周期函数(钩子函数)
Vue 的生命周期总共分为8个阶段:创建前/后,载入前/后,更新前/后,销毁前/后。
-
beforeCreate(创建前)
表示实例完全被创建出来之前,vue 实例的挂载元素$el和数据对象 data 都为 undefined,还未初始化。 -
created(创建后)
数据对象 data 已存在,可以调用 methods 中的方法,操作 data 中的数据,但 dom 未生成,$el 未存在 。可以发送异步请求 -
beforeMount(挂载前)
vue 实例的 $el 和 data 都已初始化,挂载之前为虚拟的 dom节点,编译模板有没有el选项,没有时,需要执行 vm. $mount(‘模板标签’)进行编译,当有el , 有template选项时,就以template为模板,没有就指定el外部的html作为模板创建 $el模板已经在内存中编辑完成了,但是尚未把模板渲染到页面中。data.message 未替换。 -
mounted(挂载后)
vue 实例挂载完成,data.message 成功渲染。内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了。实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,DOM 渲染在 mounted 中就已经完成了。涉及图表请求,数据联动 -
beforeUpdate(更新前)
当 data 变化时,会触发beforeUpdate方法 。data 数据尚未和最新的数据保持同步。重新编译数据对应的视图层dom元素,使用diff(打补丁算法)得到 -
updated(更新后)
当 data 变化时,会触发 updated 方法。页面和 data 数据已经保持同步了。 -
beforeDestroy(销毁前)
组件销毁之前调用 ,在这一步,实例仍然完全可用。 -
destroyed(销毁后)
组件销毁之后调用,对 data 的改变不会再触发周期函数,vue 实例已解除事件监听和 dom绑定,但 dom 结构依然存在。但能访问data,只是子组件等被销毁。
(六)Vue的api接口的使用
使用vue-resource
引入: 注意,引入一定要在vue之后,否则会不生效
<script src="https://cdn.bootcdn.net/ajax/libs/vue-resource/1.5.3/vue-resource.min.js"></script>
this.$http.get/post/jsonp(‘path’,参数)
格式:
this.$http.get/post/jsonp('path',参数).then(function(res){})
其中then的函数为成功的回调
get请求
ths.$http.get('url',参数(可选)).then(res => { //数据存放在body里 res.body } )
post 请求
格式
this.$http.post('url',{发送的参数(必选,可以是空对象)}, {config,一定要写,但可以是空对象}).then(res => { //数据存放在body里 res.body } )
注意点
注意,config参数是必选的,发送的数据格式也是配置在此,
例:
要发送的是表单格式 那么参数就是 {emulateJson:true}
查看别的参数配置:可查看一下连接的config表格
https://github.com/pagekit/vue-resource/blob/develop/docs/http.md
jsonp请求
在跨域请求中,如端口不一样,协议不一样等都是跨域请求,我们jsonp请求能解决,但这只能为get请求
(七)Vue动画的使用
Vue的动画过渡类名之间的含义:
Vue的v-enter含义
即在开始进入动画前的样式;
Vue的v-leave:
即在开始离开之前的样式;
Vue的v-enter-to:
为该结束之后的样式;
Vue的v-leave-to:
为该离开结束之后的样式;
v-leave-active与v-enter-active
为离开与进入的时间段的样式。
v-move:
在元素位置变动的时候的样式,
与 v-leave-active使用,能实现动画的效果更加的流畅。使得元素离开的时候能实现位置衔接比较流畅。
总结
其中Vue的enter到enter-to为进入的半场动画,
leave到leave-to为离开的半场动画。
一般情况下,v-enter与v-leave-to,v-enter-to与v-leave的样式是一样的,能作为一组来写样式。v-leave-active与v-enter-active为一组。
transition标签
此标签为vue官方提供的,只能在有vue里面使用,里面有默认以上的动画类名,不用手动写类名。
Style里的transition与普通的css的一样,all表示所有属性,渐变时间为0.4s,ease为动画样式渐入渐出。
transition的tag属性
这个属性能控制transitio渲染成的标签,如果tag='div',那么transition的html里面将被渲染成div标签
注意,默认是span标签
transition 的name属性
当transition有name属性时,那么我们的v-enter的类名动画设置就变成 .name-enter等的类名方式
第三方库Animate的使用
官方网址:ps:此处为中文文档,版本比较老旧,具体可以查看英文文档的更新
http://www.animate.net.cn/
引入标签
<link href="https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.min.css" rel="stylesheet">
设置属性
设置 enter-active-class与 leave-active-class 属性类
<transition name="" mode="out-in" enter-active-class="" leave-active-class="">
<h1 v-if="flag">123</h1>
</transition>
mode :为设置动画的先后顺序,out-in 为先出后进 in-out为先进后出
挑选动画效果
设置动画效果
<transition name="" mode="" enter-active-class="animated bounce" leave-active-class="animated bounceOutRight">
<h1 v-if="flag">123</h1>
</transition>
或
<transition name="" mode="" enter-active-class="bounce" leave-active-class="bounceOutRight">
<h1 v-if="flag" class=‘animated ’>123</h1>
</transition>
animated类名放在trasition身上或元素身上都能实现相同的效果
设置动画持续的时间 :duration
在transition标签身上添加属性 :duration=‘毫秒数’ 即可统一设置入场与离场的时间
:duration = {enter:'400',leave:'300'} //表示入场时间400毫秒,离场300毫米
实现半场动画
即该动画只有进入没有出去,或只有出去没有进入,
例如淘宝手机端的添加购物车的小球,都是只有离开没有进入的半场动画。
要实现半场动画,只能借助钩子函数
动画钩子函数
- before-enter:动画进入之前,此时动画尚未开始,可以设置元素的起始样式或者位置。
- enter :开始时,此时动画已开始,可以在此设置动画结束之后的状态,如结束时的位置,以及transition等,注意在函数中如果需要过渡效果一定要在开头写 el.offsetWidth,否则没有过渡效果,且一定要调用第二个参数 done()
- after-enter:半场动画完成之后,
与之对应的还有离开。把这三个钩子函数绑定在trasition标签上且实现相应的函数操作即可实现半场动画
例:
<transition name="" mode="" @before-enter="BeforeEnter" @enter="Enter" @after-enter="afterEnter">
<div class="cricle" v-show="flag"></div>
</transition>
动画钩子函数的参数
el:第一个参数el,表示是要执行函数的节点,默认为第一个参数
例:BeforeEnter(el)
done:第二个参数,是一个函数
列表动画 transition-group
即是一个可以一次性实现多个元素相同的动画效果,如实现ul li 的动画
在实现列表过渡时,如果是循环遍历出来的,那么就不能使用transition包裹,要用 transition-group ,与transition一样,里面默认有v-enter,v-leave-to等类名
transition-group的tag属性
作用
注意:
transition-group默认在渲染的时候为span标签,
此时如果我们把transition-group在里面嵌套li时,
即是span里面嵌套li,这样就不符合我们w3c的规范,
即不能再行内元素里面嵌套块级元素,那么tag属性能改变成我们设置的标签
格式
<transition-group tag="ul"></transition-group>
表示把transition-group变成我们的ul标签
组件与模块化
组件
不同的组件拆分不同的功能模块,如把一个页面的拆分成一个个小的部分,如头部脚部这些等等。方便ui组件的复用
创建组件
注意!! 我们创建的组件即template内容是一定只有一个根节点,最好都用一个div包裹起来。
Vue.extend 全局创建
格式:
var com1=Vue.extend({
template: '<div><h3>123</h3></div>' , // 表示页面要展示的是哪个内容
})
// 组件注册
Vue.component('myCom1',com1) //myCom1为自定义的组件名,com1为组件
Vue.component创建组件
与第一种方式不同的是,把com1直接放在第二个参数里面,且不需要用Vue.extend
Vue.component('myCom1',{
template: '<div><h3>123</h3></div>' , // 表示页面要展示的是哪个内容
}) //myCom1为自定义的组件名,com1为组件
使用template创建组件
直接再html页面中使用 <template id=‘com1’></template>标签,里面写你要展示的内容,注意依然只支持一个div根节点。
再scripit标签中,使用 Vue.component('myCom1',{ template:'#com1' }) 即可。
注册私有组件 comptent
当组件的复用不频繁时,可以注册局部组件。在vue实例中,使用components进行定义私有属性
格式:
components:{
自定义的组件名:{ template:组件的内容 }
}
组件中的data数据
组件中可以有自己的data数据,但data数据的格式为
data:function(){ return { 里面的数据 }}
与脚手架的差不多,位置与template同级
组件的使用
直接使用我们自定义的组件名作为标签即可使用,如<mycom1>
注意!!!!
如果自定义的组件名使用了驼峰命名,那么驼峰之间使用-连接,
如自定义命名为myCom1,那么使用的时候采用 <my-com1> 才能生效
1.创建组件模板
2.注册组件
3.使用标签使用组件
动态组件
在实际的应用场景中,组件之间需要切换,如手机客户端的登录与注册的页面,都需要组件切换,当我们使用true或者false控制页面切换,那么只能切换两个页面,那么就需要component标签。
component标签
格式:
<component :is=' "组件名字" '></component>
注意,:is才是合法的;is接受一个变量,那么就能实现多组件切换,
缺点
动态组件的频繁切换,组件会频繁的背销毁于创建
解决方法:
使用keep-alive包裹,把组件缓存起来。
<keep-alive>
<component :is=' current '></component>
</keep-alive>
keep-alive
生命周期
- activated() 激活组件,进入组件就会触发
- deactivated 离开组件触发,停用组件
- errorCaptured 捕获子组件/后代组件发生错误的生命周期
组件之间的传参
默认子组件无法访问父组件的data值
父组件传递参数给子组件
在子组件里面使用父组件的值
传递data数据
在子组件需要定义 props
格式:父组件传递:
<com1 :parentmsg='msg'></com1>
其中 parentmsg 为自定义属性,com1为子组件,
parentmsg属性需要在props数组里里面定义一个parentmsg,才能正确使用该自定义属性,msg为父组件中的data数据。
子组件接受:
例:
com1:{
template:'',
props:['parentmsg'],
}
其中 props里面的数据都是父组件传递过来的,且只可读不可写。
子组件使用parentmsg即可。
props的配置,类型校验
可以约束传值的类型等
props:[
stu:{
type:[Number,String]
default(){
return 60;
}
validator(val){
return val>50
}
},
age:Number
obj:{
reqiure,
}
]
stu规定的类型为字符类型或字符串类型,且,如果父组件没有传递过来值时,默认取值为 60,validator检验规则希望传过来的值是大于50的值,否则会报错,obj为必填项,否则会报错。
注意:undefined与null能通过任意类型的校验
- default 默认值
- type 值的类型
- validator(val) 校验器规则
子组件传递参数给父组件
子组件传递给父组件参数时,只能通过该方法进行传参
在子组件发送方法:
格式:
this.$emit('自定义的方法名',函数的传递的实参)
以上的表达式写在子组件的某个方法里面,注意,从第二个参数开始,都是给父组件的方法传递的参数。
父组件接受:
格式:
<com1 @自定义的方法名=' 子组件里调用传参的方法名 '></com1>
注意方法名不带()
在method:{
子组件里调用传参的方法名(接受的参数){
操作
}
}
兄弟组件之间传值 $emit $on
使用事件总线来传递。
1.创建一个js文件,在这个js里面导出vue的实例,
import Vue from ‘vue’
export default new Vue()
2.在组件中引入该js文件
发送参数的组件:
使用$emit 发射事件,携带参数:导入的js文件名.$emit('自定义方法名',传递的参数)
3.接受参数的组件:
引入js文件(事件总线文件)
在created函数中:
导入的js文件名.$on('传递的自定义方法名',(传递的参数)=>{})
在脚手架中配置全局总线:
1.在main.js中
new Vue({
render: h => h(App),
// 全局事件总线
beforeCreate(){
Vue.prototype.$bus= this; //this这个new Vue实例
},
router,
store,
}).$mount('#app')
2.在组件中
this.$bus.$emit
祖先组件之间传值
使用provide来传值
祖先组件给孙子组件传参
1.在祖先组件里面
provide(){
return {'参数名':参数值}
}
2.在孙子组件里面
inject:['参数名']
单向数据流
即数据是从上到下进行流动的。当上层数据变化,下层数据也会变化
上层数据:如父组件,下层数据:如子组件。
当父组件的值传递给子组件时,父组件的值更改,那么子组 件的传递过来的值也会被修改,但子组件更改父组件的数据不会引起父组件值的变化。
模块化
如node,保证功能模块的功能单一
组件化与模块化的区别
1.组件化是从ui界面的角度进行划分的,模块化是从代码逻辑的角度划分的,
插槽 slot
在父组件调用子组件时,可以使用插槽来给子组件的标签里面添加一些东西
简单插槽/默认插槽
没有名字的插槽
格式:
在子组件里面 <slot></slot>
在父组件里面 <com1>父组件的数据</com1>
那么com1组件就会添加 以上的内容
具名插槽
即具有名字的插槽,可以填充的内容
格式:
<slot name='center'> </slot>
<templat v-slot:center>填充的内容</template>
使用v-slot指定插槽,就可以指定填充
作用域插槽
子组件给父组件传递值,可以通过插槽来传送,子组件的插槽slot 传递的数据都被存放在 scope里面。scope是对象
例:
子组件:
<slot :a='item'></slot>
父组件
<template slot-scope='scope'>{{ scope.a }} </template>
ref
获取节点 与 组件
<div class="commentArea" ref="mydiv">
this.$refs.mydiv
获取组件中的data数据与method方法
格式:
<com1 ref='mycom'></com1>
this.$refs.mycom.data数据名;
this.$refs.mycom.method方法名+小括号调用()
路由
路由是动态加载组件的一种方式
注意!!!vue的路由默认是hash路由,即地址栏得带个#,对应的a标签地址栏跳转的时候也要写成 #/path
后端路由与前端路由
后端路由:把所有url地址,对应服务器的资源
前端路由:就跳转页面,页面不会进行刷新
v-router
当我们的地址栏改变之后,v-router的实例就会监听到地址栏改变,然后通过route里面的各个规则里的path进行匹配。匹配成功之后,就会对应的展示相对应的component里面的组件,否则就空白。
引入
v-router官网
引入:注意要在引入vue之后再引入
<script src="https://cdn.bootcdn.net/ajax/libs/vue-router/4.1.5/vue-router.cjs.min.js"></script>
使用案例
<div id="#app">
<router-view></router-view>
</div>
<script>
var login = Vue.component('login', { template: '<h1>123</h1>' })
var router = new VueRouter({
router: [
{ path: '/login', component: login }
]
})
var vm = new Vue({
router: router
})
</script>
VueRouter 实例
格式:
var router = new VueRouter({
routes:[ // 配置路由规则
{ //第一个路由规则
path:'/login'
components: login
}
]
})
表示,如果地址url是/login,那么就展示login这个组件
注意,最后要将这个路由放在vue实例上且再页面上放置<router-view></router-view>标签,才能达到监听的效果,<router-view>标签相当于提供坑位,给该组件显示。
如:
new Vue = {
router:router //值是上面var router的router
}
配置规则 routes
每个路由对象都会有一个配置规则routes,用来手动配置一些规则对象,可以有多个对象,
path
表示监听哪个路由连接,
格式:
path:'/path'
components
表示当path创建后,设置这个path路径指向的是我们要展示的哪个路由组件
格式:
component:组件模板对象
注意!!值是组件的模板对象,不是组件名字
例:
var login = Vue.component('loginzujian',{template:''})
那么login就是组件的模板对象,loginzujian就是组件名称,组件名称仅使用于标签。如<loginzujian>
children 嵌套路由
该路由规则下的孩子路由 ,即路由嵌套,
格式:
children:[
{path:'/path',component:component}
]
注意:children 里面也可以套children,无限套用
/path 里面 / 可以加也可以不加,
加的时候url地址不显示父级路由地址,即/path/path的形式,且router-link里面的to写的是 /path
不加上的时候显示,因为 / 表示的意思就是说从根目录开始匹配。router-link里面的to写的是 /path/path 要把父级的路由地址带上
name 路由的名字
redirect 路由重定向
通过配置路由规则来进行重定向,可以强制跳转到某个页面
格式:
{path:'/',redirect:'/login'}
表示,当地址栏是 / 根目录时,强制跳转到 /login地址
alias 路由的别名
注意别名需要添加 /name
router-link标签
是一个官方提供的标签,默认渲染为a标签,与a标签效果一致,通过to属性设置跳转地址,但是就算把标签通过修改tag来把渲染成其他的标签(除a之外的标签),他点击的时候仍然会
格式:
<router-link to="path"></router-link>
设置active样式
当我们处于该to的地址时,我们可以通过.router-link-exact-active给该标签设置样式。这是默认的类名,我们可以通过router实例里面,通过linkActiveClass来自定义全局配置他的类名,3.x适用
例:
routers:[],
llinkActiveClass:'myclassname'
router-view标签
该标签是显示路由的标签,只有加上该标签,通过路由跳转的组件才会显示在页面上,类似一个坑位
页面跳转的方式
导航分为编程式导航以及声明式导航,页面跳转就发生在这两个导航中
编程式导航 this.$router
即使用 this.$router.xxx的形式进行跳转
push
格式:
this.$eouter.push({
path:'/path',
query:{参数},
})
replace
格式:
this.$router.replace('path')
replace 与push的区别
replace不会往我们的浏览器添加历史记录,即不能前进或后退,push有。
go
格式:
this.$router.go(-1) // 参数是整数,正整数表示前进的步长,负整数返回步长
如果不带参数就是刷新当前页面
NavigationDuplicated问题
当使用编程式导航时,当传递的参数不变的情况下,多次进行跳转会报Nagition的问题
那么为什么会出现这个问题呢?
由于push的底层是返回一个promise对象,promise对象要传入成功与失败的回调,由于没有传入,那么promise就无法捕获到这个异常,就报错
如何解决?
1.给路由跳转写一个成功的回调与失败的回调即可
例:
this.$router.push({name:name},(res)=>{},(err)=>{})
2.改写原型对象的push方法
在router文件夹的index.js文件中
let origin = VueRouter.prototype.push
VueRouter.prototype.push =function(localtion,resolve,reject) {
// location 为跳转的地址,与传递的参数 //resolve 为成功的回调函数// reject为失败的回调函数
if(resolve && reject){
origin.call(this,localtion,resolve,reject);
}else{
origin.call(this,localtion,()=>{},()=>{}); // 如果没传成功或失败的回调,那么我们就手动添加一个成功与失败的回调
}
}
声明式导航
即使用route-link标签通过to属性进行跳转的方式。
路由传参
定义参数
传参方式
1.query
采用地址栏?拼接传参的方式,参数被存储在 router.query 这个对象里面,
格式:
发送:
this.$router.push('/path?name='+this.name)
接受:
this.$router.query.name;
name为参数
2.params
通过该传递的方式是不会显示在地址栏里面的。
当采用地址栏占位符的方式传参(动态路由),参数被存储到 route.params这个对象里面
例:
router路由规则匹配采用占位符 : 的形式,
router:[{path:'/login/:id ', component:login}]
<router-link to='/login/12'></router-link>
那么当点击跳转时,会自动帮我们匹配正则表达式,id就是12,被保存在params对象里面,
注意:此时地址栏里面显示的依然时 /login/12,且这个跳转地址要完全匹配path规则,即path里面写了几个参数就要传几个参数,否则就无法展示该组件
使用:
this.route.params.id
3.对象传参
格式:
this.$router.push({
name:'在路由规则里面的name值',
params:{ // 存放在params的参数
参数名:值,
}
query:{ // 存放在query的参数
参数名:值
}
})
注意:name能配合query与params使用,但path只能配合query使用
query传参与params传参的区别
1.query传递的参数是拼接在url地址栏,也会被保存在$router对象里。params传递的是传递在$route里面的
2.query传递参数页面是不会消失,params会,
动态路由
router路由规则匹配采用占位符 : 的形式,
router:[{path:'/login/:id ', component:login}]
<router-link to='/login/12'></router-link>
那么当点击跳转时,会自动帮我们匹配正则表达式,id就是12,被保存在params对象里面,
注意:此时地址栏里面显示的依然时 /login/12,且这个跳转地址要完全匹配path规则,即path里面写了几个参数就要传几个参数,否则就无法展示该组件
使用:
this.route.params.id
路由命名视图
即当router-view使用name属性时,可以指定显示对应名称为name的组件
格式:
<router-view name='left'></router-view>
rotuers:[
{
path:'/',
components:{
'default':home,
'left':left
'right':right
}
}
]
表示router-view显示的是left这个组件,如果没有name这个属性,那么router-view这个坑位显示的是default里面的组件home,注意要有双引号,因为name的值为字符串
监听路由
监听的路由地址 'this.$router.path'
或
$router(to,from){
// to为即将进入的路由
//from 离开的路由
}
组件内更新的钩子函数
或使用组件内的更新钩子函数
在从一个地址跳转到另外一个地址的时候,组件更新的时候会触发以下的钩子函数,跳转的地址不变,参数发生改变能监听到
第三个参数,如果不加的话,from会一直停留在第一个路由变化,手动调用next(),才会真正监听到上一个。
beforeRouteEnter(to,from,next){}
beforeRouteUpdate(to,from,next){}
beforeRouteLeave(to,from,next){}
路由守卫
监听路由地址的变化,如 /user?id=1 --> /user?id=2
注意我们的守卫能解决路径参数不变,组件不刷新的问题
全局守卫
全局前置守卫 router.beforeEach
拦截请求路由路径,如果路由路径不符合我们的要求,就不让它往下执行路由
格式:
router.beforeEach((to,from,next)=>{
if(to.path!=path){
next(false)
}else{
next();
}
})
全局后置守卫 router.afterEach
与前置守卫不同的是没有next函数
router.afterEach((to,from)=>{
})
路由独享守卫
当进入这个路由时才会触发,与前置守卫可以做同一件事
以下在路由配置规则route里面写,一级,
beforEnter:(to, from, next) => {
// ...
next();
}
也是一定要调用next()才会真正进入路由
组件内守卫
beforeRouteEnter
格式:
beforeRouteEnter: (to, from, next) => { //不!能!获取组件实例 `this` }
他的this指向window,其他指向组件实例
beforeRouteUpdate
格式:
beforeRouteUpdate (to, from, next) {//在当前路由改变,但是该组件被复用时调用,可访问this}
beforeRouteLeave
格式:
beforeRouteLeave (to, from, next) {//导航离开该组件的对应路由时调用,可访问this}
hash与history路由
hash路由
具有newUrl以及oldURL参数,是hash路由跳转的原理,能使用以下函数进行监听,hash是我们vue默认的路由模式。
window.onhashchange = function(event){
console.log(event);
}
history路由
window.history 对象可以看到里边提供的方法和记录长度
history对象内有back(),forword(),go()等方法
前进,后退,跳转操作方法:
history.go(-3);//后退3次
history.back(); //后退
history.forward(); //前进
pushState 方法可以添加历史记录
二者的区别
1.hash路由会携带#,history不会
2.hash书信页面不会请求服务器,history刷新会
3.hash工作原理 hashchang 事件 newurl,oladurl
4.history工作原理是使用的go,back,forward等方法。
解决路由组件不更新的问题
当我们使用编程式导航时,由于vue的高复用性,那么即使参数改变,组件也不会刷新调调用,仅仅时路径发生了改变而已,这是,解决方法有两种
router-view
使router-view标签增加key属性,唯一标识,
<router-view :key="key"></router-view>
computed: {
key() {
return this.$route.path + Math.random();
},
},
监听路由路径的变化
监听 watch
data上的所有数据都可以进行进行监听,
格式:
watch:{
'name':function(){}
}
表示:当name改变时,立即就会触发function函数,这是一种浅监听
监听引用数据类型
监听引用数据类型,要开启深度监听,deep:true,且要使用对象的方式即以下的方式,也可以实现浅监听。且监听引用数据类型时,newval与oldval的值都是最新的值。
格式:
obj:{
handler(){},
deep:true,
immediate:true;//立即执行
}
计算属性
在computed中可以定义一些属性,这些属性叫做计算属性,
计算属性的本质就是一个方法,只不过我们在使用这些计算属性的时候,是把他们的名称直接当作属性来使用的,并不会把计算属性当成方法来调用
格式
计算属性,里面是属性值,调用的时候是 name;
格式:
computed:{
name(){
return this.name;
}
}
作用
主要是处理data中需要计算/处理的数据,
特点:
1. 计算属性在引用时不能加(),直接是普通属性进行使用。
2. 当计算属性函数内部,所使用的data数据发生变化时,就会立即重新执行这个函数,重新计算,重新创建这个属性
3. 会有缓存,当里面的数据没有发生改变,就不会重新计算,直接从缓存里面拿
(3).计算属性computed与methods的区别
Computed为一般涉及到计算的都会放进computed里,格式与methods一样.
- 在页面中展示计算属性的结果使用 {{函数名}} , methods里的是 {{ 函数名() }}.
- Computed的输出是有缓存的,在数据没有变更的情况下,尽管调用多次但只执行一 次,methods的是每次调用都会执行.
- computed不处理异步请求
render 函数
编译模板的函数,创建我们的节点,是template的底层。这个函数在beforMounted 与 Mounted 之间。
格式:
render(createElement){
return createElement('标签名',{标签属性},渲染的数据)
}
webpack
前端的静态资源过多的问题
当前端的静态资源过多时,如 .js .css .jpg .svg .vue等,会导致网页加载速度过慢,且发送很多二次请求,而且要处理里面错综复杂的关系,
解决方案
1.使用 合并,压缩,精灵图,图片的base二进制编码外,
2. requireJs和webpack工具
说明
webpack是前端构建工具,他基于nodejs
基本使用方式
安装
npm i webpack -g
命令
webpack xxx.js xxx1.js
表示把 xxx.js 文件 打包到xxx1.js 文件中
webpack 的配置文件
生成配置文件之后,那么我们直接使用命令 webpack就直接可以打包,不用写路径了。
在项目根目录下,创建webpack.config.js 文件,该文件配置如下
const path = require('path');
modoule.exports = {
entry:path.jion('path'), //入口文件,表示要打包哪个文件
output:{ // 表示打包的文件放到哪个文件里
path:path.join('path'), // 放到哪个文件里
filename:'xxx.js' //要打包成哪个文件名
}
}
webpack-dev-server
该工具可以在在相应的代码修改时,可以自动给执行webpack命令进行同步。依赖webpack,所以在执行 npm i 时会报错,需要手动进行安装
安装:
npm i webpack-dev-server -D 局部安装
webpack-dev-server 的配置
由于是局部安装,可以在package.json文件的script 里面添加
"dev":"webpack-dev-server" ,
那么执行 npm run dev 之后就可以实现同步保存了
dev 的配置参数
webpack-dev-server --open --port 3000 --contentBase src --hot
表示 :--open:自动打开,--port 指定端口号3000, --contentBase 指定打开的目录src,--hot热重载
webpack-dev-server 配置参数的第二种方式
在webpack.config.js里面配置,写在moudel.exports里面
devServer:{
open:true, //自动打开浏览器
port: 3000 //设置启动的时候的端口号
contentBase: 'src' ,// 指定托管的根目录
hot: true, // 启用热更新
},
plugins:[ // 由于开启了热更新,是配置插件的节点,才不会被报错
new webpack.HotMoudleReplacementPlugin() // 是一个构造函数,在里面存放了热更新的模块对象。
]
html-webpack-plugin
由于通过webpack构建的js文件是一个物理磁盘上的文件,通过这个插件,能把物理磁盘上的文件放到内存中。即不需要再html页面中配置scrpt处理文件与css处理文件
使用
安装:
npm i html-webpack-plugin -D
在webpack.config.js里面
导入:
const htmlwebpack = require('html-webpack-plugin')
在plugins里配置:
new htmlwebpack = ({ //在内存中生成html页面,在内存中的插件
template:path.join('path.index.html') //指定模板页面,将来会根据指定的页面,来生成内存页面
filename:'index.html' // 指定生成页面的名称
})
webpack处理 样式文件
注意,webpack默认处理js文件。如果要处理其他文件。需要手动安装第三方loader加载器。
安装
npm i style-loader css-loader -D
在main.js文件中导入该css文件
import 'path/index.css'
注意,处理css文件使用css-loader less文件使用 less-loader,scss文件使用scss-loader
配置
在webpack.config.js在里面新增一个配置节点 module,是一个配置对象,在这个配置对象上,有一个rules属性,是一个数组,这个数组中存放了所有第三方文件匹配和处理规则。
module:{
rules:[
{
test:/ \.css$ /, 正则匹配.css文件
use : ['style-loader','css-loader'] 把匹配到的文件以该loader文件进行处理,会先交给css-loader文件里面处理,再交给style-loader
}
]
}
webpack处理图片资源
会把图片转换成base64,小图片合适。大图片不合适
安装
npm i url-loader file-loader
配置
module:{
rules:[
{
test:/ \.(jpg|png|gif)$ /, 正则匹配.css文件
use : ['url-loader?limit=7631&name=[hash:8]-[name].[ext]'] 当图片比7631个字节大或等于时,不会被编译成base64的图片,name属性可以使图片名保持原样不变
hash:8表示再图片名字前面拼接上一个8为的hash值,注意hash值是32位的,当拼接上8位的hash值之后,能放置不同文件的图片重命名的情况
}
]
}
处理字体
也可以使用url-loader文件进行处理,与图片处理一样需要配置相关的文件
处理vue文件
安装 npm i vue-loader vue-template-complier -D
导入vue包: 在main.js导入 import Vue from 'vue'
定义组件 .vue
在main.js使用import导入这个组件
且创建vue实例,内部的配置对象增加一个render属性 使用render渲染以上的组件
插件
我们使用npm i 下载的包都是插件,插件本身是一个对象。通常用来添加一个全局的功能。插件中声明的方法和功能可以提供Vue实例消费
定义插件
都需要暴露一个install方法,
以下示例一个自定义的插件
let myPlugin = {
install (Vue, options) {
Vue.directive('focus', {
inserted (el) {
el.focus();
}
})
}
}
Vue.use(myPlugin);
使用插件
格式:
Vue.use(插件)
混入
当多个实例或组件共用一个属性、数据等,那么就可以使用我们的混入,混入的对象里面存在我们组件所有的属性,如data、methods等,
全局混入与局部混入
格式:
全局混入:
let myMixin={}
Vue.mixin(myMixin)
局部混入:
mixins:[myMixin]
混入的规则
1.当我们的数据或属性有同名时,会合并,例:双方都有data时,里面的数据会形成合并
2.生命周期也会合并,并依次执行就,混入的生命周期先执行
3. method的方法名有同名时,那么会保留组件的。
MVVM模式
vue主要借鉴了MVVM模式
M: model层 ,数据层 data(){return {}}
V:view层 视图层DOM
VM 为联系视图层View于model层的纽带,viewModel层,通过DOM listeners监听view层,通过data bindings监听model层
当视图层数据发生改变时,通知VM层,当VM层通知model,改变相应的变化,model层发生变化也如此