vue教学——从0基础到掌握的过程

vue介绍

一年前我跟你一样,对于vue是一点不知,但是经过一年的成长,现在我来谈谈对于vue的看法,让大家更多的了解使用vue框架。既然我们要学习vue,那什么是vue?首先vue 是一个构建用户界面的渐进式的框架,它是目前最火的一个框架,采用自底向上增量开发的设计,它的核心只关注视图层、容易学,低耦合,可重复使用一些视图逻辑,独立开发。

库与框架的区别

我们知道vue 是一个构建用户界面的渐进式的框架,基于mvvm模式开发,那我们必须知道库和框架的区别:

1.库(插件) - 提供某一个小功能,对项目的入侵性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求;例如vue.js,jquery.js…等,其实我们之前使用的引入js文件,就是使用的其中的库。
2.框架 - 框架是以整套完整的解决方案,对项目侵入性很大,项目如果需要更换框架,就需要重新构架整个项目,换句话说就要从头到脚彻底换新。

vue的特点与核心

首先我们需要先了解vue的特点,它只关注视图层,容易学,而且轻量,灵活,适用于移动端项目,是渐进式框架等。
其次它的核心包括:1.响应式的数据变化,视图可以改变数据,数据也可以改变视图;2.通过Object.defineProperty()方法来实现响应式数据变化(此时不理解这个方法不要紧,后面解释数据双向绑定时候会详情解释这个方法);3.设计思想是MVVM;4.组件化系统,组件可维护,可复用。

vue的设计思想MVVM,与MVC的区别

MVC与MVVM的详情图(上面图是MVC与MVVM的逻辑详情图)

MVVM是Model-View-ViewModel的缩写,Model层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View代表的是ui组件,它负责将数据模型转换成ui展现出来;ViewModel它是一个调度者,分割了M与V,每当V层想要获取保存数据都要由VM做中间处理。
在MVVM架构下,View与Model之间没有直接关系,而是通过VM进行交互,是VM提供了数据双向绑定,所以V层的数据变化会同步到M层中,而M层的数据变化也会立即反应到V层上。
MVVM和MVC区别不大,都是一种设计思想,前端操作的主要是MVC中的V层部分,然后将V层划分成了MVVM思想,而MVVM是由MVC中C层演变成VM层,最终MVVM模型解决了MVC中大量操作Dom的操作,提高了渲染性能,加载速度变快,用户体验好。vue是数据驱动,通过数据来显示视图层,而不是对于dom节点的操作。

如何使用vue

1,直接使用cdn提供的免费连接
https://cdn.jsdelivr.net/npm/vue/dist/vue.js
https://cdn.jsdelivr.net/npm/vue@2.6.0
2,使用npm安装:npm install vue
前提是先创建package.json安装依赖的清单列表:npm init
3,vue-cli脚手架直接生成vue项目
注:在此篇文章中教大家如何从上手到熟练的过程,先直接使用vue.js库,可以使用cdn免费的链接,也可以使用npm安装下载vue(在cmd命令中输入npm init生成一个package.json,然后输入npm install vue,会生成一个node_modules文件在里面vue文件下的dist文件中找到vue.js然后引入到你的html文本中就可以了)

vue基本语法

1.先控制一个根元素取id名为app(这个名字是你随便取的,但是你取的名字下面需要挂载),以后所写的内容均需要在这个元素中进行;2.new Vue()如下步骤所示:

<body>
	<div id="app">
	<!-- 此处显示data中的msg数据,下面两个大括号表示插值表达式-->
	 {{ msg }}
	</div>
	<script src="./js/vue.js"></script>
	<script type="text/javascript">
		let vm = new Vue({ //创建vue实例
			el: '#app', //绑定元素
			data: { //此处的数据存放方式是对象
				msg: 'hello world'
			},
	  Object.freeze(msg)//当使用这个方法之后,会阻止修改data中msg数据
		//注意区分:后面会进行组件开发,组件中的data必须是函数,因为
		//函数有自己的作用域,每个data都是独立,可以各种操作不受影响
		//而如果都用对象形式,则操作多个实例都会引用同一个对象,同一个堆内存
		// data(){注意此处与上面的data相对比,此处是函数
		// 	return{
			// 		msg:'hello world'
		// 	}
		// }
		})
		vm.msg = '你好' //修改实例中的数据
	</script>
</body>

vue的指令系统

  1. v-cloak 。能够解决插值表达式闪烁的问题
<style>
	[v-cloak]{
	  display: none;//使用插值表达式可以设置css样式解决刷新闪烁的问题
	}
</style>

2.v-text与v-html 。v-text相当于原生javascript中的innerText,只识别文本不识别标签;v-html相当于原生javascript中的innerHTML,可以识别标签

<body>
		<div id="app" v-cloak>
			<p v-text="msg"></p>
			<p v-html="msg"></p>
		</div>
		<script src="./js/vue.js"></script>
		<script type="text/javascript">
			let vm = new Vue({ //创建vue实例
				el: '#app', //绑定元素
				data(){//存放数据
					return{
						msg:'<h3>hello world</h3>'
					}
				}
			})
		</script>
	</body>

如下图所示
在这里插入图片描述
3.v-bind,属性绑定,可以简写成:(冒号),只能实现单向数据的绑定

①.绑定属性方法

<body>
	<div id="app" v-cloak>
		<input type="button" :value="msg" />//绑定属性,用data中的数据
	</div>
	<script src="./js/vue.js"></script>
	<script type="text/javascript">
		let vm = new Vue({ //创建vue实例
			el: '#app', //绑定元素
			data(){//存放数据
				return{
					msg:'修改'
				}
			}
		})
	</script>
</body>

如下图所示
在这里插入图片描述
②.绑定样式
使用class样式:

<style>
			.w{
				background-color: #7FFFD4;
			}
			.e{
				color: chocolate;
			}
			.r{
				font-size: 20px;
			}
		</style>
	</head>

	<body>
		<div id="box">
			<!-- 数组中传入三元运算符 -->
			<!-- <h1 :class="['w','e',flg ? 'r' : '']">我是一个h1</h1> -->
			<!-- 数组中传入对象 -->
			<!-- <h1 :class="['w','e',{r:flg}]">我是一个h1</h1> -->
			<!-- 直接传入一个对象 -->
			<!-- <h1 :class="{w:true,e:true,r:true}">我是一个h1</h1> -->
			<!-- 在数据中引入样式 -->
			<h1 :class="as">我是一个h1</h1>
		</div>
		<script src="js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#box',
				data:{
					flg:false,
					as:{w:true,e:true,r:false}
				}
			})
		</script>
	</body>

使用内联样式:

<h1 :style="{color:'red','font-size':'40px'}">这是一个h1</h1>

4.v-on,绑定事件,可以简写成@

①使用方法

<body>
	<div id="app" v-cloak>
		<!-- 绑定属性和事件 -->
		<input type="button" :value="msg" @click="handlerClick"/>
	</div>
	<script src="./js/vue.js"></script>
	<script type="text/javascript">
		let vm = new Vue({ //创建vue实例
			el: '#app', //绑定元素
			data(){//存放数据
				return{
					msg:'点击'
				}
			},
			methods:{//定义的逻辑事件放在methods中定义声明
				handlerClick(){
					alert('hello world')
				}
			}
		})
	</script>
</body>

如下图所示
在这里插入图片描述
②事件修饰符

.stop 阻止冒泡
.prevent 阻止默认事件
.once 事件值触发一次
.capture 添加时间侦听器时使用事件捕获模式
.self 清除捕获冒泡机制,值实行单一效果,点击谁实行谁的效果
.passive 滚动事件的默认行为(不能与prevent一起连用,连用失效)
使用方式:如<a href=’@click.prevent=‘handler’’>点击此时点击不会跳转
注:事件修饰符有链接式写法,但是链接之后,前面的修饰符对后面的就不起作用了

③按键修饰符

我们知道很多网页比如你按enter键就会进入的效果,这就是使用了按键修饰符,按键修饰符有:.enter .tab .delete .esc .space .up .down .left .right等等,使用方法:@keyup.enter=“执行的函数方法”,也可以使用按键码执行相应的操作,即@key.13 = "执行的函数方法"若想获取按键码可以使用vue提供的一个方法,vue.config.keyCode.enter = 13;

5.v-for与key属性,列表循环与数据渲染,可以循环数组、对象、以及数字

<body>
	<div id="box" v-cloak>
	<!--v-for循环语法 ,key值确定唯一性,以免操作相同元素引起失误,故循环时候都加上key值,确定唯一性 -->
		<p v-for="(item,key) in user" :key='item.id'> {{item.name}}-----{{item.gender}} </p>
	</div>
	<script src="js/vue.js"></script>
	<script type="text/javascript">
		var vm = new Vue({
			el: '#box',
			data() {
				return {
					user: [{
							id: 1,
							name: 'tom',
							gender: '男'
						},
						{
							id: 2,
							name: 'tony',
							gender: '女'
						},
						{
							id: 3,
							name: 'toke',
							gender: '男'
						},
						{
							id: 4,
							name: 'toome',
							gender: '女'
						}
					]
				}
			}
		})
	</script>
</body>

如下图所示结果:
在这里插入图片描述
6.v-model,vue中唯一一个实现数据双向绑定的指令(除自定义指令外),它只能应用于表单控件中(input,textare,select),下面列举介绍几种数据双向绑定的效果以及v-model的原理
①.v-model的用法

<body>
	<div id="box">
		<h4>{{msg}}</h4>
		<!-- 当改变input里面的数据内容,暂时h4里面的内容也会发生改变,这就是数据双向绑定 -->
		<input type="text" v-model="msg" style="width: 100%;"/>
	</div>
	<script src="js/vue.js"></script>
	<script type="text/javascript">
		var vm = new Vue({
			el:'#box',
			data:{
				msg:'大家都是好同志,爱敲代码的好同志'
			}
		})
	</script>
</body>

如下图所示:当你修改里面的内容立马与页面中h4标题一致
在这里插入图片描述
②.使用绑定属性与绑定方法共同来实现数据双向传递(oninput方法)

<body>
		<div id="box">
			<h4>{{msg}}</h4>
			<!-- 当改变input里面的数据内容,暂时h4里面的内容也会发生改变,这就是数据双向绑定 -->
			<input type="text" :value="msg" @input='changeHandler' style="width: 300px;"/>
		</div>
		<script src="js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#box',
				data:{
					msg:'大家都是好同志,爱敲代码的好同志'
				},
				methods:{
				    changeHandler(e){//定义的点击事件
				        this.msg = e.target.value
				    }
                }
			})
		</script>
	</body>

③.v-model实行数据双向绑定的原理(刚学习vue的同学看不懂没关系,可以先行跳过)

/*
观察对象,属性一旦变化了,就调用render方法 ,如何知道属性变化了呢?
有观察者来观察这个对象,
整个监听的流程:把所有的数据都劫持到,改成getter和setter的形式
*/

//属性一旦变化了,就调用render方法:重新渲染页面
function rander(d) {
    console.log('数据变化了,我要更新了', d);
}


//观察者,把data的属性都加上getter和setter的形式
function observer(data) {
    if (typeof data === "object") {
        for (key in data) {
            defineResponse(data, key, data[key]);
        }
    }
}
function defineResponse(data, key, value) {
    //{x:1,y:2}
    observer(value)
    //使用Object.defineProperty()来劫持各个属性的setter与getter,在数据变动时,触发相应的监听回调
    Object.defineProperty(data, key, {
        get() {
            //console.log('get', value);
            return value
        },
        set(newval) {
            value = newval;
            observer(newval);
            console.log('set', newval);
            rander(newval)
        }
    })
}
let data = {
    n: 100,
    h: { x: 1, y: 2 }
}
observer(data);
// data.n = 200;
// console.log(data.n);

// data.h.x = 3;
// console.log(data.h);

data.h = { x: 900 }
data.h.x = 1000;
console.log(data.h);

7.v-if与v-show两种都是显示与隐藏的效果,v-if每次显示与隐藏都有新元素的创建与销毁过程伴随,而v-show,只是css样式display的显示与隐藏,占据内存空间。
其中指令系统还包括v-else,v-else-if,一般v-if与v-else连用时,当不显示v-if时就显示v-else的内容;v-else-if是v-if与v-else的结合。

指令练习测一测

学习完上面的指令系统,接下来会有几个小的练习,希望可以帮助你更好掌握vue的指令。
1.跑马灯练习
要求:两个控制按钮,一个取名为‘跑起来’,另一个取名为‘停止’,分别控制页面的数据变化,数据为‘猥琐发育!别浪~~!’,前面的字符串自动拼接在后面。

<body>
	<div id="box">
		<input type="button" value="跑起来" @click="show"/>
		<input type="button" value="停止" @click="pause"/>
		<h4 v-cloak>{{msg}}</h4>
	</div>
	<script src="js/vue.js"></script>
	<script type="text/javascript">
		var vm  = new Vue({
			//控制的元素
			el:'#box',
			//数据
			data:{
				msg:'别浪~~!猥琐发育!',
				timer:null,
			},
			//方法
			methods:{
				show(){//开始方法
				// var _this = this; 如果使用箭头函数,可以不加这一步
					if(this.timer){
						return;
					}else{
						this.timer = setInterval(()=>{
						var start = this.msg.substring(0,1);
						var end = this.msg.substring(1);
						this.msg = end + start;
						},400)
					}
				},
				pause(){//暂停方法
					clearInterval(this.timer);
					this.timer = null;
				}
			}
		})
	</script>
</body>

如下图所示:
在这里插入图片描述
2.音乐播放器(默认为顺序播放)

<body>
	<div id="app">
		<div class="songList">
			<div @click="handlerSong(index)" v-for="(item,index) in musicListData" :key='item.id' :class="{active:index==currentIndex}">//此处:class是绑定类名,active是一个类名
				<h3>歌名:{{ item.name }}</h3>
				<h4>歌手:{{ item.autor }}</h4>
			</div>
		</div>
		<audio :src="musicListData[currentIndex].srcSong" controls="controls" autoplay="autoplay" @ended="handlerNext"></audio>
	</div>
	<script src="./js/vue.js"></script>
	<script>
		var musicData = [{
				id: 1,
				name: "少林英雄",
				autor: "华语群星",
				srcSong: "./static/华语群星 - 少林英雄.mp3"
			},
			{
				id: 2,
				name: "梧桐树",
				autor: "连子",
				srcSong: "./static/连子 - 梧桐树.mp3"
			},
			{
				id: 3,
				name: "扶桑树",
				autor: "孟萌、刘泓君",
				srcSong: "./static/孟萌、刘泓君 - 扶桑树.mp3"
			},
			{
				id: 4,
				name: "伪装",
				autor: "王炜一",
				srcSong: "./static/王炜一 - 伪装.mp3"
			}
		]

		new Vue({
			el: '#app',
			data() {
				return {
					musicListData: [],//歌曲数存放
					currentIndex: 0//默认显示播放曲目的下表索引
				}
			},
			methods: {
				handlerSong(index) {//点击切换歌曲
					this.currentIndex = index;
				},
				handlerNext() {//当播放完此歌曲后播放下一首
					this.currentIndex++;
					if (this.currentIndex === 4) {
						this.currentIndex === 0;
					}
				}
			},
			created() {//这是晟敏周期里面的一个钩子函数,在此处先用,后面会详情解释
				this.musicListData = musicData;
			}
		})
	</script>
</body>

vue中的过滤器

1.全局过滤器,在创建vue实例之前定义全局过滤器
语法:vue.filter(‘过滤器的名称’,function(msg,ele){//第一个参数固定代表管道符前面的数据,第二个参数代表需要执行的语句
//这里显示需要执行的ele数据的代码
})
使用:{{ msg | 过滤器的名称 }}

<body>
		<div id="box">
			<p>{{msg|fil(ele)}}</p>
		</div>
		<script src="../js/vue.js"></script>
		<script type="text/javascript">
			Vue.filter('fil', function(msg,ele) {
				return msg.replace(/单纯/g, ele);
			})
			var vm = new Vue({
				el: '#box',
				data: {
					msg: '我是一个单纯的孩子,以前很单纯,以后也很单纯',
					ele:'爱笑'
				}
			})
		</script>
	</body>

如下图所示
在这里插入图片描述
过滤器可以多次被调用,即{{ msg | 过滤器1 | 过滤器2 }},所谓的全局过滤器,就是所有的vm实例都可以共享。

2.私有过滤器(局部过滤器),只能在控制的el节点里面使用,用法与全局过滤器一样,只是语法抒写会使用在局部,如下代码所示

<body>
	<div id="box">
		<p v-for="item in list" key='item.name'>{{ item.name | fil}}---{{ item.prince | fil1(2)}}</p>
	</div>
	<script src="../js/vue.js"></script>
	<script type="text/javascript">
		var vm = new Vue({
			el: '#box',
			data: {
				list: [{
						name: 'js入门1',
						prince: 451
					},
					{
						name: 'js入门2',
						prince: 452
					},
					{
						name: 'js入门3',
						prince: 453
					},
					{
						name: 'js入门4',
						prince: 454
					}
				]
			},
			filters: {//过滤器集合
				fil(name) {//过滤器1
					return name.slice(0, 1).toUpperCase() + name.slice(1);
				},
				fil1(prince,pes){//过滤器2
					return prince.toFixed(pes);//保存小数后几位
				}
			}
		})
	</script>
</body>

如下图所示
在这里插入图片描述
注:过滤器调用时,如果私有过滤器与全局过滤器名字一致时,则会先找私有过滤器,然后在找全局过滤器。

vue自定义指令

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。
1.全局指令
当页面加载时,该元素将获得焦点,

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) { // el聚焦元素,指令放在哪个元素上面,el就指哪个元素
  //表示行为js操作放在此处,被绑定元素插入到父节点时调用
    el.focus()
  },
  bind:function(el){
   //表示样式相关操作一般放在bind中,指令第一次绑定到元素时调用
  el.style.color = 'red';
  }//一般只用前面两种方法,后面两种用的很少很少
  updated:function(el){
  //当vNode更新时候调用(可能会调用多次)
  },
  unbind:function(el){
  //只调用一次,指令与元素解绑时候调用
  }
})

2.局部指令(私有指令):与自定义过滤器一样,需要写在控制元素节点el当中

directives: {
  focus: {
    // 指令的定义,这里面的属性方法与全局的一样,都含有inserted,bind等
    inserted: function (el) {
      el.focus()
    }
  }
}

3.指令钩子函数中的参数

inserted,bind,update,unbind这些是指令的钩子函数,
他们的参数含有:(el、binding、vnode 和 oldVnode)。
①el:指令所绑定的元素,可以用来直接操作 DOM 。
②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 钩子中可用。
注:除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

动态绑定指令参数:

Vue.directive('fontWeight',{
				bind:function(el,binding){
					el.style.fontWeight = binding.value;
				},
			})//使用:v-fontWeight = '600';这样就显示加粗的效果

计算属性与侦听器

1.watch,它是一个侦听器,可以侦听数据的变化,使用语法如下代码所示

<body>
		<div id="app">
			<input type="text" v-model="first"/>
			<input type="text" v-model="last"/>
			<input type="text" v-model="fulls"/>
		</div>
		<script src="../js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#app',
				data:{
					first:'',
					last:'',
					fulls:''
				},
				watch:{//侦听器
				first(newval,oldval){//这里的fist与数据中的名字保
				//持一致,只要first发生变化,就会知道他的变化
				//里面包含两个参数newval代表数据变化之后值,
				//oldval代表数据原来的值
						this.fulls = newval + this.last;
					},
					last(newval){
						this.fulls = this.first + newval;
					}
				}
			})
		</script>
	</body>

如果监听的数据形式是一个对象,则需要进行深度监听,代码如下

watch:{
obj:{
handler(newval,oldval){
console.log(obj.a)
},
immediate:true//刷新加载
deep:true//是否可以深度监听
}
}
obj:{
a:‘’,
b:‘’
}

如下图所示
在这里插入图片描述
注:watch只能单向监听,如上所示,只能改变前面的值影响后面值的变化,不能改变后面的值影响前面,为了解决这一双向监听的功能,故出现了计算属性的方法

2.computed,computed定义了一些属性,叫做计算属性,计算属性本质是一个方法,但我们使用时是直接当做属性来使用,并不是方法,在引用时不能加();特别注意,在computed中的属性名不能与data中的名字重复,且声明computed中的属性之后,应该消除data中的一些名称仙童的属性,任何data中数据发生变化,整个computed中属性中的函数方法就会重新计算,计算结果会被缓存起来,方便下次重新使用。

如下代码所示:

<body>
		<div id="app">
			<input type="text" v-model="first"/>
			<input type="text" v-model="last"/>
			<input type="text" v-model="fulls"/>
		</div>
		<script src="../js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#app',
				data:{
					first:'',
					last:''
				},
				computed:{
					// fulls(){//单向绑定
					// 	return this.first + this.last;
					// }
					fulls:{//双向绑定
						get(){
							return this.first + ' ' + this.last;
						},
						set(value){
							value = value.split(' ');
							this.first = value[0];
							this.last = value[1];
						}
					}
				}
			})
		</script>
	</body>

如下图所示:改变前后数据都会发生变化
在这里插入图片描述
3.watch、computed、methods三者的区别

computed是计算属性,有getter与setter属性,会根据属性进行缓存,getter返回属性值,setter接受属性值,属于同步操作。
watch是监听,里面属性函数方法中含有两个参数,分别代表新旧值的数据,当数据发生变化时候就会侦听到,属于一步操作。
methods是保持一些事件的储存位置,存放一些方法的空间。

vue中的过度与动画

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

条件渲染 (使用 v-if)
条件展示 (使用 v-show)
动态组件
组件根节点

这里是一个典型的例子:

<body>
		<div id="app">
			<input type="button" value="切换" @click="flag=!flag"/>
			<transition enter-active-class='box' leave-active-class='box1' :duration=2000>
				<h3 v-if="flag">我是一个h3</h3>
			</transition>
		</div>
		<script src="../js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#app',
				data:{
					flag:false
				}
			})
		</script>
	</body>
<style>
			/* .my-enter,.my-leave-to{
				background-color: #204D74;
				transform: translateX(80px);
				transition-duration: 1s;
			}
			.my-enter-to,.my-leave{
				background-color: red;
			} */
			.box{
				transform: translate(100px);
				transition-duration: 2s;
				background-color: #255625;
			}
			.box1{
				transform: translate(0px);
				transition-duration: 2s;
				background-color: red;
			}
			
		</style>

当插入或删除包含在 transition 组件中的元素时,Vue 将会做以下处理:
① 自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
②如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。
③如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概念不同)

过度的类名

在进入/离开的过渡中,会有 6 个 class 切换。

  1. v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。

  2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。

  3. v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

  4. v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。

  5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

  6. v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

在这里插入图片描述
如下代码所示:

<style>
			[v-cloak]{
				display: none;
			}
			li{
				width: 100%;
				border: 1px dashed #999999;
				margin: 5px;
				line-height: 35px;
				padding-left: 5px;
				font-size: 12px;
			}
			li:hover{
				background-color: hotpink;
				transition: all 0.8s ease;
			}
			
			/* 添加时候的效果(指进入的效果) */
			.v-enter,.v-leave-to{
				opacity: 0;
				transform: translatey(80px);
			}
			.v-enter-active,.v-leave-active{
				transition: all 0.6s ease;
			}
			
			/* 移除时候的效果(指出去时候的效果) */
			/* .v-move与 .v-leave-active配合使用,能够实现列表后续的元素,渐渐地飘上来的效果*/
			.v-move{
				transition: all 0.6s ease;
			}
			.v-leave-active{
				position: absolute;
			}
		</style>
	</head>

	<body>
		<div id="app" v-cloak>
			<label>
				id:<input type="text" v-model="id"/>
			</label>
			<label>
				name:<input type="text" v-model="names"/>
			</label>
			<input type="button" value="添加" @click="add()" />
			<!-- transition-group默认渲染成span元素 -->
			<!-- appear指刚开始页面进入的渐入效果 -->
			<transition-group tag='ul' appear>
				<li v-for="(item,index) in list" :key='item.id' @click="del(index)">{{ item.id }}---{{ item.name }}</li>
			</transition-group>
		</div>
		<script src="../js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data: {
					id: '',
					names: '',
					list: [{
							id: 1,
							name: '赵高'
						},
						{
							id: 2,
							name: '秦桧'
						},
						{
							id: 3,
							name: '魏忠贤'
						},
						{
							id: 4,
							name: '严嵩'
						}
					]
				},
				methods: {
					//添加
					add() {
						this.list.push({
							id: this.id,
							name: this.names
						});
						this.id = '';
						this.names = ''
					},
					//删除
					del(index){
						this.list.splice(index,1)
					}
				}
			})
		</script>
	</body>

效果如图所示
在这里插入图片描述

动画钩子

可以在属性中声明 JavaScript 钩子

<transition
v-on:before-enter=“beforeEnter”
v-on:enter=“enter”
v-on:after-enter=“afterEnter”
v-on:enter-cancelled=“enterCancelled”

v-on:before-leave=“beforeLeave”
v-on:leave=“leave”
v-on:after-leave=“afterLeave”
v-on:leave-cancelled=“leaveCancelled”

// …
methods: {
// --------
// 进入中
// --------

beforeEnter: function (el) {
// …
},
// 当与 CSS 结合使用时
// 回调函数 done 是可选的
enter: function (el, done) {
// …
done()
},
afterEnter: function (el) {
// …
},
enterCancelled: function (el) {
// …
},

// --------
// 离开时
// --------

beforeLeave: function (el) {
// …
},
// 当与 CSS 结合使用时
// 回调函数 done 是可选的
leave: function (el, done) {
// …
done()
},
afterLeave: function (el) {
// …
},
// leaveCancelled 只用于 v-show 中
leaveCancelled: function (el) {
// …
}
}

这些钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用。

当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。

推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css=“false”,Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。

动画钩子详情请参照vue官网,vue动画钩子

vue实例的生命周期

1.对于生命周期我们先了解什么是生命周期?从vue实例创建、运行、到销毁的期间,总是伴随着各种各样的事件,这些事件统称为生命周期。
2.生命周期钩子:生命周期过程中的事件函数名叫做生命周期钩子。
3.vue的生命周期函数:
如下图所示
在这里插入图片描述
在这里插入图片描述
创建期间的生命周期函数:
beforeCreated:实例刚在内存模板中创建出来,此时还没有初始化好data与methods,换句话说此时data中的数据与methods中的方法不能使用与获取;
created:实例已经在内存中创建ok,此时data中的数据与methods中的方法可以获取查看,但是还没有开始编译模板;
beforeMoubted:此时已经完成模板的编译,只是在内存中渲染了模板,但是还没有将数据渲染到页面中;
mounted:已经完成了模板的编译,已经挂载到了页面的容器中;

运行期间的生命周期函数:
beforeUpdated:当数据发生变化时,此时data中的状态值已经保持最新,但是页面的数据还是旧的数据;
updated:实例已经更新完毕,此时data中的状态值已经与页面的显示数据保持一致,页面已经重新渲染好了;

销毁期间的生命周期函数:
beforeDestory:实例在销毁之前调用此步,解绑之间的束缚,但是里面的方法还有指令,过滤器都还可以用,只是在做准备工作;
destory:此时实例已经销毁,里面的方法还有data不能使用,所有的监听都会被移除。

如下代码所示:

<body>
		<div id="box" style="width: 100px;">
			<p id="p">{{ msg }}</p>
			<input type="button" value="修改msg" @click="msg='nihao'">
		</div>
		<script src="../js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#box',//控制的元素
				data(){//数据
					return{
						msg:'hello world'
					}
				},
				methods:{//方法
					show(){
						alert('hello')
					}
				},
				beforeCreate(){
				//实例刚在内存中被创建出来,此时还没有初始化好data与methods,不能找到里面的数据与方法
					console.log(this.msg)//undefined
				},
				created(){
				//实例已经在内存中创建ok,此时data与methods中的数据与方法可以拿到了
					console.log(this.msg)//hello world
				},
				beforeMount(){
					//此时模板已经编译完成,但是尚未把模板渲染到页面中,此时还是内置模板字符串
					console.log(document.getElementById('p').innerText)//{{ msg }}
				},
				mounted(){
					//此时已经完成模板编译,页面中已经可以看见数据显示了
					console.log(document.getElementById('p').innerText)//hello world
				},
				//当数据发生更新变化时,执行以下的钩子函数
				beforeUpdate(){
					//当数据发生变化时,此时data中的状态值是最新的,但是页面中的数据还是旧的
					//因为此时还没有重新渲染dom节点
					console.log('界面中的元素:'+ document.getElementById('p').innerText)//hello world
					console.log('data中的msg数据:'+ this.msg)//nihao
				},
				updated(){
					//此时data中的状态值与页面保持一致了,data中的数据是什么页面中的数据就显示什么
					console.log('界面中的元素:'+ document.getElementById('p').innerText)//nihao
					console.log('data中的msg数据:'+ this.msg)//nihao
				},
				beforeDestory(){
					//vue已经从运行阶段到销毁阶段了,当执行此函数时,实例上的data与methods此时已经处于销毁状态
					//但是此时还没有真正销毁,其中的数据还有methods都还可以用,只是处于准备状态(用的很少)
				},
				destoryed(){
					//此时组件已经被完全销毁,组件不能被正常使用(一般用作定时器的清除)
				},
				//上面有创建销毁的过程,如果用户操作频繁,则对网站的性能消耗特别大
				//下面的是vue的激活钩子函数,可以使用vue的内置组件<keep-alive></keep-alive>包裹元素
				//这样达到当你再次使用此页面时还保持你原来想要的状态(根据要求使用,一般使用很少)
				activated(){
					//激活状态的钩子函数,
				},
				deactivated(){
					//停止激活状态的钩子函数
				}
			})
		</script>
	</body>

vue的组件化开发

什么是组件?

组件的出现就是为了拆分vue实例的代码量的,能够让我们以不同的组件来划分不同的功能模块,将来我们需要什么样的功能,就去调用对应的组件即可。

组件化与模块化的不同

组件化:是从UI界面的角度惊醒划分的,方便UI组件的重复使用;
模块化:是从代码逻辑的角度进行划分的,方便代码的分层开发,保证每个功能的单一。

组件的使用

全局组件

定义在vue实例(new Vue({}))之前
Vue.component(‘组件名’,{
template:‘html代码’,
data(){…},
mehtods:{…}
})

<body>
		<div id="app">
			<we></we>
			<hr />
			<we></we>
			<hr />
			<we></we>
		</div>
		<template id="temp">//注template模板下只有一个根目录,这是vue的规定
			<div>
				<input type="button" value="+1" @click="adds"/>
				<!-- <h4> {{ count }} </h4> -->
				<h4> {{ counts }} </h4>
			</div>
		</template>
		<script src="../../js/vue.js"></script>
		<script type="text/javascript">
			var obj={counts:0}
			Vue.component('we',{
				template:'#temp',
				data(){
					// return{
					// 	count: 0
					// }
					return obj
				},
				methods:{
					add(){
						this.count++;
					},
					adds(){
						this.counts++;
					}
				}
			})
			var vm = new Vue({
				el:'#app'
			})
		</script>
	</body>
局部组件(私有组件)

定义在实例当中,如下代码所示:

<body>
		<div id="app">
			<h4>{{ msg }}</h4>
			<mycom></mycom>
			<hr />
			<mycom></mycom>
			<hr />
			<mycom></mycom>
		</div>
		
		<template id="temp">
			<div>
				<input type="button" value="+1" @click="add"/>
				<h3>{{ count }}</h3>
			</div>
		</template>
		<script src="../../js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#app',
				data:{
					msg:'你好'
				},
				methods:{
					adds(){
						this.count++;
					}
				},
				components:{
					mycom:{//这是创建的局部组件
						template:'#temp',
						data(){
							return {count:0}
						},
						methods:{
							add(){
								this.count++;
							}
						}
					}
				}
			})
		</script>
	</body>
组件页面之间的切换
<body>
		<div id="app">
			<a href="" @click.prevent="qiehuan='log'">登录</a>
			<a href="" @click.prevent="qiehuan='res'">注册</a>
			<a href="" @click.prevent="qiehuan='asd'">其它</a>
			<keep-alive>
				<!-- component是一个占位符,is是属性,可以用来展示组件的名称 -->
				<component :is = "qiehuan"></component>
			</keep-alive>
		<script src="../../js/vue.js"></script>
		<script type="text/javascript">
			Vue.component('log',{
				template:'<h2>登录页面</h2>'
			})
			Vue.component('res',{
				template:'<h2>注册页面</h2>'
			})
			Vue.component('asd',{
				template:'<h2>其它页面</h2>'
			})
			var vm = new Vue({
				el:'#app',
				data:{
					qiehuan:'log'
				}
			})
		</script>
	</body>

如图所示
在这里插入图片描述

组件之间的传值

1.父组件向子组件传值
父组件通过props向子组件传值,子组件定义属性名,把父组件的数据绑定在属性上,然子组件中使用props接收,如下代码所示:

<body>
		<div id="app">
			<coml :message = 'msg'></coml>
		</div>
		<script src="../../js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#app',
				data:{
					msg:'这是实例的数据',
					check:false,
					num:23,
					list:[{id:1,name:'李四1'},{id:2,name:'李四2'}]
				},
				methods:{},
				components:{
					coml:{
						template:'<h2>这是子组件上面的html代码----{{ message }}</h2>',
						data(){
							return{msgs:'这是子组件上面的数据'}
						},
					props:['message'],//这里可以是数组,也可以是对象
					//props: {
					//message:{
					//type:['String']//数据类型
					//default:'父组件不给值时候,这就是默认值',
					// required:true//这是设置必传,与default二选一
					//}
                    //}
					methods:{}
					}
				}
			})
		</script>
	</body>

2.父组件向子组件传递方法
父组件向子组件传递方法通过绑定自定义事件,定义事件属性名,然后在子组件中使用$emit()的方法使用,如下代码所示

<body>
		<div id="app">
			<coml @func = 'show'></coml>//自定义事件绑定
		</div>
		<template id="temp">
			<div>
				<h2>这是组件当中的html代码</h2>
				<input type="button" value="按钮" @click="myclick"/>
			</div>
		</template>
		<script src="../../js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#app',
				data:{
					msg:'这是父组件中的数据'
				},
				methods:{
					show(){
						console.log('这是父组件当中的方法')
					}
				},
				components:{
					coml:{
						template:'#temp',
						data(){
							return{msg1:'这是子组件当中的数据'}
						},
						methods:{
							shows(){
								console.log('这是子组件中的方法')
							},
							myclick(){
						this.$emit('func')//使用此完成父传子的方法
							}
						}
					}
				}
			})
		</script>
	</body>

3.子组件向父组件传值
子组件向父组件传值也是通过绑定自定义事件,然后子组件通过$.emit(‘方法名’,参数),这里的参数代表子组件上面的属性,可以是数据也可以是其他的。

<body>
		<div id="app">
			<coml @func = 'show'></coml>//这是绑定的自定义事件
			<h4>{{ msg }}</h4>
		</div>
		<template id="temp">
			<div>
				<h3>这是子组件中的html代码</h3>
				<input type="button" value="按钮" @click="myclick"/>
			</div>
		</template>
		<script src="../../js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#app',
				data:{
					msg:null
				},
				methods:{
					show(data){
						this.msg = data;
						console.log(this.msg)//这是子组件的数据
					}
				},
				components:{
					coml:{//这是创建的子组件
						template:'#temp',
						data(){
							return{
								msgs:'这是子组件中的数据'
							}
						},
						methods:{
							myclick(){
							//这是使用的方法与携带的子组件的参数数据
								this.$emit('func',this.msgs)
							}
						}
					}
				}
			})
		</script>
	</body>

4.平行组件之间的传值
平行组件之间传值思路:
①.先创建一个过渡的bus对象 let bus = new Vue(),通过这个对象将数据传递过去
②.创建两个平行之间的组件test1,test2,确定1向2中传递数据
③.在1中设置数据,并且在1中调用方法使用 e m i t 方 法 , b u s . emit方法,bus. emitbus.emit(‘方法的名字’,参数(指数据))
④.在2中接收参数,使用bus.$on(‘方法的名字’,(val)=>{val就是1中传递过来的数据})

<body>
		<div id="app">
			<mycom></mycom>
			<mycon></mycon>
		</div>
		<template id="test1">
			<span @click="handlerClick">传值</span>
		</template>
		
		<template id="test2">
			<span>{{ testdata }}</span>
		</template>
		<script src="../../js/vue.js"></script>
		<script type="text/javascript">
			/*
			平行组件之间传值思路:
			1.先创建一个过渡的bus对象  let bus = new Vue(),通过这个对象将数据传递过去
			2.创建两个平行之间的组件test1,test2,确定1向2中传递数据
			3.在1中设置数据,并且在1中调用方法使用$emit方法,bus.$emit('方法的名字',参数(指数据))
			4.在2中接收参数,使用bus.$on('方法的名字',(val)=>{val就是1中传递过来的数据})
			*/
			let bus = new Vue();
			new Vue({
				el:'#app',
				data(){
					return{}
				},
				methods:{},
				components:{
					mycom:{
						template:'#test1',
						data(){
							return{
								testData:'我是test1的数据'
							}
						},
						methods:{
							handlerClick(){
								bus.$emit('func',this.testData)
							}
						}
					},
					mycon:{
						template:'#test2',
						data(){
							return{
								testdata:''
							}
						},
						methods:{
							add(){
								bus.$on('func',(val)=>{
									this.testdata = val;//val代表传过来的值
									console.log(this.testdata)
								})
							}
						},
						created(){
							this.add()
						}
					}
				}
			})
		</script>
	</body>

以上四种传值方式最好学习者能自己敲一敲代码,能在浏览器上面运行看看效果,能深层的了解传值的方式,希望这些代码可以帮助你加深学习的兴趣。

5.组件插槽(数据的分发)

<body>
		<div id="app">
			<asd>
			//将下面的p标签分开到模板当中显示
				<template slot='header'>
					<p>头部标题1</p>
					<p>头部标题2</p>
				</template>
				<template>
					<p>内容1</p>
					<p>内容2</p>
				</template>
				<template slot='foother'>
					<p>底部标题1</p>
					<p>底部标题2</p>
				</template>
			</asd>
		</div>
		<template id="tmpl">
			<div>
				<header>
					<slot name='header'></slot>
				</header>
				<main>
					<slot></slot>
				</main>
				<footer>
					<slot name='foother'></slot>
				</footer>
			</div>
		</template>
		
		<script src="../../js/vue.js"></script>
		<script type="text/javascript">
			Vue.component('asd',{
				template:'#tmpl',
			})
			var vm = new Vue({
				el:'#app',
				data:{}
			})
		</script>
	</body>

6.使用ref获取DOM元素和组件
给你的元素或者组件绑定一个ref=‘名字’,后面在方法中可以通过$refs.名字就可以获取你的元素与组件

<body>
		<div id="app">
			<input type="button" value="获取元素" @click="getelement"/>
			<h3 ref='myh3'>我是一个特别的元素</h3>
		</div>
		<script src="../js/vue.js"></script>
		<script type="text/javascript">
			var vm = new Vue({
				el:'#app',
				data:{},
				methods:{
					getelement(){
				//this.$refs是一个集合,包含了所有的ref,
			//里面还包含其他属性,比如$root根节点,$parent父节点...等等
						console.log(this.$refs.myh3.innerText)
					}
				}
			})
		</script>
	</body>

vue 中的路由

基本使用

首先需要下载路由,1.可以使用cdn的链接通道,必须在有网的情况下引入https://unpkg.com/vue-router/dist/vue-router.js,在引入vue-router之前必须先引入vue.js;
2.下载路由使用npm install vue-router;引入下面内容
import Vue from ‘vue’
import VueRouter from ‘vue-router’
Vue.use(VueRouter)
然后就可以使用路由了
如下步骤所示

<body>
		<div id="app">
		<router-link to="/login" tag='button'>登录</router-link>
		<router-link to='/register' tag='button'>注册</router-link>
		<router-view></router-view>//表示占位符,用来显示组件的信息
		</div>
		<script src="../js/vue.js"></script>
		<script src="../js/vue-router.js"></script>
		<script type="text/javascript">
			//第一步:创建组件的模板对象
			var login = {
				template:'<h1>登录组件</h1>',
				data(){},
				methods:{}
			}
			var register = {
				template:'<h1>注册组件</h1>',
				data(){},
				methods:{}
			}
			//第二步:创建路由对象
			var vt = new VueRouter({
				routes:[//表示路由匹配规则组合
					{path:'/login',name:'login',component:login},
					{path:'/register',name:'register',component:register}
				]
			})
			//第三步:创建vue实例,并将路由对象挂载在app中
			var vm = new Vue({
				el:'#app',
				data:{},
				methods:{},
				router:vt//挂载路由对象于app中
			})
		</script>
	</body>

默认渲染成a标签,如果想要渲染成其他标签元素,则后面加上tag=‘元素’

路由的嵌套与切换

路由分为一级路由与多级路由,如果路由需要嵌套,则需要在路由配置里面加上children属性,然后配置路径与展示页面,如下代码所示:

<style>
			.box{
				color: red;
			}
			.box:hover{
				color: #7FFFD4;
			}
		</style>
<body>
		<div id="app">
			
			<!-- <a href="#/login">登录</a>
			<a href="#/register">注册</a> -->
			
			<!-- 默认渲染成a标签,如果想渲染成其它元素标签,则在里面加入tag=‘button’ -->
			<router-link to='/login' tag='button'>登录</router-link>
			<router-link to='/register' tag='button'>注册</router-link>
			
			<!-- 这是vue-router提供的,专门用来当作显示占位符的,将来路由规则匹配到的组件就会展示在占位符中 -->
			<router-view></router-view>
		</div>
		<!-- 二级路由 -->
		<template id="login">
			<div>
				<router-link to='/login/login1'>登录1</router-link>
				<router-link to='/login/login2'>登录2</router-link>
				<router-view></router-view>
			</div>
		</template>
		
		<script src="../../js/vue.js"></script>
		<script src="../../js/vue-router.js"></script>
		<script type="text/javascript">
			//创建组件模板对象
			
			//组件的模板对象
			//一级路由的组件
			var login = {
				template:'#login',
				methods:{
					tos(){
						this.$router.push({path:'/register'});//强制跳转
				//$router为VueRouter实例,想要导航到不同URL,则使用$router.push方法,
				//返回上一个history使用$router.go方法。
					}
				}
			}
			var register = {
				template:'<h1>注册组件<button @click="tol">到登录</button></h1>',
				methods:{
					tol(){
						this.$router.back();
					}
				}
			}
			//二级路由的小组件
			var login1 = {
				template:'<h1>小登陆1</h1>'
			}
			var login2 = {
				template:'<h1>小登陆2</h1>'
			}
			
			//  **创建组件(这是错误的方法)
			// Vue.component('login',{
			// 	template:'<h1>登录组件</h1>'
			// })
			
			//创建路由对象,
			//在new路由对象时候,可以为构造函数传递一个配置对象
			var routerobj = new VueRouter({
				//route//这表示路由匹配规则
				routes:[
					//每个路由规则都是一个对象,这个规则对象身上有两个属性
					//属性1:path表示监听路由的链接地址
					//属性2:component表示 如果前面匹配到的path,则展示对应组件component
					
					//component的属性值必须是一个组件的模板对象,不能是组件的引用名称
					//以及路由path必须加/
					//{path:'/',component:login},//设置默认显示登录组件
					{path:'/',redirect:'/register'},//重定向,设置默认页面
					{path:'/login',component:login,
					//二级路由新加的属性
					children:[
						{path:'login1',component:login1},
						{path:'login2',component:login2}
					]},
					{path:'/register',component:register}
				],
				//router-link-active设置选中路由的样式
				//给选中的路由加一个class名
				linkActiveClass:'box'
			})
			//创建vue实例对象
			var vm = new Vue({
				el:'#app',
				data:{},
				methods:{},
				router:routerobj//将路由规则对象注册到这个实例上面,用来监听URL地址的变化,然后展示相应的组件
			})
		</script>
	</body>

如下图所示
在这里插入图片描述

路由传参

1.使用query方式传递参数
使用query方式传递参数,是直接在地址栏上面以?+参数形式传递,当你想要获取传递的参数时,使用this.$route.query.参数名,query传递参数时不需要配置路由匹配规则,如下代码所示:

<body>
		<div id="app">
	<!-- 这种传递参数的方法不需要修改path的匹配规则,可以直接的通过this.$route.query调用?后面的数据 -->
			<router-link to="/login?id=10&name=lisi" tag='button'>登录</router-link>
			<router-link to='/register' tag='button'>注册</router-link>
			<router-view></router-view>
		</div>
		<script src="../../js/vue.js"></script>
		<script src="../../js/vue-router.js"></script>
		<script type="text/javascript">
			//组件的模板对象
			var login = {
				template:'<h1>登录组件------{{ $route.query.name }}</h1>',
				created(){//组件声明周期钩子函数
					console.log(this.$route.query.name)//$route是一个跳转的路由对象,
				//每一个路由都会有一个route对象,是一个局部的对象,
				//可以获取对应的name,path,params,query等
				}
			}
			var register = {
				template:'<h1>注册组件</h1>'
			}
			
			//创建路由
			var vt = new VueRouter({
				routes:[
					{path:'/login',component:login},
					{path:'/register',component:register}
				]
			})
			
			//创建vue实例
			var vm = new Vue({
				el:'#app',
				data:{},
				methods:{},
				router:vt
			})
		</script>
	</body>

2.使用params传递路由参数(路由匹配规则中匹配的是name中的路径)

<body>
		<div id="app">
			<router-link :to="{name:'login',params:{id:12,name:'lisi'}}" tag='button'>登录</router-link>
			<router-view></router-view>
		</div>
		<script src="../../js/vue.js"></script>
		<script src="../../js/vue-router.js"></script>
		<script type="text/javascript">
			//组件的模板对象
			var login = {
				template:'<h1>登录组件--{{ $route.params.name }}---{{ $route.params.id }}</h1>',
				created(){//组件声明周期钩子函数
					console.log(this.$route.params.id)//$route是一个跳转的路由对象,
				//每一个路由都会有一个route对象,是一个局部的对象,
				//可以获取对应的name,path,params,query等
				}
			}
			
			//创建路由
			var vt = new VueRouter({
				routes:[
					{path:'/login/:id/:name',name:'login',component:login}
				]
			})
			
			//创建vue实例
			var vm = new Vue({
				el:'#app',
				data:{},
				methods:{},
				router:vt
			})
		</script>
	</body>

3.响应路由参数的变化
当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用,此时想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象:

<body>
		<div id="app">
			<!-- 动态绑定的to找的是匹配规则name的路径 -->
			<router-link :to="{name:'User',params:{id:12,name:'lisi'}}" tag='button'>用户1</router-link>
			<router-link :to="{name:'User',params:{id:11,name:'zhangsan'}}" tag='button'>用户2</router-link>
			<router-view></router-view>
		</div>
		<script src="../../js/vue.js"></script>
		<script src="../../js/vue-router.js"></script>
		<script type="text/javascript">
			//组件的模板对象
			var User = {
				template:'<h1>我是用户--{{ $route.params.name }}---{{ $route.params.id }}</h1>',
				watch:{
					'$route'(to,from){
						console.log(to.params.id)
					}
				}
			}
			
			//创建路由
			var vt = new VueRouter({
				routes:[
					{path:'/User/:id/:name',name:'User',component:User},
					{path:'/User:id/:name',name:'User',component:User}
				]
			})
			
			//创建vue实例
			var vm = new Vue({
				el:'#app',
				data:{},
				methods:{},
				router:vt
			})
		</script>
	</body>

如图所示在这里插入图片描述

路由守卫

路由守卫是在路由跳转前做一些验证,比如登录前进行页面跳转验证
1.全局前置守卫

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // to.path即将要进入的目标 路由对象
  //from.path当前导航正要离开的路由
  //next()指向后执行的函数,且此函数必须执行。next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。
})

2.全局后置守卫
它和前置守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

router.afterEach((to, from) => {
  // ...
})

3.路由独享守卫
你可以在路由配置上直接定义 beforeEnter 守卫,只会作用于被设置守卫的路由

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

4.组件内的守卫

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
}

注意 beforeRouteEnter 是支持给 next 传递回调的唯一守卫。对于 beforeRouteUpdate 和 beforeRouteLeave 来说,this 已经可用了,所以不支持传递回调,因为没有必要了。

beforeRouteUpdate (to, from, next) {
  // just use `this`
  this.name = to.params.name
  next()
}

这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。

beforeRouteLeave (to, from, next) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
  if (answer) {
    next()
  } else {
    next(false)
  }
}

总结

经过以上的分析总结,vue其实说难不难,说简单不简单,难在于使用时候需要了解其中的数据驱动的方法,以及对于原生js的编程能力要强,这是学习者需要掌握的;简单在于不需要编程者操作dom,能够简化很多多余的代码,而更多的关心数据的变化与视图的渲染,如果你是一位小白,之前没有接触过过vue的知识,这篇文章一定能够让你了解vue的一些基本用法,能够熟练的运用它们,在下一章中会介绍工作中使用的技术,vue全家桶(vue-cli,vue-router,axios,vuex,插件)以及webpack在vue中的配置使用。
如果你觉得这篇文章有帮到你还请点赞分享,文章中存在不足之处需要修改,还请留言告知!!!!!

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值