Vue2.x基础教程(Vue2.x+Vuex+VueRouter)
Vue2.x文档目录:
什么是Vue
渐进式 JavaScript 框架
Vue.js是一套构建用户界面的框架,它不仅容易上手,还可以与其他第三方库进行整合(Swiper…)
框架和库的区别:
框架:是一套完整的解决方案,对项目的‘侵入性’较大,项目如果需要更换其他框架,则需要重构项目
库(插件):提供某一个小功能,对项目的‘侵入性’较小,如果需要更换其他插件,只需要更改相关代码即可
为什么要学习Vue框架?
提升开发效率,在企业中,时间就是效率,效率就是金钱
前端提高开发效率的发展历史:原生JS—JQ之类的类库—>前端模板引擎—>Vue/React/Angular
使用Vue有哪些优势?
-
通过数据驱动页面数据更新,无需操作DOM来更新界面
使用Vue我们只需要关心如何获取数据,如何处理数据,如何编写业务逻辑代码,只需要关心处理好的数据交给Vue即可
-
组件化开发,我们可以将网页拆分成一个独立的组件进行编写,将来通过封装好的组件拼接成一个完整的网页
简单上手
Vue使用方式有两种,一种是通过传统方式进行下载导入使用,另外一种是使用Vue-cli安装导入使用
传统方式:
下载–导入–创建Vue实例对象–指定Vue实例对象控制区域----指定Vue实例对象控制区域数据
<div id="app">
{{msg}}
</div>
<script src="../vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
msg:'hello'
}
})
</script>
数据传递
MVVM设计模式
在MVVM设计模式中由3个部分组成
M:Model 数据模型
V:View 视图(展示数据,与用户交互)
VM:View Model数据模型和视图的桥梁
MVVM设计模式最大的特点就是支持数据的双向传递
数据可以从: M ----> VM ----> V
也可以从:V – > VM —> M
Vue中MVVM的划分
Vue其实是基于MVVM设计模式的
被控制的区域:View
Vue实例对象:View Model
实例对象中的Data:Model
Vue中数据的单向传递
我们把“数据"Vue实例对象,Vue实例对象将数据交给”界面“
Model --> View Model
Vue中数据的双向绑定
默认情况下Vue只支持数据单向传递 M—> VM --> V
但是由于Vue是基于MVVM设计模式的,所以也提供了双向传递的能力
在<input>、<textarea> 及 <select> 元素上可以用 V-model 指令创建双向数据绑定
注意点:
V-model 会忽略所有表单元素的 value、checked、selected特性的初始值而总是将Vue实例的数据作为数据来源
使用V-model进行数据绑定
常用指令
指令就是Vue内部提供的一些自定义属性,这些属性中封装好了Vue内部实现的一些功能,只要使用这些指令就可以使用Vue中实现的这些功能
Vue数据绑定的特点:只要数据发生变化,界面就会跟着变化
Vue数据绑定过程
- 会先将未绑定数据的界面展示给用户
- 然后根据模型中的数据控制区域生成绑定数据之后的HTML代码
- 最后再讲绑定数据之后的HTML渲染到界面上
v-once指令
让界面不要跟着数据变化,值渲染一次 用法:直接在标签中使用v-once指令即可
v-cloak指令
利用v-cloak配合 [v-cloak]:{display:none} 默认先隐藏未渲染的界面,直到生成HTML渲染后再重新显示
v-text指令:相当于InnerText
v-html指令:相当于InnerHTML
v-if指令:可以进行判断显示隐藏
v-show指令:可以指定元素是否显示
v-if 和 v-show 的区别:
相同点:都可以控制元素是否显示
不同点:v-if 判断后决定元素是否被渲染到页面中,v-show是表示元素已经渲染到页面中只控制隐藏和显示两种状态
总结:使用 v-if 占用性能比较高,如果频繁显示隐藏某个元素,那么推荐使用v-show,v-show的执行效率比v-if高
v-for指令:
执行for循环,实例如下:
<div id="app">
<li v-for="item in 5">Hello</li>
//也可以使用 item:元素内容 index:下标
<li v-for="(item,index) in 5">Hello</li>
</div>
v-bind指令:
使用v-bind可以实现vue中的单项数据绑定,也可以使用:
简写方式
使用方法:v-bind:属性名=“model中的名称” 方法二::属性名=“model中的名称”
绑定Class类名
默认情况下使用:class=“”进行数据绑定,它会去model中查找,如果想要绑定则需要添加数组,数组内添加类名即可
<style>
.test{
background: rebeccapurple;
}
</style>
<!--方式一-->
<div :class="['test']">大家哦哈</div>
<!--方式二-->
<div :class="bg?'test':''">你好</div>
<!--使用第二种方式需要在model中定义一个test名称的boolean类型的值-->
绑定样式:
使用:style进行绑定一个对象,这个对象可以是Model中的数据
<div :style="{background:'red'}">大家哦哈</div>
事件指令
v-on指令:点击触发
在元素上使用 v-on:事件="事件名称“即可,也可以食用简写方式@事件
例如:
<div id="app">
<button v-on:click="test($event)">点我</button>
</div>
<script src="../vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
msg:'hello',
bg:true
},
methods:{
test(event){
console.log(event)
}
}
})
</script>
按键修饰符
我们可以通过按键修饰符监听按键触发的事件,
例如:监听当前事件是否是回车触发的,可以监听当前事件是否是ESC触发等
分类:
-
系统预定义修饰符
.enter .tab .delete(删除和退格键) .esc .space .up .down .left .right
使用方法:v-on:keyUp.enter=“方法名” 简写方式:@keyUp.enter= “方法名”
也可以使用 @keyUp.13=“方法名” ,通过键盘的KeyCode进行执行,兼容性不好
如果需要组合键的使用可以用:@keyUp.enter.ctrl = “方法名” 这种方式进行使用 ctrl+enter键
-
自定义修饰符
使用Vue.config.keyCodes.f1 = 13;进行指定键码,使用时只需要使用f1即可
常见修饰符:
.once:只调用一次
.prevent:调用event.preventDefault()方法 阻止默认行为,例如a标签默认行为是跳转,加上后就不会执行默认行为
.self:只当前事件从监听器绑定的元素本身触发才会触发回调 在嵌套中默认会触发事件冒泡,使用self指令可以让当前的触发
.stop:调用event.stopPropagation() 阻止事件冒泡
.capture:添加事件监听器使用capture模式,反向冒泡
自定义指令
自定义全局指令
使用vue的directive
方法创建全局指令
接收两个参数:
第一个参数:指令名称
第二个参数:对象
对象中的方法需要在指定声明周期中执行
生命周期:
**bind:**指令被绑定到元素上的时候执行
**inserted:**绑定指令的元素被添加到父元素上的时候调用
注意点:定义指令名称的时候不需要加v-,指令可以在不同声明周期阶段执行
<div id="app">
<p v-text="msg" v-color="'blue'"></p>
<input type="text" v-focus/>
</div>
<script src="../vue.js"></script>
<script>
Vue.directive("color",{
//只要绑定了指令就执行 el:当前元素 obj:对象,包含指令传递的参数,在此对象的value属性中
bind:function(el,obj){
el.style.backgroundColor=obj.value;
}
});
Vue.directive("focus",{
//渲染之后执行
inserted:el=>{
el.focus();
}
});
new Vue({
el:'#app',
data:{
msg:'hello',
}
})
</script>
自定义局部指令
只能在指定的Vue实例的对象中
new Vue({
el:'#test',
data:{
msg:'123'
},
directives:{
//指令只能在本实例对象控制区域中使用
"like":{
bind:(el,obj)=>{
el.style.backgroundColor = 'yellow';
console.log(obj.value)
}
}
}
})
计算属性
了解插值语法特点:可以在{{}}中编写合法的javascript表达式
插值语法缺点:没有代码提示,无法处理复杂语句,不易维护
定义计算属性:
new Vue({
el:'#app',
data:{
msg:'hello',
},
computed:{
'test':function(){
return this.msg+new Date();
}
}
});
使用的时候直接使用插值语法即可
注意点:计算属性和函数都可以实现值的显示,但是函数每次调用都会执行,计算属性如果值没有发生改变只调用一次
过滤器
过滤器和函数以及计算属性一样都是用来处理数据的
定义全局过滤器
通过vue的filter方法定义全局过滤器
Vue.filter('format',function(val){
console.log(val)
return val+new Date();
});
//使用过滤器 {{msg|format}}
定义局部过滤器,只能在当前vue实例对象中的控制区域中使用
new Vue({
el:'#app',
data:{
msg:'hello',
},
filters:{
'ceshi':val=>{
return val+1;
}
}
});
过滤器可以使用多个,例如:format1|format2|…
过渡动画
Vue提供了transition标签,在这个标签中包含需要添加过渡动画的元素
标签内元素只要发生显示隐藏动作将执行过渡动画
当transition组件中的元素显示时会自动查找:v-enter v-enter-to v-enter-active 类名
当transition组件中的元素隐藏时会自动查找:v-leave v-leave-to v-leave-active 类名
类名分别是:开始执行、执行过程、执行完毕 的类名
注意:一个transition组件中只能存在一个元素,否则第二个元素将无法添加过渡动画
初始动画设置
默认情况下如果元素默认显示,不会触发显示的过渡效果,如果想要让元素在刚开始就执行过渡效果,需要在transition组件上添加appear
属性
执行不同动画
默认情况transition组件回去执行v-enter v-enter-to 等 v前缀的类名进行设置过渡
如果相关实现不同动画效果可以在transition组件上添加name
属性 ,这样vue就会去找name属性前缀的类名
例如:
<style>
.v-enter{}
.v-enter-to{}
.v-enter-active{}
.v-leave{}
.v-leave-to{}
.v-leave-active{}
/*
默认情况会去找v前缀,加入name属性使用name中的值作为前缀即可使用多个动画
appear:初始动画,执行当前展示状态的过度动画
*/
</style>
<transition><div>我是第一个box</div></transition>
<transition appear name="two"><div>我是第一个box</div></transition>
Vue提供了钩子函数进行使用过度动画
分别是:befor-enter=’’ enter=’’ after-enter=’’ befor-leave=’’ leave=’’ after-leave=’’
在transition
组件中使用v-on进行绑定即可
方法参数一般接收一个当前元素,动画过程中有两个参数,分别是当前元素和回调函数,执行回调函数表示动画结束,直接执行动画结束钩子函数
注意点:
-
过渡效果
如果想看到过渡效果必须在执行过程中使用 ‘当前元素.offsetWidth/offsetHeight’ 即可
enter(el,done){ el.offsetWidth;//显示过渡效果 }
-
初始动画
如果想让页面一开始就执行过渡动画必须在执行过程中加入延迟执行done回调函数
enter(el,done){ setTimeOut(function(){ done();//动画结束回调 },0); }
自定义类名
除了以上方式以外,还可以使用enter-class = ''进行指定自定义类名进行过度动画
格式:enter-class enter-active-class = ‘’ enter-to-class=’’
可以结合Animate动画库进行使用 Animate
<transition appear enter-class=""
enter-active-class="animate__animated animate__backInLeft"
enter-to-class=""
leave-active-class="animate__animated animate__backOutDown"
>
<h2 v-show="isShow">你好啊</h2>
</transition>
列表动画
默认情况下,一个transition组件中只能包含一个元素执行过渡动画,如果想要多个执行那么需要使用transition-group组件
使用transition-group组件后默认会把组件下的所有元素放到span标签中,如果需要指定放入某个标签,可以使用tag=''
属性进行指定
过渡模式mode
默认情况下过渡动画会同时执行
- in-out 先执行进入过渡动画,再执行退出过渡动画
- out-in 先执行退出过渡动画,再执行进入过渡动画
v-for循环注意事项
- v-for为了提升性能,在更新已经渲染过的元素列表时,会采用“就地复用”策略,也正是因为这个策略,在某些时刻会导致我们的数据混乱
- 可以使用key绑定一个唯一的数据,这样v-for会先判断key是否相同,如果相同则复用,否则重新创建
- 不能使用index作为key,因为当列表的内容新增或删除时index都会发生变化,这就导致了不能很好的复用没有改变的元素
组件化
Vue量大核心:数据驱动界面 组件化
在前端开发中组件化就是把一个很大的界面拆分为多个小界面,每一个小界面就是一个组件
将大界面拆分成小界面就是组件化
组件化的好处:可以简化Vue实例代码,可以提高复用性
创建全局组件,在任意vue实例对象中都可以使用
<div id="app">
<!--使用注册好的组件-->
<lp></lp>
</div>
<script src="../vue.js"></script>
<script>
//创建组件构造器
let tem1 = Vue.extend({
//这里可以使用script标签进行定义模板,然后使用id进行指定即可 例如:template:'#init'
//推荐使用vue中封装的template组件 例如:<template>...</template> 使用:template:'#init'
template:`<div><img src="../images/lp.jpg" width="300"/><p>我是标题</p></div>`
});
//注册组件 参数1:组件名称,参数2:组件模板
Vue.component("lp",tem1);
//第二种创建方式,直接使用对象,vue会自动执行extend方法
Vue.component("lp",{
template:``
});
new Vue({
el:'#app',
data:{
}
});
</script>
注意:在声明模板的时候只能存在一个根元素
创建局部组件,只能在当前vue实例对象中使用
在Vue实例中使用components:{key:value}进行创建局部组件
new Vue({
el:'#app',
data:{
},
//注册组件
components:{
'test':{
template: '#test'
}
}
});
组件中也存在data,methods等
注意:组件中的data和vue实例中的data不一样,组件中的是需要一个函数返回对象
为什么组件中的data需要函数返回?
组件中的data如果不通过函数返回数据,那么多个组件就会共用一份数据,导致数据混乱
如果组件中的data是通过函数返回的,那么每创建一个新的组件,都会调用一次这个方法,将这个方法返回的数据和当前创建的组件绑定在一起
组件切换
通常情况下可以使用v-if进行多个组件中的切换,但是无法保存组件状态,因为v-if是重新渲染
vue提供了component动态组件,通过v-bind:is='要显示的组件名'
即可 ,component组件实现切换效果,如果需要保存组件状态需要添加keep-alive
keep-alive组件可以保存组件的状态,从缓存中取
例如:
<keep-alive>
<component :is="isShow?'lp':'list'"></component>
</keep-alive>
父子组件
在一个组件中定义了其它组件就是父子组件,其实在vue实例中可以定义其他组件,在其他组件中也可以定义更多组件
components:{
'fater':{
template:'#a',
components:{
'test':{
template:'#b'
}
}
}
}
父组件向子组件传值方式
默认情况下子组件无法使用父组件中的数据
在父组件中通过子组件上的 :自定义名称=‘值’
进行向子组件传递参数,子组件通过props属性接收 props:['传递过来的名称']
如果出现多级父子组件,需要依次向下传递
例如:
<template id="a">
<div>
<p>我是爹:{{name}} 年龄:{{age}}</p>
<!--传递参数-->
<test :name="name" :age="age"></test>
</div>
</template>
<template id="b">
<div>
<p>我是儿{{name}} 年龄:{{age}}</p>
</div>
</template>
<scrtip>
...
components:{
'test':{
template:'#b',
//接收参数
props:['name','age']
},
}
</scrtip>
父组件向子组件传递方法
与传递参数一样,只不过使用v-on
指令进行传递 例如:@getName=‘函数’
子组件接收的时候不需要props
进行接收,而是定义子组件方法,在方法中使用this.$emit('父组件传递的函数名称')
例如:
components:{
'test':{
template:'#b',
methods: {
t() {
this.$emit('cl');
}
},
props:['name','age']
},
}
子组件向父组件传递参数
通过父组件的方法进行传递参数到父组件中
components:{
'son':{
template: '#son',
methods:{
btn(){
//需要在父组件中定义方法接收参数
this.$emit('btn','我是传递过去的值');
}
}
},
}
组件中的命名注意点
注册以及使用组件
注册组件时候使用了驼峰命名,那么在使用的使用需要使用-
符号进行拼接
例如:注册组件’getName‘ 使用时 <get-name></get-name>
参数传递注意点
在传递参数的时候如果想使用驼峰命名,那么就必须写短横线分隔命名
例如:传递时:parent-name = ‘name’ 接收时:props:[‘parentName’]
方法传递注意点
在方法传递的时候不能使用驼峰命名,只能使用短横线分隔命名
例如:@parent-say=‘say’ 子组件接收:this.$emit(‘parent-say’)
插槽
插槽可以理解为一个预定设计好的一个
坑
,使用该组件的时候可以向坑
中添加合适的内容插槽可以分为两种:匿名插槽和具名插槽
匿名插槽 (没有指定名字)
在组件中的任意位置添加slot
标签作为一个坑
,这个插槽可以有默认数据,如果使用了这个组件,没有填充内容,那么会显示默认数据,否则替换全部内容
默认情况下,所有填充内容会填充到插槽中,如果出现多个匿名插槽,那么会拷贝相对应的数据
推荐一个组件中只使用一个匿名插槽
具名插槽
通过插槽的name属性给插槽定义名称
在使用时可以通过slot=’‘name’的方式,指定一个插槽填充内容
例如:
<div id="app">
<box>
<div class="box vivify fadeInLeft" >
我是第一个标签
</div>
<p slot="one">我是第二个哦</p>
<p slot="two">我是第三个昂~</p>
</box>
</div>
<template id="info">
<div>
<p>我是头部</p>
<slot name="one"></slot>
<slot name="two"></slot>
<slot></slot>
<p>我是底部</p>
</div>
</template>
默认情况下如果不指定slot属性是填充到哪一个插槽中,那么这个内容会被插入到匿名插槽中
Vue2.6版本之定义了v-slot指令
不在使用slot属性进行向插槽中插入内容了,而是通过v-slot指令进行指定
例如:template v-slot:插槽名称 或 v-slot=“插槽名称”
<box>
<div class="box vivify fadeInLeft" >
我是第一个标签
</div>
<template v-slot:one>
<div>我是插入one中的内容哦</div>
</template>
<template v-slot=‘two’>
<div>我是插入到two中的内容哦</div>
</template>
<template #one>
<div>我也是one中的元素</div>
</template>
</box>
v-slot指令可以简写为#号,v-sloat指令只能用在template上
使用slot属性进行插入内容,如果多个元素的指定插槽是同一个那么会合并这两个的内容插入其中
使用v-slot指令进行插入内容,如果多个template指定插槽是同一个那么后面的会替换掉前面的
作用域插槽
作用域插槽就是带数据的插槽,就是让父组件在填充子组件插槽内容的时候也能使用子组件的数据
通过子组件的插槽进行暴露子组件中的某个数据,通过v-bind:暴露名称='当前作用域中的数据'
<slot :datas="names" name="one">我是插槽默认数据{{names}}</slot>
在父组件中使用的时候使用 v-slot
指令进行声明对象使用,也可以使用slot-scope和slot一块使用,不指定slot走默认插槽,推荐使用v-slot指令
例如:
<template id="son">
<div>
<p>我是子组件{{names}}</p>
<!--暴露数据给父组件-->
<slot :datas="names">我是插槽默认数据{{names}}</slot>
</div>
</template>
<!--父组件使用-->
<son>
<!--也可以使用slot-scope进行使用,并且通过slot属性指定具名插槽,如果使用v-slot指令,插入匿名插槽的话使用#default即可-->
<template #one="a">
哈哈哈{{a.datas}}
</template>
</son>
简单使用Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
如果想要在子组件中使用祖先组件中的数据,那么就必须一层一层的传递(非常麻烦)
兄弟组件无法记性传递参数,如果想要实现兄弟组件进行传递参数,需要使用一个父组件作为数据存放区
,然后通过子组件操作数据将数据同步到父组件,然后在把父组件的数据传递给子组件,即可实现。(麻烦)
使用Vuex可以帮助我们解决这类问题
创建Vuex实例
const store = new Vuex.Store({
//存储公共的数据
state:{
applicationCount:0
}
});
给某个组件使用,如果这个组件是多个组件的父组件,那么这个数据子组件也可以使用
Vue.component('father',{
template:'#father',
store,
data:()=>({
count : 0
}),
methods: {
update(number){
this.count = number;
}
},
components:{
'son1':{
template: '#son1',
data:()=>({
count:0
}),
methods:{
add(){
this.count = this.count + 1;
this.$emit('getdata', this.count);
this.$store.state.applicationCount = this.count;
console.log(this.$store.state.applicationCount);
},
sub(){
this.count = this.count - 1;
this.$emit('getdata', this.count);
this.$store.state.applicationCount = this.count;
console.log(this.$store.state.applicationCount);
}
}
},
'son2':{
template:'#son2',
props:['value']
}
}
});
通过Vue实例中的store
属性记性指定Store实例对象,例如:Vue({store:实例对象名称})
通过this.$store.state.属性名 来访问Vuex中存放的数据
使用Vuex必须先导入Vue才能够使用,不推荐直接修改共享数据,因为多个组件操作同一个共享数据容易发生错误,为了解决错误需要对每一个组件都进行判断等操作。
通过指定方法修改共享数据
通过mutations属性设定修改state中的共享数据方法,每一个方法都会传入一个state对象参数
例如:
const store = Vuex.Store({
//存储共享数据
state:{
count:0
},
//定义修改共享数据的方法,类似于java实体类中的set方法
mutations:{
AddCount(state){
state.count = state.count + 1;
}
}
});
//通过commit调用Vuex中的方法
this.$store.commit('调用的方法名称');
Vuex中的getters
vuex提供了getters这个属性,属性中保存类似于vue中的计算属性的东西
这个属性中可以写多个方法,方法参数默认携一个state对象,也可以携带其他参数
getters:{
getStr:(state,getters)=>{
console.log("我触发了!");
console.log(getters);
return state.msg+",字符串长度为"+state.msg.length;
}
}
//渲染使用
{{this.$store.getters.getStr}}
如果数据一致那么直接从缓存中取,如果不一致会再次调用
VueRouter(路由)
VueRouter和v-if/v-show一样,是用来切换组件显示的
v-if/v-show是标记切换(true/false)
Vue Router是用哈希来进行切换(#/xxx)
基本使用:
<div id="app">
<center>
<h2>欢迎使用!<sup>哈哈</sup></h2>
</center>
<a href="#/one">第一个</a>
<a href="#/two">第二个</a>
<router-view></router-view>
</div>
<template id="one">
<div>
<div class="box" style="background: #1E9FFF">
我是第一个页面
</div>
</div>
</template>
<template id="two">
<div>
<div class="box">
我是第二个页面
</div>
</div>
</template>
<script>
//定义组件
const one = {
template:'#one'
}
const two = {
template:'#two'
}
//配置vue-router(路由配置)
const routes = [
{path:'/one',component:one},
{path:'/two',component:two}
]
//创建路由
const router = new VueRouter({
routes:routes
});
const vue = new Vue({
el:'#app',
//使用路由
router:router,
components:{
'one':one,
'two':two
}
})
</script>
我们通过a标签并且使用#
哈希进行跳转,可以实现组件切换效果,但是并不专业
Vue Router提供了一个专门用于设置hash的标签 router-link
使用router-link
的时候默认会渲染成a标签,可以使用tag
属性指定某个标签
定义选定样式:
默认情况下vue会给当前选中的加入router-link-active类,通过重写类来决定激活状态的样式
也可以在创建Router的时候加入linkActiveClass属性进行指定类名,这样vue就会自动将默认的替换为自定义的
重定向路由
应用场景:默认情况下是不会显示组件的,只能通过/xxx的方式访问,默认是/,通过更改/进行重定向即可实现页面默认显示某个组件
通过页面路由配置规则添加 /
的一个重定向即可,{path:’/’,component:‘要重定向的组件’}
代码:
//配置路由规则
const router = new VueRouter({
routes:[
//添加重定向路由,默认显示/two组件
{path:'/',redirect:'/two'},
{path:'/one',component:one},
{path:'/two',component:two}
],
linkActiveClass:'xg'
})
路由传参
方法1:可以在router-link的to属性中直接添加组件路径+需要传递的参数即可,例如:/one?name=xiaoge&age=12,
接收参数:使用this.$route.query.x进行接收参数
方法2:在router-link的to属性中以斜杠的方式传递参数,类似于restful风格,使用这种方式需要在配置Router对象路径中加入占位符/:key
接收参数:使用this.$route.params.x进行接收参数
调用$router.push实现携带参数跳转
使用name和params对象进行传递,地址栏中不会携带任何参数显示 【页面刷新不会携带参数】
使用path和query进行传递参数,地址栏中会携带参数 【页面刷新还会保留传递参数】
嵌套路由
嵌套路由也称为子路由,就是在被切换的组件中又切换其他子组件
例如:在第一个组件中存在两个按钮,两个按钮进一步切换当前组件中的内容
需要实现嵌套路由可以通过在配置路由规则的时候,在需要子路由的路由中配置children
属性,在属性中配置子路由地址
routes:[
{
path:'/one',
name:'one',
component:one
},
{
path:'/two',
name:'two',
component:two,
children:[
{
//子路由名称,不需要加/
path:'a',
component:one1
},
{
path:'b',
component: two1
}
]
}
]
注意:配置的子路由只能在配置路由的组件中使用,例如:配置one组件的路由以及子路由,在two组件路由下是不能使用的!
命名视图:
命名视图与具名插槽很相似,都是让不同的出口显示不同的内容
命名视图就是当路由地址被匹配的时候同时指定多个出口,并且每个出口显示内容不同
使用方式与具名插槽类似,如果需要在同一组件中显示同时显示多个视图出口,需要给router-view指定name属性
在配置路由规则的时候需要使用components
对象使用key:value进行声明 (名字:组件)
<div id="app">
<router-view name="one"></router-view>
<router-view name="two"></router-view>
</div>
const router = new VueRouter({
routes:[
{
path:'/',
components:{
one:box1,
two:box2
}
}
]
})
路由钩子
beforeRouteEnter:(to,from,next) : 跳转路由之前
beforeRouteUpdate:(to,from,next) :路由发生改变 例如:localhost:80/#/index --> localhost:80/#/index?name=123就会触发钩子函数
beforeRouteLeave:(to,from,next) : 路由跳转之后,即当前页面离开时
以上钩子函数的参数为:目标路由,跳转前路由,next函数(放行函数,不写无法继续执行路由跳转)
当next参数为false时,将无法进行路由跳转
Watch属性
Watch属性是专门用于监听数据变化的,只要数据发生了变化就会调用相对应的回调方法
Watch属性不仅能监听数据变化,也能监听路由地址的变
通过在vue实例中添加watch属性,对象由key:value组成,key=要监听的变量,默认情况函数会返回两个参数
第一个参数是新的值(当前值)
第二个参数是旧的值(为改变之前的值)
watch:{
num1:function(){
this.res = parseInt(this.num1) + parseInt(this.num2);
},
num2:function() {
this.res = parseInt(this.num1) + parseInt(this.num2);
},
//监听路由
"$route.path":function(newUrl,oldUrl){
this.pageName = newUrl;
this.oldPageName = oldUrl;
}
}
上述对wath为简写方式,完整方式如下实例:
watch:{
//简写
input(n,o){
console.log(n,o)
},
//完整写法
input:{
//处理方法 当前值,上次改变前的值
handler(n,o){
console.log(n,o);
},
//在数据初始化并且不发生改变的时候执行(立即执行) 值:true/false
immediate:true
}
}
handler:处理改变的结果函数
immediate:是否立即执行
deep:深度监听,想要监听整个数组或对象发生变化时可以使用deep进行深度监听,否则无效
深度监听就是当监听对象不发生改变,但是当前对象或数组的属性内容发生改变就会触发
Vue生命周期
new Vue()实例:创建一个vue实例
创建阶段
beforeCreate:实例刚被创建,此时还没有初始化data和methods属性
created:实例的data和methods已经被初始化完成,此时还没有编译模板
编译模板,根据data中的数据和指令生成html,此时还没有被渲染到页面上,只是存在内存当中
beforeMount:完成模板的编译,但是还没有挂载到页面中
mounted:表示vue已经完成了模板渲染
运行阶段
beforeUpdate:当data中的数据发生改变的时候才会调用,但是界面没有改变
updated:使用改变后的数据从新编译模板渲染到页面中
销毁阶段
beforeDestory: 数据开始销毁,此时data和methods都没有被销毁
destoryed:已经被彻底销毁
自定义插件Plugin
Vue.use做了什么事情?
Vue.use的作用是注册一个Vue插件(注册一个组件),Vue.use必须在new Vue之前被调用
什么时候需要定义插件?
当某一个组件或者功能经常需要被使用时,我们可以将这个组件封装为一个插件
如果想使用use的方式注册组件,那么必须先将组件封装成插件,必须暴露一个install方法才能使用use
创建步骤:
- 新建js文件
- 导入封装好的组件,向外抛出一个对象,对象中必须包含install方法
- 在install方法中使用vue进行定义全局组件
- 在main.js中使用use进行注册
实例代码:
//index.js
import Vue from 'vue'
import Loading from '../Loading' //自定义组件
export default{
install:function(){
Vue.component(Loading.name,Loading);//注册组件
}
}
//main.js
//导入定义封装好的js文件
import Loading from '../plugin/loading/index'
//使用use进行全局注册
Vue.use(Loading)
Vue中的特殊特性
vue是使用数据驱动页面的,但是有些时候我们必须操作dom元素
通常使用document进行获取元素,这样可以使用,但是vue不推荐使用
Vue推荐使用ref进行标记以及获取元素内容
例如:标记某个元素ref属性为index
,获取该元素的时候应该使用 this.$refs.index
进行获取,所有被标记ref属性的元素都会被放入$refs对象中
Vue除了直接使用自定义组件标签直接渲染组件,也可以使用Vue实例中的render进行渲染组件
例如:
render:function(createElement){
//渲染one组件
return createElement('one');
}
使用render渲染组件会将当前控制区域覆盖掉,使用标签会渲染到控制区域中
Vue-Cli
官方提供的脚手架工具
默认已经帮我们搭建好了一套利用webpack管理vue的项目结构
安装Vue-cli和使用Vue-cli
安装脚手架工具:npm install -g @vue/cli
检查是安装成功:vue -version
创建vue3项目:vue create project-name
结构解读
在使用vue init webpack [projectName]创建vue2项目时我们能够看到build文件夹和config文件夹
这两个文件夹中存储了webpack相关配置,我们可以针对项目需求进行修改webpack配置
在vue-cli3以后生成的项目目录结构已经没有build文件夹和config文件夹,这么做的目的就是为了让初学者不用关心webpack,只专注于使用vue