Vue2指令

147 阅读5分钟

指令的概念

什么是Vue指令?

  • 指令(Directives)vue 提供的模板语法
  • 用于渲染页面的基本结构

指令按使用途径分类

  1. 内容渲染指令
  2. 属性绑定指令
  3. 事件绑定指令
  4. 双向绑定指令
  5. 条件渲染指令
  6. 列表渲染指令
  7. 插槽指令
  8. 自定义指令

内容渲染指令

  • 用于渲染DOM元素的文本内容,或者DOM元素的渲染状态

v-text

  • 更新元素的 textContent,用于将数据显示在界面中
  • 注:覆盖元素内部原有内容
 <div v-text="name">名字</div>
 export default {
   data(){
     return{ name:'ljh' }
   },
 }

1665544874401.png

v-html

  • 更新元素的 innerHTML
 <div v-html="name"></div>
 export default {
   data(){
     return{ name:'<h1>ljh</h1>' }
   },
 }

1665547915970.png

v-pre

  • 跳过所在节点的编译过程
  • 用途: 跳过没有指令语法、插值语法的节点,加快编译
 <div v-pre>名字:{{name}}</div>
 export default {
   data(){
     return{ name:'ljh' }
   },
 }

1665548208948.png

v-once

  • 所在节点初次渲染后视为静态内容
  • 用途: 数据改变不引起所在节点更新,用于优化性能
   <h2 v-once> n的初始值是:{{num}}</h2>
   <h2>当前的n值是:{{num}}</h2>
   <button @click = "num++">num+1</button>
 export default {
   data(){
     return{ num:0 }
   },
 }

1665548710615.png

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:'动态绑定的属性' }
   }
 };

1665556740648.png

  • 双引号内的是 JavaScript 表达式
  • v-bind 可简写为 “:”
 <input type="text" :placeholder="msg"/>

事件绑定指令

  • 用于监听DOM事件,如点击、鼠标移出等

v-on

 <button v-on:click="showTip">点击</button>
 methods:{
   showTip(){
     alert('hello')
   }
 }

1665557248590.png

  • 监听的事件回调,可以传递参数
 <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)
   }
 }

1665557735575.png

双向绑定指令

  • 数据双向绑定
  • 用途: 常用于表单输入

v-model

 <input type="text" v-model="username">
 <div>{{ username }}</div>
 export default {
   data(){
     return { username:'ljh' }
   },
 };

1665558014008.png

  • 原理: 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' }
   },
 };

1665562869597.png

  • 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>

1665563112306.png

v-show

  • DOM 设置 cssstyle 属性
  • 原理: 动态为元素添加或移除 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' }
   },
 };

1665564157180.png

列表渲染指令

  • 基于一个数组来循环渲染一个列表结构

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:'王五' }
     ]
    }
 },

1665564549473.png

  • v-for第二个参数当前项索引
  • 语法: (item, index) in arr
  • 参数皆是形参可重命名,如(user, i) in list
 <h2 v-for="(user,i) in list">{{ user.name + i }}</h2>

1665564910290.png

  • key属性: 列表循环需加:key="唯一标识"
 <h2 v-for="(user,i) in list" :key="user.id">{{user.name+i}}</h2>

为什么需要key属性?

  • 添加Key可以标识组件的唯一性,更好区别各个DOM节点
  • 作用: 主要用来做 dom diff 算法,为了高效的更新虚拟DOM

key属性原理

当某一层有很多相同的节点时,我们希望插入一个新的节点

1665565397074.png

使用 key 属性给每个节点做唯一标识diff 算法就能正确识别此节点,找到正确位置插入新节点

  1. 索引作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)
   }
 }
  • 当添加一个人员时,用索引作为唯一标识,会出现列表紊乱的情况

1665567840555.png

  • 算法流程

1665568228621.png


  1. 唯一标识作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>
  • 点击添加人员时,列表正常展示

1665568064988.png

  • 算法流程

1665568244428.png

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>

1666424658486.png

  • 简写: #
 <Count>
   <template #show>
     <h1>hello</h1>
   </template>
 </Count>