指令篇
Vue的常用指令有哪些?
1.v-if 和 v-show
共同点:两者都是控制元素的显示与隐藏。
v-if可以与v-else-if,v-else搭配使用,条件渲染。条件不符合的DOM不会被渲染
v-show通过控制元素的display属性来控制节点的显示隐藏(display:none)
使用场景:由于v-if需要频繁创建销毁节点,所以不适合频繁切换显示隐藏的场景,反之,v-show适合。
2.v-for
列表渲染,用的巨多,一般axios请求回来数据,拿着v-for去一个遍历渲染到页面上。
<li v-for="(item,index) of person" :key="index">
{{item.name}}-{{item.age}}
<input type="text" />
</li>
v-for和v-if的优先级问题
vue2中:
vue2中v-for的优先级高于v-if,如果一个标签内同时使用v-for和v-if,可以实现过滤某些数据,然后渲染的效果,但是这样的话,需要遍历整个数字,遍历的时候v-if判断要不要渲染,造成了计算浪费,性能不好。
误区 并不是一次性遍历完数组渲染上去,然后再遍历数字通过v-if销毁部分节点!
解决办法 使用computed属性,过滤出符合条件的数组项,然后v-for遍历即可。
vue3中:
vue3中相反,v-if的优先级高于v-for,同样,每次渲染都要做一次条件表达式计算,浪费性能,还是用计算属性来解决。官方不推荐混一起使用。
未改进的模板:
<ul>
<li v-for="user in users" v-if="user.isActive" :key="user.id">
{{ user.name }}
</li>
</ul>
改进后如下:
模板渲染
<div>
<div v-for="(user,index) in activeUsers" :key="user.index">
{{ user.name }}
</div>
</div>
计算属性
computed: {
// 在computed里先做好判断,这里过滤的成本远比v-if的成本低
activeUsers: function() {
return this.users.filter(function(user) {
return user.isShow;
})
}
}
key可不可以使用index
可以使用,但是会有问题,如果对数据进行逆序添加,逆序删除等破坏DOM元素顺序的操作,会造成效率低的问题,如果结构中还有输入类的input框,会导致界面出现问题。
例子:比如往最前面加一个元素,根据索引新加的为0,会进行diff算法,发现不一样,只能重新生成真实DOM,效率低。如果还有input框,真实DOM残留这用户输入,往前面加一个,input框diff的时候就直接复用了,而diff跟真实DOM没有半毛钱关系。所以就出现错位的情况。
解决办法:使用数据的唯一标识,比如id,手机号等等,但是如果不对数据进行逆序添加删除的破环顺序的操作,用index是没问题的
3.v-bind 和v-model
1.v-bind
对一个属性值的动态绑定,v-bind把引号里面的东西当成JS表达式执行。
2.v-model
先来看一个需求:有时候我们需要拿到用户的输入,然后同时更新我们的数据,比如星级评分,这个时候需要v-model。v-model属于语法糖,所以先来看一下最原始的写法:
解释 通过v-on(@)监听事件,触发回调函数,回调函数中拿到用户输入赋值给data中的数据message,v-bind(:)绑定input的value,将message赋给value。
这样:我data里的数据变了,input里面也呈现了正确的内容,及时拿到了用户的输入。
<template>
<div>
<input v-bind:value="message" v-on:input="updateMessage" >
<p>Message is: {{ message }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: ''
}
},
methods: {
updateMessage(event) {
this.message = event.target.value
}
}
}
</script>
最后看一下v-model的写法:
<template>
<div>
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: ''
}
}
}
</script>
指令是干什么的
指令就是绑定DOM元素的属性(v-bind,v-model:value='msg')、值或表达式(v-if='x===y',v-show,v-html,v-model='msg')、事件(v-on:click),避免使用原生JS操作DOM元素,但是有时候我们还需要使用自定义指令,实现一些特殊的功能(造轮子)。
指令修饰符
补充: v-on用于监听DOM事件。
1. .prevent阻止默认事件
<form v-on:submit.prevent="onSubmit">
...
</form>
阻止表单提交这个默认事件,表单不会真的提交,但是会触发omSubmit事件。同样可以通过@click.prevnet='linkTo',同样,会触发linkTo事件,但是不会跳转。
2. .stop阻止默认事件
<div @click="onDivClick">
<button @click.stop="onButtonClick">Click me</button>
</div>
methods: {
onDivClick(event) {
console.log('Div clicked');
},
onButtonClick(event) {
console.log('Button clicked');
}
}
阻止事件冒泡,这样父元素的点击事件就不会触发了!
其他
1..once只能触发一次该事件
2..capture走事件捕获阶段
自定义指令
封装原生DOM操作,定义自己的指令。
配置项:directives (函数式)
<div id="root">
<h2>当前的n为<span v-text="n">{{n}}</span></h2>
<h2>放大的n为<span v-big="n"></span></h2>
</div>
<script>
new Vue({
el: "#root",
data: {
n: 99,
},
directives: {
big(element, binding) {
//element是真实DOM元素,我们可以操作
// binding是一个对象,它里面有value,就用这个,别的无关紧要
element.innerText = binding.value * 10;
},
},
});
</script>
配置项:directives (配置项式):分别在指令与元素绑定时、元素插入页面时、页面重新渲染时,可以做相应的DOM操作,钩子函数。
<input type="text" v-fbind:value="n" />
fbind: {
//1.指令和元素绑定成功时
bind(element, binding) {
console.log("bind");
element.value = binding.value;
},
//2.元素插入页面时
inserted(element, binding) {
console.log("insert");
element.focus();
},
//3.页面重新渲染时执行
update(element, binding) {
console.log("update");
element.value = binding.value;
},
},
自定义指令的坑
1.如果模板中用v-big-number多个单词的形式,下面配置的时候要给对象的key加引号('big-number')!
2 fbind 和 big函数里面的this都是window。
3 这样配置是局部的指令,只有自己这个组件可以使用,要配置全局的如下,这样所有组件都可以用了:
Vue.directive('big',函数传进来)
Vue.directive('fbind',配置对象传进来)
没有s,directive