指令的概念
什么是Vue指令?
- 指令(Directives) 是
vue提供的模板语法 - 用于渲染页面的基本结构。
指令按使用途径分类
- 内容渲染指令
- 属性绑定指令
- 事件绑定指令
- 双向绑定指令
- 条件渲染指令
- 列表渲染指令
- 插槽指令
- 自定义指令
内容渲染指令
- 用于渲染DOM元素的文本内容,或者DOM元素的渲染状态
v-text
- 更新元素的
textContent,用于将数据显示在界面中 - 注: 会覆盖元素内部原有内容
<div v-text="name">名字</div>
export default {
data(){
return{ name:'ljh' }
},
}
v-html
- 更新元素的
innerHTML
<div v-html="name"></div>
export default {
data(){
return{ name:'<h1>ljh</h1>' }
},
}
v-pre
- 跳过所在节点的编译过程
- 用途: 跳过没有指令语法、插值语法的节点,加快编译
<div v-pre>名字:{{name}}</div>
export default {
data(){
return{ name:'ljh' }
},
}
v-once
- 所在节点初次渲染后,视为静态内容
- 用途: 数据改变不引起所在节点更新,用于优化性能
<h2 v-once> n的初始值是:{{num}}</h2>
<h2>当前的n值是:{{num}}</h2>
<button @click = "num++">num+1</button>
export default {
data(){
return{ num:0 }
},
}
v-cloak
- 保持在元素上直到关联实例结束编译
- 用途: 解决浏览器在加载页面时因存在事件差而产生闪动问题
- 原理: 先隐藏文件挂载位置,处理渲染好再显示最终结果
- 使用: 需要与
css规则一起使用 - 场景:
data中的数据可能是从服务器获取的,网络不好的情况下,页面可能会显示未编译的Mustache标签,那么页面在渲染时就会先显示{{message}},然后变为hello
<div v-cloak>{{message}}</div>
export default {
data(){
return { message:'hello' }
}
};
- 配合CSS将其隐藏,直至解析完成
[v-cloak]{
display: none;
}
属性绑定指令
- 为元素的属性动态绑定属性值
v-bind
<input type="text" v-bind:placeholder="msg"/>
export default {
name:'App',
data(){
return { msg:'动态绑定的属性' }
}
};
- 双引号内的是
JavaScript表达式 v-bind可简写为“:”
<input type="text" :placeholder="msg"/>
事件绑定指令
- 用于监听DOM事件,如点击、鼠标移出等
v-on
<button v-on:click="showTip">点击</button>
methods:{
showTip(){
alert('hello')
}
}
- 监听的事件回调,可以传递参数
<button v-on:click="showTip('hello')">点击</button>
methods:{
showTip(msg){
alert(msg)
}
}
v-on可简写为@
<button @click="showTip('hello')">点击</button>
- 内置变量
$event,即原生DOM的事件对象
<button @click="showTip">点击</button>
methods:{
showTip(e){
console.log(e)
}
}
双向绑定指令
- 数据双向绑定
- 用途: 常用于表单输入
v-model
<input type="text" v-model="username">
<div>{{ username }}</div>
export default {
data(){
return { username:'ljh' }
},
};
-
原理:
v-model只是语法糖,实际上是v-bind:value和@input(输入框)的结合- 通过
:value绑定username变量,输入内容时触发input事件 - 通过事件对象参数
event.target.value获取输入的内容,再赋值给username
- 通过
<input type="text" :value="username" @input="username = $event.target.value">
条件渲染指令
- 按需控制
DOM的显示与隐藏
v-if
- 动态添加或删除
DOM元素,实现元素的显示和隐藏 - 用途: 进入页面时,该元素默认不展示,并且后期也可能不被展示(隐藏和显示切换少)
<div v-if="username === 'jh'">{{username}}</div>
<h1>hello</h1>
export default {
name:'App',
data(){
return { username:'ljh' }
},
};
-
v-if配套指令v-else-if:必须配合v-if指令一起使用v-else:必须跟v-if成对使用
<h2 v-if="username === 'jh'">jh</h2>
<h2 v-else-if="username === 'lh'">lh</h2>
<h2 v-else>{{username}}</h2>
v-show
- 为
DOM设置css的style属性 - 原理: 动态为元素添加或移除
display:none样式,实现元素的显示和隐藏 - 用途: 元素需频繁切换显示状态,
v-show性能更好
<h2 v-show="username === 'jh'">jh</h2>
<h2 v-show="username === 'lh'">lh</h2>
<h2 v-show="username === 'ljh'">{{username}}</h2>
export default {
data(){
return { username:'ljh' }
},
};
列表渲染指令
- 基于一个数组来循环渲染一个列表结构
v-for
-
需使用
item in arr形式的特殊语法arr是待循环的数组item是数组的每一项
<h2 v-for="item in list">{{item.name}}</h2>
data(){
return {
list:[
{ id:1,name:'张三' },
{ id:2,name:'李四' },
{ id:3,name:'王五' }
]
}
},
v-for的第二个参数:当前项索引、- 语法:
(item, index) in arr - 参数皆是形参,可重命名,如
(user, i) in list
<h2 v-for="(user,i) in list">{{ user.name + i }}</h2>
key属性: 列表循环需加:key="唯一标识"
<h2 v-for="(user,i) in list" :key="user.id">{{user.name+i}}</h2>
为什么需要key属性?
- 添加Key可以标识组件的唯一性,更好区别各个DOM节点
- 作用: 主要用来做
dom diff算法,为了高效的更新虚拟DOM
key属性原理
当某一层有很多相同的节点时,我们希望插入一个新的节点
使用 key 属性给每个节点做唯一标识,diff 算法就能正确识别此节点,找到正确位置插入新节点
- 索引作key
<button @click="add">添加一个人员</button>
<ul>
<li v-for="(item,index) in person" :key="index">
{{item.name}}-{{item.age}}
<input type="text"/>
</li>
</ul>
data(){
return {
person:[
{id:1,name:'张三',age:18},
{id:2,name:'李四',age:19},
{id:3,name:'王五',age:20},
]
}
},
methods:{
add(){
const p = {id:4,name:'赵六',age:21}
this.person.unshift(p)
}
}
- 当添加一个人员时,用索引作为唯一标识,会出现列表紊乱的情况
- 算法流程
- 唯一标识作key
<button @click="add">添加一个人员</button>
<ul>
<li v-for="(item,index) in person" :key="item.id">
{{item.name}}-{{item.age}}
<input type="text"/>
</li>
</ul>
- 点击添加人员时,列表正常展示
- 算法流程
key属性对比规则
①旧虚拟DOM中找到与新虚拟DOM相同的 key:
- 若虚拟
DOM中内容没变,直接使用之前的真实DOM - 若虚拟
DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
②旧虚拟DOM中未找到与新虚拟DOM相同的 key:
- 创建新的真实DOM,随后渲染到到页面。
用索引作为key可能会引发的问题
①若对数据进行逆序添加、逆序删除等破坏顺序操作
- 会产生没有必要的真实
DOM更新 --> 界面效果没问题,但效率低。
②结构中还包含输入类的 DOM
- 会产生错误
DOM更新 --> 界面有问题。
开发中如何选择key?
- 最好使用数据的唯一标识作为
key,比如id、手机号、身份证号、学号等 - 如果没有逆序添加、逆序删除等破坏顺序操作,仅用于渲染展示,可用索引作为
key
插槽指令
- 把一堆内容填充到指定名称的插槽中,又不破坏原本结构
v-slot
-
提供具名插槽或需要接收
prop的插槽 -
限用于
<template>标签- 组件 (对于一个单独的带
prop的默认插槽)
-
参数:插槽名 (可选,默认值是
default) -
完整写法:
v-slot:
<!-- Count.vue -->
<div>
<slot name="show"></slot>
</div>
<!-- App.vue -->
<Count>
<template v-slot:show>
<h1>hello</h1>
</template>
</Count>
- 简写:
#
<Count>
<template #show>
<h1>hello</h1>
</template>
</Count>