Vue3常用指令+响应式API的详解及快速实战

559 阅读9分钟

通过上一篇# Vue3项目搭建与基础知识详解详细介绍了Vue3项目搭建的全过程,从创建项目到精简结构,再到关键文件的解读,想必大家都很清楚自己该干嘛了吧。OK,这次我们就来深入探讨一下在Vue3中常用的一些API和其中的一些常用的指令吧,真正深入了解后,我们就可以慢慢的开始创建属于自己的项目了

image.png

常用的几种指令

Vue 使用一种基因 HTML 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的 HTML,可以被符合规范的浏览器和 HTML 解析器解析。

在底层机制中,Vue 会将模板编译成高度优化的 JavaScript 代码。结合响应式系统,当应用状态变更时,Vue 能够智能地推导出需要重新渲染的组件的最少数量,并应用最少的 DOM 操作。

下图中是我们常用的一些指令,我们来对他们进行一个深入的探讨吧

image.png

  1. v-text :常用于将文本内容插入到元素中,或者说是更新元素的文本内容。这个功能不就相当于原生 JS 中的 innerText 属性或者 textContent 属性嘛,只不过在原生JS中麻烦了一点,要先获取到元素的id再去更新文本内容。不过我一般不使用v-text这种方法,而是使用最基本的数据绑定形式--利用俩个花括号,在元素中挖个坑,然后文本内容就放在里面。展示一下这两种方式的实现:

    image.png

  2. v-html:常用于将数据作为 HTML 插入到元素中,相当于用原生 JS 中的innerHTML属性来更新元素的 HTML 内容嘛

    image.png

  3. v-on: 给元素绑定事件监听器,监听 DOM 事件,并在触发时执行方法。这有个缩写的方法@,通常会使用这样种缩写。跟原生JS中利用addEventListener是一样的。这里一般是这样用的v-on:click="handler" 或 @click="handler"

    image.png

    631f90b8-5069-4d7a-b10a-d4b110f8a2b8.gif

  4. v-ifv-elsev-else-if:用于有条件地渲染元素。v-if 根据表达式的值决定是否渲染元素。v-else 提供了一个备选方案,当 v-if 的条件不满足时使用。v-else-if(Vue 3 中新增)则提供了更简洁的方式来表示多个 v-if

  5. v-show:基于表达式值的真假性,来改变元素的可见性,来判断是否要show出来。简单来说就是,根据表达式的值来显示或隐藏元素。如果表达式为真,则显示该元素;否则,隐藏它。常用于改变css样式,当满足某个条件时,改变display 的值,展示出来,是不是感觉这个指令好熟悉。没错v-ifv-show很像,但是在底层还有很大的区别的,后面来给大家对比一下。

    image.png

    6db6e7b4-6ba1-4060-95db-cca997cf4a66.gif

  6. v-for: 循环遍历数组或对象,并为每个项目渲染一个模板。指令值必须使用特殊语法 xxx in xxx 为正在迭代的元素提供一个别名,后者为数组或者对象之类的,而前者则是一个别名(代表数组或对象中的一个)在这个别名中我们还可以加入索引值(一般都是要的,原因后面给出)。注意v-for 的默认方式是尝试就地更新元素而不移动它们。要强制其重新排序元素,需要用特殊  key 来提供一个排序提示,一般来说会将索引值作为key,确保每个元素的key不同。

    image.png

  7. v-bind:动态的绑定一个或多个 属性attribute,也可以是组件的 prop,这个也有缩写 : 或者 . (当使用 .prop 修饰符),当 属性 和绑定的值同名时,值可以省略不写(常用)。所谓动态的就是,可以人为的去修改属性。比如说一张图片,我们不传入图片的地址,而是用一个参数放在里头<img v-bind:src="pic" alt="">,这样我们就可以在写js的时候去定义图片的地址。这意味着每当pic的数据发生变化时,src属性也会相应地更新,从而动态地改变显示的图像源。

    image.png

  8. v-model: 提供双向数据绑定,在Vue中主要用于表单元素,如<input><textarea><select>等,它实现了表单控件与Vue实例中数据属性之间的双向绑定。这意味着当用户在表单中输入数据时,相应的数据属性会自动更新;反之,如果数据属性通过其他方式发生改变,表单控件的值也会随之更新。

    image.png

    cd8f61fb-0f2f-4b0d-af8c-ef6f8cfb9659.gif

v-if vs v-show

它们之间存在一些关键的区别:

  1. 渲染方式:

    • v-if 是“真正的”条件渲染,这意味着当 v-if 表达式的值为假时,Vue 将不会渲染整个元素及其包含的子元素。当表达式值变为真时,Vue 将重新创建和渲染这些元素。这包括重新初始化作用域,重新绑定事件监听器,以及重新创建子组件。
    • v-show 则是通过修改 DOM 元素的 CSS display 属性来控制显示或隐藏。无论 v-show 的表达式值如何,元素都会被渲染并保留在 DOM 中,只是其可见性会通过 display: none 或 display: block(或其他可见性相关的值)来控制。
  2. 性能影响:

    • v-if 在首次渲染时性能较高,因为如果条件为假,它不会对 DOM 产生任何影响。但在条件频繁变化时,v-if 会导致频繁的 DOM 重绘和重新布局,这可能会影响性能。
    • v-show 在首次渲染时性能较低,因为它会总是创建元素并保留在 DOM 中,即使元素是隐藏的。但在条件频繁变化时,v-show 的性能较好,因为它仅仅改变 CSS 属性,不会导致 DOM 结构的变化。
  3. 使用场景:

    • v-if 更适合在条件很少改变的情况下使用,例如在页面加载时根据用户的权限来决定是否显示某个按钮。
    • v-show 则更适合在条件频繁改变的情况下使用,例如在响应用户交互时快速切换元素的可见性,如开关菜单。
  4. 其他特性:

    • v-if 可以与 v-else 和 v-else-if 结合使用,以形成更复杂的条件分支逻辑。
    • v-show 没有类似的配套指令。

所以在我们开发项目的时候,选择使用 v-if 还是 v-show 应该基于元素的显示频率和性能需求,以至于满足我们的项目要求。

常用的几种响应式API

在 Vue 中,响应式系统是其核心特性之一,它使得数据和视图能够自动同步更新。Vue 3 引入了 Composition API,进一步增强了响应式处理的能力。ref(), computed(), reactive(), 和 watch() 都是 Vue 3 中用于处理响应式数据的关键函数。下面我会逐一介绍它们的功能以及与响应式的联系,来瞅瞅吧。

注意:在使用他们之前,需要从vue模块中导入,并用解构的方式将他们导入

  1. ref() :是一个函数,用于创建一个响应式引用类型。它返回一个对象,该对象具有一个指向给定值的 .value 属性。当你访问或修改 .value 时,Vue 的响应式系统会追踪依赖关系并在需要时重新渲染组件。

  2. reactive() 函数将普通 JavaScript 对象转换为响应式对象。与 ref() 不同,reactive() 返回的对象本身是响应式的,而不是包含一个 .value 属性的对象。

  3. computed() 用于创建计算属性,这些属性是基于其他响应式数据源计算得出的。当依赖的数据变化时,计算属性会自动重新计算并缓存结果,直到依赖再次改变。

  4. watch() 函数用于观察响应式数据的变化。当被观察的数据变化时,指定的回调函数会被执行。

以上API极大地简化了状态管理和数据流的控制,是Vue3响应式系统的核心组成部分,也是我们经常会用到的。

快速实战

我们直接来实战一波,做一个购物列表,实现如下图一样的相关功能。显示一系列书籍及其详细信息,并允许调整数量或移除项目。总价格也根据所选的数量进行计算。

8b74a12e-6d6f-47c0-8a91-74626e7e78d6.gif

  • 首先我们需要在<template>中编译html将框架整出来,并且对一些要实现功能进行命名:

    <template>
      <h2>购物车</h2>
      <table>
          <thead>
              <th>序号</th>
              <th>书籍名称</th>
              <th>出版日期</th>
              <th>价格</th>
              <th>购买数量</th>
              <th>操作</th>
          </thead>
          <tbody>
              <tr v-for="(item,index) in books" :key="item.id">
                  <td >{{ index + 1 }}</td>
                  <td>{{ item.name }}</td>
                  <td>{{item.date}}</td>
                  <td>{{item.price}}</td>
                  <td>
                      <button @click="minus(index)" :disabled="item.count<=1">-</button>
                      <span class='counter'>{{ item.count }}</span>
                      <button @click="add(index)">+</button>
                  </td>
                  <td>
                      <button @click="Delete(index)">删除</button>
                  </td>
              </tr>
          </tbody>
      </table>
      <h2 >总价格:{{total}}</h2>
    </template>
    
  • 然后在<style lang="css" scoped>中写入一些css样式,将整个页面放在中间,小小的调整一些样式:

    <style lang="css" scoped>
    *{
      text-align: center;
    }
    table{
      margin: 0 auto;
      border: 1px solid #aaa;
      border-collapse: collapse;
    }
    th,td{
      padding: 8px 16px; 
      border: 1px solid #aaa;
    }
    .counter{
      margin: 0 10px;
    }
    
    </style>
    
  • 最后再在<script setup>中写入js代码,将上面的相关功能都实现

    <script setup>
    import {reactive,computed} from 'vue'
    let books=reactive([
          {
            id: 1,
            name: '《算法导论》',
            date: '2006-9',
            price: 85.00,
            count: 1
          },
          {
            id: 2,
            name: '《UNIX编程艺术》',
            date: '2006-2',
            price: 59.00,
            count: 1
          },
          {
            id: 3,
            name: '《编程珠玑》',
            date: '2008-10',
            price: 39.00,
            count: 1
          },
          {
            id: 4,
            name: '《代码大全》',
            date: '2006-3',
            price: 128.00,
            count: 1
          },
    ])
    
    const minus =(x)=>{
      books[x].count--
    
    }
    const add =(x)=>{
      books[x].count++
    }
    const total =computed(()=>{
      let sum=0
      for(let item of books){
          sum+=item.price*item.count
      }
      return sum
    })
    
    const Delete =(x)=>{
      books.splice(x,1)
    
    }
    </script>
    

让我们的Vue项目跑起来吧,你就可以得到一开始的功能图了

总结

好了,就到这里了吧,对于掌握这些基础的指令和API,我觉得还是挺重要的。不过,只要你敲代码敲多了,这些也是会熟能生巧的,所以还是要经常的去练习去思考,提升自己对Vue的理解,这样子才能将Vue发挥到极致,开发项目的速度就会越来越快了。加油吧