Vue常见指令基本用法【Vue学习笔记4】

2023-11-01  本文已影响0人  扶得一人醉如苏沐晨

一、vue的指令概念

image.png

二、vue的指令

2.1. 内容渲染指令

内容渲染指令用来辅助开发者渲染DOM元素的文本内容,常用的内容渲染指令有以下3个:

image.png

(1)v-text

用法实例(作为属性来使用):

image.png

缺点:会覆盖元素内部原有的内容

(2){{ }} 插值语法

image.png

在实际开发中用的最多,只是内容的占位符,不会覆盖原有的内容
只能写简单的js表达式,不能写if等复杂的js语句

(3)v-html

image.png

2.2. 属性绑定指令v-bind

注意:插值表达式只能用在元素的内容节点,不能用在属性节点

如果需要为元素的属性动态绑定属性值,则需要用到 v-bind 属性绑定指令

<div id="app">
  <input type="text" :placeholder="tips" />
  <hr />
  <!-- vue 规定 v-bind: 指令可以简写为 : -->
  <img :src="photo" alt="" style="width: 150px" />
</div>

<!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
<script src="./lib/vue-2.6.12.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
  // 创建 Vue 的实例对象
  const vm = new Vue({
    // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
    el: "#app",
    // data 对象就是要渲染到页面上的数据
    data: {
      tips: "请输入用户名",
      photo: "https://cn.vuejs.org/images/logo.svg",
    },
  });
</script>

属性绑定使用JavaScript表达式

属性绑定除了支持绑定简单的数据值之外,还支持Javascript 表达式的运算

<div v-bind:id="'list'+id"></div>

2.3. 事件绑定指令v-on

image.png

注意:原生 DOM 对象有onclick、oninput、onkeyup 等原生事件,替换为 vue 的事件绑定形式后分别为: v-on:click、v-on:input、v-on:keyup

<div id="app">
  <p>count 的值是:{{ count }}</p>
  <!-- 在绑定事件处理函数的时候,可以使用 () 传递参数 -->
  <!-- v-on: 指令可以被简写为 @ -->
  <button v-on:click="add(1)">+1</button>
  <button v-on:click="sub">-1</button>
</div>

<!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
<script src="./lib/vue-2.6.12.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
  // 创建 Vue 的实例对象
  const vm = new Vue({
    // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
    el: "#app",
    // data 对象就是要渲染到页面上的数据
    data: {
      count: 0,
    },
    // methods 的作用,就是定义事件的处理函数
    methods: {
      add(n) {
        // 在 methods 处理函数中,this 就是 new 出来的 vm 实例对象
        // console.log(vm === this)
        //console.log(vm)
        // vm.count += 1
        this.count += n;
      },
      sub() {
        // console.log('触发了 sub 处理函数')
        this.count -= 1;
      },
    },
  });
</script>

给谁绑定事件就给谁加v-on,后面跟事件(如click)和处理函数(如add)。如果传参就在定义处理函数小括号里加形参,绑定事件小括号里加实参。

通过this. 调用数据源中的变量与方法。

v-on:简写为@

如果不传实参,则默认传一个事件对象给处理函数。

<div id="app">
  <p>count 的值是:{{ count }}</p>
  <!-- 如果 count 是偶数,则 按钮背景变成红色,否则,取消背景颜色 -->
  <button @click="add">+N</button>
</div>

<!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
<script src="./lib/vue-2.6.12.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
  // 创建 Vue 的实例对象
  const vm = new Vue({
    // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
    el: "#app",
    // data 对象就是要渲染到页面上的数据
    data: {
      count: 0,
    },
    methods: {
      add(e, n) {
        this.count += n;
        console.log(e); //打印出来的是一个MouseEvent对象

        // 判断 this.count 的值是否为偶数
        if (this.count % 2 === 0) {
          // 偶数
          e.target.style.backgroundColor = "red";
        } else {
          // 奇数
          e.target.style.backgroundColor = "";
        }
      },
    },
  });
</script>

如果传了实参,则该事件对象会被覆盖,也就不存在target属性。

vue 提供了内置变量,名字叫做 $event,它就是原生 DOM 的事件对象 e,可以用于传实参。

<button @click="add($event, 1)">+N</button>

这样就可以获得事件对象的target了。实际开发中用的较少。

2.4. 事件修饰符

原生js中常用事件对象的preventDefault()来阻止默认行为,stopPropagation()来阻止事件冒泡

image.png

Vue的简写:在绑定事件的同时加给事件加事件修饰符。语法格式如下:

<div id="app">
  <a href="http://www.baidu.com" @click.prevent="show">跳转到百度首页</a>
  <hr />
  <div
    style="
      height: 150px;
      background-color: orange;
      padding-left: 100px;
      line-height: 150px;
    "
    @click="divHandler"
  >
    <button @click.stop="btnHandler">按钮</button>
  </div>
</div>

2.5. 按键修饰符

image.png
clearInput(e) {
  console.log("触发了 clearInput 方法");
  e.target.value = "";
}
commitAjax() {
  console.log("触发了 commitAjax 方法");
}

2.6. 双向绑定指令v-model

image.png

在提交表单或采集数据时,不需要再操作DOM,只要修改了表单文本框,就会修改数据源,直接用this. 就能获得最新的数据源。

v-bind:value="username" 与 v-model="username"的区别:

  • 前者是单向绑定,数据源改变驱动页面数据改变,但页面上的改动不会同步到数据源;
  • 后者是双向绑定。

只有表单元素使用v-model才有意义。如

  • (1)input: type="radio"; type="checkbox"; type="xxx
  • (2)texytarea
  • (3)select

vue内部会判断v-model绑定的元素类型,有选择地控制元素的属性(例如input type="checkbox"绑定check属性,input type="text"绑定value属性)

<div id="app">
  <select v-model="city">
    <option value="">请选择城市</option>
    <option value="1">北京</option>
    <option value="2">上海</option>
    <option value="3">广州</option>
  </select>
</div>
<script src="./lib/vue-2.6.12.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
  // 创建 Vue 的实例对象
  const vm = new Vue({
    // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
    el: "#app",
    // data 对象就是要渲染到页面上的数据
    data: {
      username: "zhangsan",
      city: "2",
    },
  });
</script>

2.7. v-model指令的修饰符

image.png

(1).number

用户输入表单的是字符串,不能进行数值的计算(只能字符串拼接),可以用.number转换成数值类型再计算

(2).trim

在例如输入用户名的场景时我们希望去掉用户可能因为误操作在首尾输入的空格,可以使用.trim,它不会处理输入内容中间的空格。

(3).lazy

因为使用v-model时表单输入框和数据源中的数据是实时更新的,在改变输入框内的内容过程中没有必要更新数据源中的数据,会引起性能上的问题,所以可以使用.lazy,在表单输入内容修改完成("change"时,如失去焦点)再同步数据源的数据。

<div id="app">
  <input type="text" v-model.number="n1" /> +
  <input type="text" v-model.number="n2" /> = <span>{{ n1 + n2 }}</span>
  <hr />
  <input type="text" v-model.trim="username" />
  <button @click="showName">获取用户名</button>
  <hr />
  <input type="text" v-model.lazy="username" />
</div>

<!-- 1. 导入 Vue 的库文件,在 window 全局就有了 Vue 这个构造函数 -->
<script src="./lib/vue-2.6.12.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
  // 创建 Vue 的实例对象
  const vm = new Vue({
    // el 属性是固定的写法,表示当前 vm 实例要控制页面上的哪个区域,接收的值是一个选择器
    el: "#app",
    // data 对象就是要渲染到页面上的数据
    data: {
      username: "zhangsan",
      n1: 1,
      n2: 2,
    },
    methods: {
      showName() {
        console.log(`用户名是:"${this.username}"`);
        //``是模板字符串,可以括住多行字符串
        //${}是占位符,将数量较多的变量插入字符串的写法,简化 "xxx"+变量+"xxx" 的写法
      },
    },
  });
</script>

2.8. 条件渲染指令

2.8.1. v-if和v-show

image.png image.png

2.8.2. v-else

image.png

2.8.3. v-else-if

image.png

2.9. 列表渲染指令

image.png

v-for中的索引

image.png

需要索引再加()

使用v-for的元素本身也可以访问数组的item

<tr v-for="(item, index) in list" :key="item.id">
  <td>{{ index }}</td>
  <td>{{ item.id }}</td>
  <td>{{ item.name }}</td>
</tr>

官方建议:只要用到了 v-for 指令,那么一定要绑定一个:key 属性,而且,尽量把 id 作为 key 的值,官方对 key 的值类型,是有要求的:字符串或数字类型,key 的值是千万不能重复的,否则会终端报错:Duplicate keys detected

key值的注意事项:

image.png

index的非唯一性是指:索引与该项具体数据并没有强烈的绑定关系,它只会绑定第几项数据。

小案例:品牌列表

案例效果截图:

image.png

源码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>品牌列表案例</title>
    <link rel="stylesheet" href="./lib/bootstrap.css" />
    <link rel="stylesheet" href="./css/brandlist.css" />
  </head>

  <body>
    <div id="app">
      <!-- 卡片区域 -->
      <div class="card">
        <div class="card-header">添加品牌</div>
        <div class="card-body">
          <!-- 添加品牌的表单区域 -->
          <!-- 取消form表单的默认submit会刷新页面的事件 -->
          <form @submit.prevent="add">
            <div class="form-row align-items-center">
              <div class="col-auto">
                <div class="input-group mb-2">
                  <div class="input-group-prepend">
                    <div class="input-group-text">品牌名称</div>
                  </div>
                  <!-- 双向绑定用户输入的品牌名称brand,并修饰符删去首位空格 -->
                  <input
                    type="text"
                    class="form-control"
                    placeholder="请输入品牌名称"
                    v-model.trim="brand"
                  />
                </div>
              </div>
              <div class="col-auto">
                <button type="submit" class="btn btn-primary mb-2">添加</button>
              </div>
            </div>
          </form>
        </div>
      </div>

      <!-- 表格区域 -->
      <table class="table table-bordered table-hover table-striped">
        <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">品牌名称</th>
            <th scope="col">状态</th>
            <th scope="col">创建时间</th>
            <th scope="col">操作</th>
          </tr>
        </thead>
        <tbody>
          <!-- 循环列表用v-for -->
          <tr v-for="item in list" :key="item.id">
            <td>{{ item.id }}</td>
            <td>{{ item.name }}</td>
            <td>
              <div class="custom-control custom-switch">
                <!-- 双向绑定启用状态checkbox -->
                <input
                  type="checkbox"
                  class="custom-control-input"
                  id="customSwitch1"
                  v-model="item.status"
                  :id="'cb'+item.id"
                />
                <!-- v-if显示隐藏 -->
                <!-- 动态绑定label中的for属性,指定表单对象 -->
                <label
                  class="custom-control-label"
                  :for="'cb'+item.id"
                  v-if="item.status"
                  >已启用</label
                >
                <label class="custom-control-label" :for="'cb'+item.id" v-else
                  >已禁用</label
                >
              </div>
            </td>
            <td>{{ item.time }}</td>
            <td>
              <a href="javascript:;" @click="remove(item.id)">删除</a>
            </td>
          </tr>
        </tbody>
      </table>
    </div>

    <script src="./lib/vue-2.6.12.js"></script>

    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          // 用户输入的品牌名称
          brand: "",
          // nextId是下一个可用的id
          nextId: 4,
          // 品牌列表数据
          list: [
            { id: 1, name: "宝马", status: true, time: new Date() },
            { id: 2, name: "奔驰", status: false, time: new Date() },
            { id: 3, name: "奥迪", status: true, time: new Date() },
          ],
        },
        methods: {
          /*
           * 点击链接链接,删除对应的品牌信息
           */
          remove(id) {
            // 写一步测一步,减少bug的出现
            // console.log(id);
            this.list = this.list.filter((item) => item.id !== id);
          },
          /*
           *阻止表单的默认提交方法后触发add方法
           */
          add() {
            // 如果填写的brand值为空字符串,应该return出去
            if (this.brand === "") return alert("必须填写品牌名称");
            // 没有被return出去,则执行添加
            // console.log(this.brand);
            // 1、先把要添加的对象整理出来
            const obj = {
              id: this.nextId,
              name: this.brand,
              status: true,
              time: new Date(),
            };
            // 2、往this.list数组中push步骤1得到的对象
            this.list.push(obj);
            // 3、清空this.brand,让this.nextId自增加1
            this.brand = "";
            this.nextId++;
          },
        },
      });
    </script>
  </body>
</html>

案例中的小回顾:

<label>标签中的for属性:指向表单元素id,规定label与哪个表单元素绑定(如:用户点checkbox和checkbox后面的label都会引起checkbox状态改变,提高了用户体验)

可以给案例中的checkbox的label动态绑定一个for(v-bind)

上一篇下一篇

猜你喜欢

热点阅读