Web前端笔记-12、Vue-插值表达式、响应式、Vue指令

概念:Vue 是一个用于构建用户界面渐进式框架。

构建用户界面:把数据渲染成页面。

渐进式:声明式渲染、组件系统、客户端路由VueRouter、大规模状态管理Vuex、构建工具webpack/vite。循序渐进,学一点用一点。

框架:一套完整的项目解决方案。

Vue快速上手

使用步骤:

  • 准备一个容器。
  • 导包。
  • 创建实例 new Vue()
  • 实例指定配置项渲染数据。el指定挂载点,data提供数据。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <!-- 1. 准备一个容器 -->
  <div id="app">
    <p>姓名:{{uname}}</p>
    <p>年龄:{{age}}</p>
    <p>朋友的姓名:{{friend.fname}}</p>
    <p>朋友的性别:{{friend.sex}}</p>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app', // 指定数据展示的元素
      data: {
        // 要展示的数据
        uname: 'good',
        age: 18,
        friend: {
          sex: '男',
          fname: 'friend'
        }
      }
    })
  </script>
</body>
</html>

插值表达式

插值表达式{{ }}是一种 Vue 的模板语法

作用:利用表达式进行插值,渲染到页面中

表达式:是可以被求值的代码,JS引擎会将其计算出一个结果

obj.name price >=100 ? 'ex':'cheap' arr[0] fn() obj.fn()

以上都是表达式。

注意:

  1. 使用的数据必须存在。
  2. 支持的是表达式,而非语句。比如 if for不能用。
  3. 不能在标签属性中使用插值当作属性值。

响应式

除了基本的模板渲染,Vue背后还做了大量工作。比如:数据的响应式处理。

响应式:数据变化了,页面(视图)会自动更新。

结论:data中所有的数据都会加到app对象上,成为其属性。 let app = new Vue()

思想:数据驱动视图。别想着改DOM了,直接改数据即可。实在改不了的再想DOM的事。

开发者调试工具

专门调试Vue项目。

极简插件:下载 开发者模式一 拖拽安装 插件详情允许访问文件

Vue指令

v-html v-show v-if v-else v-on v-bind v-for v-model

Vue 会根据不同的【指令】,针对标签实现不同的【功能】。方便渲染数据的。

指令:带有 v-前缀的特殊标签属性

v-html

相当于原生的innerHTML,把v-html=""的值展示到标签内容中。

会把标签的原有内容覆盖。

会动态解析标签。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <p>{{str}}</p>
    <p v-html="str"></p>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        str: '一个v-html的示例,可以<strong>解析html标签</strong>'
      }
    })
  </script>

</body>
</html>

v-show v-if

v-show:控制元素显示隐藏。v-show = "true or false"

原理:切换 display:none 控制显示隐藏。

场景:频繁切换显示隐藏的场景。

v-if:控制元素显示隐藏(条件渲染)。v-if = "true or false"

原理:基于条件判断,是否 创建或移除 元素节点。

场景:要么显示,要么隐藏,不频繁切换的场景。

v-if 可配合 v-else-if 和 v-else多条件判断控制显示隐藏。

v-on

进行注册事件的。注册事件 = 添加监听 + 提供处理逻辑

之前注册事件:找到元素对象,addEventListener,写回调函数。

现在用v-on。

语法:

v-on:事件名="内联语句"适合比较简单的一行逻辑

v-on:事件名 ="methods中的函数名"适合多行

简写:

v-on:替换成@

v-on:click="count++" 可以简写成 @click="count++"

内联:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <button @click="count--">-</button>
    <span v-html="count"></span>
    <button @click="count++">+</button>

    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        count: 10
      }
    })
  </script>
  </div>
</body>
</html>

使用函数:

methods:与data平级。

在Vue中,this永远表示Vue实例对象。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <button @click="fn">切换显示隐藏</button>
    <h1 v-show="flag">内容</h1>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        flag: true,
        count: 0
      },
      methods: {
        fn() {
          this.flag = !this.flag
          this.count++
          console.log(`第${this.count}次点击`)
        },
      },
    })
  </script>
</body>
</html>

传参:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .box {
      width: 210px;
      margin: 20px;
      padding: 20px;
      border: 3px solid #000;
      border-radius: 10px;
    }
    h3 {
      margin: 10px 0 20px 0;
    }
    p {
      margin: 20px;
    }
  </style>
</head>
<body>
  <div id="app">
    <div class="box">
      <h3>自动售货机</h3>
      <button @click="fn(colaPrice)">可乐{{colaPrice}}元</button>
      <button @click="fn(coffePrice)">咖啡{{coffePrice}}元</button>
      <button @click="fn(milkPrice)">牛奶{{milkPrice}}元</button>
    </div>
    <p>银行卡余额:{{money}}元</p>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        money: 100,
        colaPrice: 5,
        coffePrice: 10,
        milkPrice: 8
      },
      methods: {
        fn(n) {
          this.money -= n
        },
      },
    })
  </script>
</body>
</html>

事件对象:

事件对象就是之前addEventListener中回调函数的第一个参数e。

回顾:这个对象里有事件触发时的相关信息,包含属性和方法例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息e.target e.keye.target得到的是触发事件的元素

  • 如果在模板中(html页面中)使用事件对象,可以使用 $event(固定写法)
  • 如果在JS中使用事件对象,还是事件处理函数的形参e
  • 如果JS中,既用e,又有其他参数,秉持一对一的原则。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <h2>输入框1输入内容,并将其显示在p标签中(在模板中使用)</h2>
    <input type="text" @input="result1 = $event.target.value">
    <p v-html="result1"></p>

    <h2>输入框2输入内容,并将其显示在p标签中(在JS的函数中使用)</h2>
    <input type="text" @input="fn">
    <p v-html="result2"></p>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        result1: '',
        result2: '',
      },
      methods: {
        fn(e) {
          this.result2 = e.target.value
        }
      },
    })
  </script>
</body>
</html>

上面的代码中,在模板中,$event就是input触发时返回的事件对象。在JS的事件函数用e。

一对一原则:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <h2>输入框1输入内容,并将其显示在p标签中(在模板中使用)</h2>
    <input type="text" @input="result1 = $event.target.value">
    <p v-html="result1"></p>

    <h2>输入框2输入内容,并将其显示在p标签中(在JS的函数中使用)</h2>
    <input type="text" @input="fn(100, 200, $event)">
    <p v-html="result2"></p>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        result1: '',
        result2: '',
      },
      methods: {
        fn(a, b , e) {
          console.log(a + b)
          this.result2 = e.target.value
        }
      },
    })
  </script>
</body>
</html>

@input="fn(100, 200, $event)"fn(a, b , e) {}对应

v-bind

作用:动态设置html的标签属性。

语法:v-bind:属性名="表达式"

一旦属性名加上了v-bind,引号里就只能看作表达式,不再是字符串。

简写:把v-bind删掉,:属性名="表达式"

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <button v-show="index>0" @click="index--">上一页</button>
    <img :src="imgList[index]" alt="波仔" :title="title">
    <button v-show="index<imgList.length-1" @click="index++">下一页</button>
  </div>

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        index: 0,
        title: '波仔',
        imgList: [
          './imgs/10-01.png',
          './imgs/10-02.png',
          './imgs/11-00.gif',
          './imgs/11-01.gif'
        ]
      },
    })
  </script>
</body>
</html>

v-for

作用:基于数据循环,多次渲染整个元素。可以遍历数组、对象、数字等。

遍历数组语法:v-for="(item, index) in 数组"v-for="item in 数组"

v-for的key

在有v-for的标签里加key属性,key的值是字符串或者数字,通常用到变量或表达式,注意别忘了使用v-bind。以后所有的遍历都加上key,保证key不重复即可。

作用:key作用:给元素添加的唯一标识。便于Vue进行列表项的正确排序复用。

v-for 的默认行为会尝试 原地修改元素(就地复用)。数据驱动,根据数据v-for生成li,如果不给key,vue不知道应该删哪个li,就默认将最后一个li删掉,并根据数据重新渲染填充剩下的li。

推荐使用id,不要用index,因为index会变。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <ul>
      <li v-for="item in bookList" :key="item.id">
        <span>{{item.name}}</span>
        <span>{{item.author}}</span>
        <button @click="del(item.id)">删除</button>
      </li>
    </ul>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        bookList: [
          {id:1, name:'《红楼梦》', author: '曹雪芹'},
          {id:2, name:'《西游记》', author: '吴承恩'},
          {id:3, name:'《水浒传》', author: '施耐庵'},
          {id:4, name:'《三国演义》', author: '罗贯中'},
        ]
      },
      methods: {
        del (id) {
          this.bookList = this.bookList.filter(item=>{
            return item.id !== id
          })
        }
      },
    })
  </script>
</body>
</html>

v-model应用到input

思想:双向数据绑定。

作用: 给表单元素使用,双向数据绑定。可以快速获取或设置表单元素内容

数据变化,视图自动更新。视图变化,数据自动更新。

语法:v-model ='变量'

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    账户:<input type="text" v-model="username"> <br><br>
    密码:<input type="password" v-model="password"> <br><br>
    <button @click="login">登录</button>
    <button @click="reset">重置</button>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        username: '',
        password: '',
      },
      methods: {
        login(){
          console.log('账密:', this.username, this.password)
          
        },
        reset(){
          this.username = this.password = ''
        },
      },
    })
  </script>
</body>
</html>

id使用时间戳写法

  1. id: +new Date()
  2. id: Date.now()

指令修饰符

通过.指明一些指令后缀,不同后缀封装了不同的处理操作以简化代码。

  • v-model修饰符

v-model.trim 去除首尾空格

v-model.number 转数字(填数字才有效,比如年龄、单价需要字符串转数字)

v-model.lazy 输入框change时,才更新数据(比如手机号的输入)

  • 事件修饰符

@事件名.stop 阻止冒泡

@事件名-prevent 阻止标签的默认行为 <a> <form>

@keyup.enter 键盘回车监听 .esc .49数字1 .13enter

v-bind对样式操作的增强

分为控制类名和控制style行内样式

语法 ::class = "对象/数组"

对象:键就是类名,值是布尔值。如果值为 true,有这个类,否则没有这个类(比较方便)

<div class="box" :class="{类名1:布尔值,类名2:布尔值 }"></div>

适用场景:一个类名,来回切换。Tab切换。

数组:数组中所有的类,都会添加到盒子上,本质就是一个 class 列表。

<div class="box" :class="[类名1,类名2,类名3]"></div>

适用场景:批量添加或删除类

<!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>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    ul {
      display: flex;
      border-bottom: 2px solid #e01222;
      padding: 0 10px;
    }
    li {
      width: 100px;
      height: 50px;
      line-height: 50px;
      list-style: none;
      text-align: center;
    }
    li a {
      display: block;
      text-decoration: none;
      font-weight: bold;
      color: #333333;
    }
    li a.active {
      background-color: #e01222;
      color: #fff;
    }

  </style>
</head>
<body>

  <div id="app">
    <ul>
      <li v-for="(item, index) in list" :key="item.id" @mouseenter="activeIndex=index">
        <a :class="{active: index === activeIndex}" href="#">{{item.name}}</a>
      </li>
    </ul>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        activeIndex: 0, // 记录高亮
        list: [
          { id: 1, name: '京东秒杀' },
          { id: 2, name: '每日特价' },
          { id: 3, name: '品类秒杀' }
        ]
      }
    })
  </script>
</body>
</html>

操作行内样式:style ="样式对象"

<div class="box" :style="{CSS属性名1:CSS属性值,CSS属性名2:CSS属性值}"></div>

适用场景:某个具体属性的动态设置

<div class="box" :style="{width:'100px', 'background-color':'pink' }"></div>
<div class="progress">
  <div class="inner" :style="{width: percent+'%'}">
    <span>{{percent}}%</span>
  </div>
</div>

v-model应用到其他表单元素

v-model与表单元素的绑定关系:

input:text => value

textarea => value

input:checkbox => checked

input:radio => checked

select => value

注意:复选框只有一个和多个一组(name相同)是不一样的,只有一个的复选框v-model与value值绑定时通过布尔值控制。一组的复选框通过一个数组控制,数组中存在对应value的复选框被选中。

<input type="checkbox" name="hobby" value="吃" v-model="aihao"/>吃饭
aihao: ['吃']

全选,反选:

通过v-model与复选框绑定(绑定的是checked)。

list.every(item => item.isChecked)

computed: {
  checkedAll:{
    get(){
      // 点击小控制全选框
      return this.fruitList.every(item => item.isChecked)
    },
    set(val) {
      // 点击全选框控制小
      this.fruitList.forEach(item => {
        item.isChecked = val
      })
    }
  }  
}

// 在全选复选框处 v-model="checkedAll"
posted @ 2025-05-30 10:41  subeipo  阅读(54)  评论(0)    收藏  举报