【前端23_Vue】生命周期、常见API的使用,v-key的特点、组件及通信、插槽、路由


Vue

因为之前曾接触过小程序的开发,所以 入手 Vue 相对爽了一些,因为思想都是数据绑定,Vue是华人尤雨溪开发的,这可是个大佬,B站上有个关于大佬的纪律片,是 Up主:鱼C-小甲鱼 翻译的,有兴趣的话可以看看。

https://www.bilibili.com/video/BV1dT4y1V7Dn


M V VM

  • 他是一种架构方式、开发思想

  • M:Model 数据模型 (操作数据的类)

  • V:View 视图界面 (HTML)

  • VM:ViewModel 视图模型


Vue 的思想

Vue是比较重要的是用数据来驱动页面,下面是一个简单的用Vue实现的页面

	<body>
		<div id="app">{{message}}</div>
	</body>
	<script src="js/vue.js"></script>
	<script>
		var app = new Vue({
			el:"#app",
			data:{
				message:"hello world"
			}
		})
	</script>

Vue 实例中常见对象

el

获取元素,你可以用#id.类名,类似JQuery的选择器等等,也可以用document.querySelectAll()之类的

data

实例中的数据都放在这里

computed 计算属性

计算属性的结果是放在缓存里的

method 方法

顾名思义,可以在这里定义方法


生命周期函数

需要记得有

  • beforeCreatedatamethods都不能使用(可以在此声明周期中打印 data,报undefined,或是执行method方法:报错

  • create:可以使用 datamethods

  • beforeMount:节点在内存中已经生成好了,但是没有挂载到页面上(我们可以通过document.querySelector('').innerHTML); 来获取页面上的信息,因为没有渲染到页面上,此时还是模板字符串的内容{{ msg }},说明数据还没有替换到页面上,但是内存里已经渲染好了)

  • mounted:挂载到页面上了,通过document.querySelector('').innerHTML) 也能获取到挂在上去的msg了(mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其他操作的话,这个实例,就静静的躺在内存中,不动弹了)
    在这里插入图片描述

  • beforeUpdata:数据已经更新了,并且内存中也更新完了,但是没有渲染到页面上(测试方法:写个按钮,改变data,触发此函数)

  • updated:渲染到页面上了,此时已经是新的数据

  • beforeDestroy:从运行阶段,进入到销毁阶段,此时Vue实例上所有的 datamethods 都可以使用

  • destroyed:销毁完毕,什么都没了~

其实有规律可循,创造-挂载-更新-销毁
在这里插入图片描述

测试生命周期如下

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>生命周期测试</title>
        <script src="vue.js" type="text/javascript" charset="utf-8"></script>
    </head>
	<body>
		<div id="app">
			<div id="h3">{{ msg }}</div>
			<input type="button" @click="msg = 'No'" value="点我变成No">
		</div>
	</body>

	<script type="text/javascript">
		var vm = new Vue({
			el   : "#app",
			data : {
				msg:'我是信息'
			},
			methods:{
				show(){
					console.log(this.msg);
				}
			},
			beforeCreate(){
				// 这是第一个生命周期 beforeCreate,表示实例完全被创建出来之前,会执行它
				// 此时 data 和 methods 是不能使用的。
				console.log('1. beforeCreate:', this.msg);
			},
			created(){
				// 这是第二个生命周期,完成了data 和 method 的加载。
				console.log('2. created:', this.msg);
				// this.show();
			},
			beforeMount() {
				// 这是第三个生命周期,表示 模板已经加载到内存中编译完成了,但是没有把模板渲染到页面中	
				console.log('3. beforeMount:', document.querySelector('#h3').innerHTML);		// {{ msg }}
				// 在 beforeMount 执行的时候,页面中的元素,黑没有被真正替换过来,只是之前写的一些模板字符串
			},
			mounted() {
				// 这是遇到的第4个生命周期函数,表示,内存中的模板已经挂载到页面中了,用户已经可以看到渲染好的页面了
				console.log('4. mounted:', document.querySelector('#h3').innerHTML);		// 我是信息
				// 注意1:mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了
				// 此时,如果没有其他操作的话,这个实例,就静静的躺在内存中,不动弹了
				console.log('********************************************************************');
				console.log('********************************************************************');
				// 注意2:如果要通过某些插件操作页面上的 dom 节点,最早要在 mounted 中进行
			},
			
			// 以下两个是:运行阶段的生命周期函数
			// 这两个事件,会根据 data 的变化,有选择性的触发 0 次或 多次
			beforeUpdate() {
				// 这个时候,页面没有被更新,【数据更新了吗? 肯定更新了】
				console.log('beforeUpdate:data 中的 msg 的值是:', this.msg);
				console.log('beforeUpdate:页面中的节点内容:',document.querySelector('#h3').innerHTML,'(说明内存中的数据已经改变了,但是没有渲染到页面上)');
				// 结论:当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的
				// 此时 data 的数据是最新的,页面还是旧的
				console.log('---------------------------------------------------------------------');
			},
			updated() {
				console.log('updated:data 中的 msg 的值是:', this.msg);
				console.log('updated:页面中的节点内容:',document.querySelector('#h3').innerHTML);
				// 页面和data 的数据已经保持同步了,都是最新的
			},
			beforeDestroy() {
				// 当执行beforeDestroy 钩子函数的时候,Vue实例就已经从 运行阶段,进入到了销毁阶段
				// 注意:当执行 beforeDestory 的之后,实例身上所有的 data 和所有的 methods,以及过滤器,指令...
				// 都处于可用的状态,此时,还没有真正的执行销毁过程
			},
			destroyed(){
				// 组件已经完全被销毁了
			}
		});
	</script>
</html>

参考资料 黑马程序员:Vue 的声明周期


常见API的使用

v-if 条件

	<body>
		<!-- 条件语句必须if/else紧跟着 -->
		<div id="app">
			{{message}}
			<div v-if="message == 'hello world'">if</div>
			<div v-else-if="message == 'hello world1'">else-if</div>
			<div v-else>else</div>
		</div>
	</body>
	<script src="js/vue.js"></script>
	<script>
		var app = new Vue({
			el:"#app",
			data:{
				message:"hello world"
			}
		})
	</script>

v-show

  • v-show不能搭配template ,即使条件不对也会显示到页面上
<template v-show="1 == 2">
	<h1>我是个标题</h1>
</template>
  • 如果v-show里面的条件不对的话,页面渲染的时候会使用display:none把他隐藏掉
<div v-show="1 == 2">
	<h1>我是个标题</h1>
</div>

这里有个经典面试问题:v-ifv-show 有什么区别?如果频繁的显示隐藏,我用那个更好?

要回答这个问题就需要知道这两个命令是怎么工作的,v-if 它是根据条件的真假,从而是否创建元素,v-show 是控制css的属性display:none,也就是不管真假,他都会创建并渲染,只是控制css达到不显示的效果而已。

参考文档 Vue中v-if和v-show区别与用法解析

v-for 循环

  • 比方说我要循环一个名字叫li的数组
<body>
	<div id="app">
	 	<!-- 这里也可以写成 (each,index) of li,借用了ES6的语法-->
		<div v-for="(each,index) in li">
			each:{{each}}-----index:{{index}}
		</div>
	</div>
</body>
<script src="../js/vue.js"></script>
<script>
	var app = new Vue({
		el:"#app",
		data:{
			li:['one','two','three','four','five']
		}
	})
</script>

在这里插入图片描述


v-key**

参考博文1
参考博文2

  • 虚拟DOM的Diff算法,其核心是基于两个简单的假设:1. 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。2. 同一层级的一组节点,他们可以通过唯一的id进行区分。
  • 总结一句话:为了更好的让Vue更新虚拟Dom,key来给每个节点做一个唯一标识。
  • 影响:如果不加上标识的话,在插入的时候会发生错误
    在这里插入图片描述

在这里插入图片描述

v-cloak 取消抖动

用Vue渲染页面的时候,你刷新页面,会有页面没有加载数据就渲染出来的情况,一闪而过(尝试截取动图但是截不到),但是为了美,这种缺点怎么可能忍呢!!!

只需两步轻松解决

  • 在标签里写上 v-cloak
  • 在样式里写[v-cloak]{ display: none; }

举个小例子

<style>
	[v-cloak]{
		display: none;
	}
</style>
<body>
	<div id="app" v-cloak></div>
</body>

v-once

首次渲染之后,页面不再随着数据的变化而变化

	<body>
		<div id="app">
			<div v-once>
				<!--可以在控制台上改变数值 app.message = 'nihao' -->
				{{message}}
			</div>
		</div>
	</body>
	<script src="js/vue.js"></script>
	<script>
		var app = new Vue({
			el:"#app",
			data:{
				message:"hello world"
			}
		})
	</script>

v-bind 绑定属性 **

v-bind可以简略写成:,v-bind:后面接标签的属性,用来绑定标签的属性。

<body>
		<div id="app">
			<!-- 下面两个div的绑定类是一样的,都是name1 -->
			<div v-bind:class="className"> v-bind:class="className"</div>
			<div :class="className">:class</div>
		</div>
	</body>
	<script src="js/vue.js"></script>
	<script>
		var app = new Vue({
			el:"#app",
			data:{
				className:"name1"
			}
		})
	</script>

在这里插入图片描述


v-on 绑定事件

  • v-on 也可以写成 @
  • 可以传递参数,如果向添加事件因子,可以@click="函数名($event)这样传递
<!-- 下面两个div都绑定了click点击事件,效果一样 -->
<div v-on:click=""></div>
<div @click=""></div>
<button @click="hand2(10,$event)">btn2---$event</button>
  • v-on也可以绑定多个事件
	<input type="text" v-on:click="click1()" v-on:change="change1" v-model="data1">
	<input type="text" v-on:click="click1(),change1()" v-model="data1">
修饰符

.这个点就是修饰符,能修饰什么呢?下面就是例子

冒泡与捕获
  • 阻止冒泡:.stop
<div @click="fa">fa
	<div @click.stop="son">son</div>
	<!-- 这样,点击son,就不会出发fa的点击事件了 -->
</div>
  • 捕获:.capture
<div @click.capture="fa">fa
	<div @click="son">son</div>
</div>
<!-- 这样,点击son,就会先触发fa,然后son -->
按键触发事件
  • 37是键盘上的左方向键
  • 如果向要组合按键,触发连招的话,可以连着修饰符写,如下
<input type="text" @keydown.37="key1Handler">
<input type="text" @keydown.space="key1Handler1" placeholder="space">
<!-- 组合按键 -->
<input type="text" @keydown.shift.83="key1Handler2" placeholder="shift+S">

v-html 编译 & v-pre 跳过

注意 v-html 的一些细节

	<body>
		<div id="app">
			<span v-html="tar">span1</span>
			<span v-pre="tar1">span2</span>
		</div>
	</body>
	<script src="js/vue.js"></script>
	<script>
		// v-html 转化成html
		// 注意转化后的页面格式,是插入此标签内了,标签内原有的内容将被覆盖
		
		// v-pre 跳过这个元素和它的子元素的编译过程。
		// 可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
		var app = new Vue({	
			el:'#app',
			data:{
				tar:"<a href='#'>11</a>",
				tar1:"<a href='#'>11</a>"
			}
		})
	</script>

图片展示在这里插入图片描述


v-model 绑定输入

  • v-model可以绑定inputtextarea的文本
<body>
	<div id="app" v-cloak> 
		<input type="text" v-model="message">
		{{message}}
		<textarea rows="" cols="" v-model="message">
			
		</textarea>
	</div>
</body>
<script src="../js/vue.js"></script>
<script>
	var app = new Vue({
		el:"#app",
		data:{
			message:"hello world"
		}
	})
</script>
  • input失焦时在改变data,把输入框中的值变为number、去掉输入框中值的首尾空格
<body>
	<div id="app">
		<!-- .lazy 是change事件,当失去焦点的时候会改变 -->
		<input type="text" v-model.lazy="mes">
		
		<!-- .number 把输入数据变成类型为number -->
		<input type="text" v-model.number="mes">
		
		<!-- .trim 去首和尾空格 -->
		<input type="text" v-model.trim="mes">
		
		<h1>{{mes}}</h1>
	</div>
</body>
<script src="../js/vue.js"></script>
<script>
	var app = new Vue({
		el:"#app",
		data:{
			mes:"hello world"
		}
	})
</script>

单选框、复选框、下拉框

  • 都是通过v-model来分组,相当于校服,不同学校相当于不同的组。校服一样说明是一个学校的
  • 单选框
<body>
	<div id="app">
		<!-- 单选:多个互斥 -->
		<input type="radio" v-model="pick" value="male">	<label></label>
		<input type="radio" v-model="pick" value="female">	<label></label>
		<input type="radio" v-model="pick" value="???">		<label>男女男</label>
	</div>
</body>
<script src="../js/vue.js"></script>
<script>
	// 单选框
	// 页面上选择哪一项,pick的值就是哪一个value值
	var app = new Vue({
		el:"#app",
		data:{
			pick:"male"
		}
	})
</script>
  • 多选框
<body>
	<div id="app">
		<!-- 复选框多选 -->
		<input type="checkbox" v-model="check" value="checkBox1">		<label>复选框1</label>
		<input type="checkbox" v-model="check" value="checkBox2">		<label>复选框2</label>
	</div>
</body>
<script src="../js/vue.js"></script>
<script>
	var app = new Vue({
		el:"#app",
		data:{
			// check里存储谁被选中了
			check:[]
		}
	})
</script>
  • 下拉框
<body>
	<div id="app">
		<!-- select如果想添加多个属性,加multiple -->
		<select v-model="select">
			<!-- 默认是个option中的文本进行匹配
			 如果用了value的话优先value
			 -->
			<option>1</option>
			<option>2</option>
			<option value='你好'>3</option>
		</select>
	</div>
</body>
<script src="../js/vue.js"></script>
<script>
	var app = new Vue({
		el:"#app",
		data:{
			select:"你好"
		}
	})
</script>

组件

组件命名要求

  • 短横线分隔命名
  • 首字母大写命名

全局/局部组件定义

顾名思义,组件的使用范围不一样

  • 需要注意的是,全局组件要在实例化对象之前就要注册,说人话,就是
    在这里插入图片描述
  • 为什么要先注册在实例化呢?反过来行不行呢?我反过来会报如下的错误
[Vue warn]: Unknown custom element: <card> -
 did you register the component correctly? 
 For recursive components, make sure to provide the "name" option.

报错信息提示说:不知道的元素card,是否正确注册组件?,看一下生命周期那张流程图:创建完Vue实例之后就已经渲染完template了,这时候在注册带有template的组件的话,Vue是不认识的

<body>
	<div id="app">
		{{message}}
		<else-name></else-name>
	</div>
</body>
<script src="../js/vue.js"></script>
<script>
	// 全局组件:
	// else-name 是我自定义的标签名称
	// 命名规范:不能用驼峰命名,推荐都用小写 	
	Vue.component('else-name',{
		template:'<div>这是组件中</div>'
	})
</script>

局部的组件,这里写了两种写法

  • 直接把模板放到组件里
  • 把模板放到外边:方便修改
// 局部:只在当前vue中有效
	var child = {
		template:'<div>这是组件局部,内部中2</div>'
	}
	var app = new Vue({
		el:"#app",
		data:{
			message:'hello world'
		},
		components:{
			'demo1':{
				template:'<div>这是组件局部,内部中1</div>'
			},
			'demo2':child
		}
	})

组件中的模板

  • 模板里只能由只能有一个根元素,不能有两个以上的根元素

意思是说可以这样:<div> <div></div> </div> 不可以<div></div> <div></div>
前者两个div是父子关系,后者两个div是同级的哥们关系

组件中的变量

组件中的变量可以这样定义和使用

Vue.component('else-name',{
	template:'<div>这是组件全局-外部中{{mess1}} {{mess2}}</div>',
	data:function(){
		return {
			mess1:'<<这是组件中的data1>>',
			mess2:'<<这是组件中的data2>>'
		}
	}
})

组件的通信

父传子: props的属性
  • 是否要有必须值
  • 默认值
  • 约束数据类型
props: {
  items: {  // 必须提供字段
    required: true,
    default: 3,
    type: Array
  },
}
  • 先来个简单的,Vue的实例对象和组件的通信
    在这里插入图片描述

  • 假如我设Vue实例是爸爸,实例中的组件是儿子,儿子里又有个组件叫孙子,那么,爸爸和孙子之间怎么交流?

<body>
	<div id="app">
		<son :msgson=msgfa></son>
	</div>
</body>
<script src="../js/vue.js"></script>
<script>
	// props单项传递,父向子传
	var app = new Vue({
		el: '#app',
		data: {
			msgfa: '我是你爸爸'
		},
		components:{
			'son': {
				props:["msgson"],
				template:`<div>
							介绍:{{msgson}}
							<grandson :msggrandson='sonData'></grandson>
						  </div>`,
				components:{
					'grandson':{
						props:['msggrandson'],
						template:`<div>{{msggrandson}}</div>`
					}
				},
				data:function(){
					return {
						sonData:'儿子'
					}
				}
			}
		}
	})
</script>
子传夫:自定义事件 $emit

儿子如何向爸爸传递信息呢,也就是子向父传递,这时候用到了自定义函数

<body>
	<div id="app">
		<show @myevent="showVal"></show>
	</div>
</body>
<script src="../js/vue.js"></script>
<script>
	// 子向父亲 $emit()触发事件,只是为了传值 v-on
	Vue.component('show', {
		data: function(){
			return {
				str: '我是组件中的string'
			}
		},
		methods: {
			sendMsgToFa: function(){
				// 这里的this指向组件
				// 自定义事件
				this.$emit('myevent',this.str);
			}
		},
		template: `<button @click="sendMsgToFa">点击弹出组件传递的数据</button>`
	})
	var app = new Vue({
		el:"#app",
		data:{
			message:"hello world"
		},
		methods:{
			showVal: function(a){
				alert(a)
			}
		}
	})
</script>
  • 如果我的孙子向给儿子传递信息呢?(就是组件中的组件组件 传递信息)
<body>
	<div id="app">
		我有三个阶级关系,分别是父亲--儿子--孙子
		<son :msgson=msgfa></son>
		
	</div>
</body>
<script src="../js/vue.js"></script>
<script>
	// props单项传递,父向子传
	var app = new Vue({
		el: '#app',
		data: {
			msgfa: '我是你爸爸'
		},
		components:{
			'son': {
				props:["msgson"],
				template:`<div>
							介绍:{{msgson}}
							<grandson :msggrandson='sonData' @myevent='showVal'></grandson>
							
						  </div>`,
				components:{
					'grandson':{
						props:['msggrandson'],
						template:`<div>
										{{msggrandson}}
										<button @click="sendMsgToFa">孙子给儿子传值</button>
								  </div>`,
						methods:{
							sendMsgToFa: function(){
								// 传值不是自发的,而是事件驱动的,所以需要个绑定事件
								// 自定义事件确定了,父亲的接收函数名,和想要传递给父亲的数据,
								this.$emit('myevent','我是孙子里面的消息')
							}
						}
					}
				},
				data:function(){
					return {
						sonData:'儿子'
					}
				},
				methods:{
					showVal: function(val){
						console.log(val);
					}
				}
			}
		}
	})
</script>
中央事件总线bus:数据的中介

如果我现在还是有三层关系,分别是父亲,儿子,和孙子,父亲是Vue实例,儿子是实例中的组件,孙子是组件中的组件
如果这三个人,两两之间可以互相通信,那么就不向上面那样麻烦了,如何做到呢?

我们需要借助一个中介:中央事件总线
在这里插入图片描述

<body>
	<div id="app">
		<abc :myval="btnVal"></abc>
	</div>
</body>
<script src="vue.js"></script>
<script>
	// 注册中央时间总线
	var eventBus = new Vue();
	// 注册一个名为 abc 的组件
	Vue.component('abc', {
		props:["myval"],
		template: `<div>
				<button @click="showVal">{{myval}}</button>
			</div>`,
		methods: {
			showVal() {
				// $emit 需要事件驱动,比方点击事件,来发送信息给 eventBus
				eventBus.$emit('myevent','你好啊')
			}
		}
	})
	var app = new Vue({
		el: '#app',
		data: {
			msgfa: '我是你爸爸',
			btnVal:"点击"
		},
		mounted(){
			// 我们可以在挂载的生命周期函数里接收这个自定义事件。
			// 当点击事件触发的时候,这边的on 事件就接收到消息了
			eventBus.$on('myevent',function(res){
				console.log(res);
				this.msgfa = res;
			})
		}
	})
</script>
中央事件总线在项目中的使用

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

// bus.js
class Bus {
  constructor() {
    this.callback = {};
  }
  $on(eventName, fn) {
    // 监听,相当于添加事件
    this.callback[eventName] = this.callback[eventName] || [];
    this.callback[eventName].push(fn);
  }
  $emit(eventName, argu) {
    // 发送事件,其实就是执行时间是吧
    this.callback[eventName].forEach((item) => {
      item(argu);
    });
  }
}

module.exports = Bus;

父链 $parent
  • 子组件可以通过父链拿到父组件的所有,也可以修改父组件的数据
  • 取父组件中的数据可以,但是如果是修改的话,那么父子组件的关系就会更紧,这是解耦合的操作,不太推荐(组件之间的关系应该尽量独立,不要太过亲昵)在这里插入图片描述
<body>
	<div id="app">
		<abc :myval="btnVal"></abc>
	</div>
</body>
<script src="vue.js"></script>
<script>
	// 注册中央时间总线
	var eventBus = new Vue();
	// 注册一个名为 abc 的组件
	Vue.component('abc', {
		props:["myval"],
		template: `<div>
				<button @click="showVal">{{myval}}</button>
			</div>`,
		methods: {
			showVal() {
				console.log("this.$parent :>>", this.$parent);
			}
		}
	})
	var app = new Vue({
		el: '#app',
		data: {
			message: '我是你爸爸',
			btnVal:"点击"
		}
	})
</script>

在这里插入图片描述

子链 $children

子链跟父链差不多,不过子链打印出来的是数组~(这很好理解啊孩子可以有很多,但是你爹还能有两个嘛???)

<body>
	<div id="app">
		<button type="button" @click="seeChildComp">点击查看儿子</button>
		<abc :myval="btnVal" ></abc>
	</div>
</body>
<script src="vue.js"></script>
<script>
	// 注册中央时间总线
	var eventBus = new Vue();
	// 注册一个名为 abc 的组件
	Vue.component('abc', {
		props:["myval"],
		template: `<div>
				<button @click="showVal">{{myval}}</button>
			</div>`,
		methods: {
			showVal() {
				console.log("this.$parent :>>", this.$parent);
			},
			
		}
	})
	var app = new Vue({
		el: '#app',
		data: {
			message: '我是你爸爸',
			btnVal:"点击"
		},
		methods:{
			seeChildComp(){
				console.log("seeChildComp :>>", this.$children);
			}
		}
	})
</script>

在这里插入图片描述

给组件起名字,并通过名字获得组件 $refs
  • 给组件起名字 ref
  • 取值的话通过this.$refs.组件名字
    在这里插入图片描述
<body>
	<div id="app">
		<!-- 给组件起名字 -->
		<abc ref="Wangergou"></abc>
	</div>
</body>
<script src="vue.js"></script>
<script>
	// 注册一个名为 abc 的组件
	Vue.component('abc', {
		data: function() {
			return {
				sonMsg: "我是组件中的数据"
			}
		},
		template: `<div>
						{{sonMsg}}
					</div>`
	})
	var app = new Vue({
		el: '#app',
		data: {
			message: 'hello word'
		},
		mounted() {
			// 通过组件的名字拿到组件
			console.log(this.$refs.Wangergou);
		}
	})
</script>

组件的插槽:内容的分发

  • 插槽的作用在于内容的分发
    在这里插入图片描述
<body>
	<!-- 编译的作用域 -->
	<!-- 父组件的模板的内容实在父组件的作用域编译 -->
	<!-- 插槽 -->
	<div id="app">
		<comp>
			<!-- 可以把这个p标签注释掉,观察页面 -->
			<p>父亲模板的内容</p>	
		</comp>
	</div>
</body>
<script src="vue.js"></script>
<script>
	// slot是插槽
	Vue.component('comp',{
		template:`<div>
					<slot>如果父模板没有内容,就显示我</slot>
				</div>`
	})
	var app = new Vue({
		el:"#app",
		data:{
			message:"hello world"
		}
	})
</script>
  • 指定插槽的内容分发,我们可以给每个插槽起个名字
    在这里插入图片描述
<body>
	<!-- 插槽: 具名的插槽分发-->
	<div id="app">
		<comp>
			<!-- 注意这里不是v-slot -->
			<!-- 具名插槽 -->
			<p slot="top">top</p>
			<p slot="foot">foot</p>
			<!-- 无名插槽,注意他们插入的位置 -->
			<p>我没有名字1</p>
			<p>我没有名字2</p>
		</comp>
	</div>
</body>
<script src="vue.js"></script>
<script>
	// slot是插槽
	Vue.component('comp',{
		template:`<div>
					 <slot name="top"></slot>
					 <slot name="foot"></slot>
					 <div>
						<slot></slot>
					 </div>
				  </div>`
	})
	var app = new Vue({
		el:"#app",
		data:{
			message:"hello world"
		}
	})
</script>

动态组件 is

  • component 标签上有个属性is,里面填写组件的名字
    在这里插入图片描述
    在这里插入图片描述

路由

简单路由

在这里插入图片描述

<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript" src="vue-router.js"></script>	
	<body>
		<div id="app">
			<router-link to="/shangcheng">商城</router-link>
			<router-link to="/shuma">数码</router-link>
			<router-link to="/jiaju">家具</router-link>
			<router-view></router-view>
		</div>
	</body>
	<script>
		// 定义一些组件
		var sc = { template:`<h1>商城组件</h1>` }
		var sm = { template:`<h1>数码组件</h1>` }
		var jj = { template:`<h1>家具组件</h1>` }
		
		// 定义路由,这个跟组件一样,都是要卸载实例化vue之前!
		var router = new VueRouter({
			routes:[
				// redirect 重定向,里面写路径
				{ path: '/',redirect: '/shuma' },
				{ path: '/shangcheng',component: sc},
				{ path: '/shuma',component: sm},
				{ path: '/jiaju',component: jj}
			]
		})
		
		var app = new Vue({
			el:"#app",
			router,			//	这里需要注册路由
		})
	</script>

动态路由

  • 动态路由可以这样写,
<script type="text/javascript" src="vue.js"></script>
	<script type="text/javascript" src="vue-router.js"></script>	
	<body>
		<div id="app">
			<!-- 点击,路由跳转到 hello/65 -->
			<!-- 不过这里有个问题,这里的url是拼接关系,请看下面动图 -->
			<router-link to="hello/65">点击</router-link>
			<router-view></router-view>
		</div>
	</body>
	<script>
		// 动态路由
		var Hello = {
			template: `<h1>你好 {{$route.params.id}} </h1>`
		}
		var router = new VueRouter({
			routes:[
				{ path:'/hello/:id', component: Hello }
			]
		})
		var app = new Vue({
			el:"#app",
			router
		})
	</script>

在这里插入图片描述

路由前进/后退

通过:this.$router.go(1),参数填整数

<body>
	<div id="app">
		<router-link to="hello">点击</router-link>
		<router-view></router-view>
		<button v-on:click="back">后退</button>
		<button v-on:click="go">前进</button>
	</div>
</body>

<script>
	// 组件
	var Hello = {
		template: `<h1>名字{{name}},年龄{{age}} </h1>`,
		props:['name', 'age']
	}
	// 路由传参
	var router = new VueRouter({
		routes:[
			{ 
				path: '/hello', 
				component: Hello ,
				props: { name:'张三', age:11 }
			}
		]
	})
	var app = new Vue({
		el:"#app",
		router,
		methods:{
			// 路由的前进和后退
			go(){
				this.$router.go(1)
			},
			back(){
				this.$router.go(-1)
			}
		}
	})
</script>

监听路由

  • 我想点击登录的时候在右上角更改信息,就是把原先的登录注册按钮改成用户名和注销
  • 然而我的登录写成了组件,在组件中更改App.vue的一个data信息,奈何学术不精,百度了好久,想到通过监听路由来出发事件
  • 主要的是watch()这个API,只要路由变化就会触发,但是浏览器的后退是不会触发的
export default{
	data:function(){
		return{
			isLogin: false,
			userName:''
		}
	},
	methods:{
		zhuxiao(){
			window.sessionStorage.setItem('isLogin', false)
			this.isLogin = false
			this.$router.push({
				path: `/login`
			})
		}
	},
	watch:{
		$route(to){
			if(to.path === '/view'){
				this.isLogin = true
				this.userName = window.sessionStorage.getItem('userName')
			}
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值