Vue基础入门 - Vue的快速创建、Vue的开发者工具安装及Vue的常用指令(v-model,v-bind,computed计算属性,watch侦听器)

发布时间:2024年01月19日

Vue

1 什么是Vue

Vue (读音 /vju?/,类似于 view) 是一套 **构建用户界面 **的 渐进式框架

Vue2官网:https://v2.cn.vuejs.org/

  • 什么是构建用户界面?

    基于数据渲染出用户可以看到的界面

  • 什么是渐进式?

    所谓渐进式就是循序渐进,不一定非得把Vue中的所有API都学完才能开发Vue,可以学一点开发一点

Vue的两种开发方式:

  1. Vue核心包开发

    场景:局部模块改造

  2. Vue核心包&Vue插件&工程化

    场景:整站开发

2 创建Vue实例

2.1 快速创建

核心步骤(4步):

  1. 准备容器
  2. 引包(官网) — 开发版本/生产版本
  3. 创建Vue实例 new Vue()
  4. 指定配置项,渲染数据
    1. el:指定挂载点
    2. data提供数据

image-20240117144257121

2.2 插值表达式 {{}}

我们可以用插值表达式渲染出Vue提供的数据

image-20240117144422777

常见错误使用:

1.在插值表达式中使用的数据 必须在data中进行了提供
<p>{{hobby}}</p>  //如果在data中不存在 则会报错

2.支持的是表达式,而非语句,比如:if   for ...
<p>{{if}}</p>

3.不能在标签属性中使用 {{  }} 插值 (插值表达式只能标签中间使用)
<p title="{{username}}">我是P标签</p>

2.3 响应式特性

简单理解就是数据变,视图对应变。

2.3.1 访问与修改

data中的数据, 最终会被添加到实例上

① 访问数据: “实例.属性名”

② 修改数据: “实例.属性名”= “值”

image-20240117144622961

3 Vue开发者工具安装

  1. 通过谷歌应用商店安装(国外网站)
  2. 极简插件下载(推荐) https://chrome.zzzmh.cn/index
image-20240117145417754 image-20240117145437182

安装失败,采用第一种方法。

image-20240117150029614 image-20240117150054988 image-20240117150129358

两个问题:

  • Vue的图标是灰色的

    该页面不是由Vue写的,换一个由Vue写的网页,如bilibili

  • Vue的图标不是灰色的,但显示

    Vue.js is detected on this page.
    Devtools inspection is not available because it's in production mode or explicitly disabled by the author.
    

按下F12,打开开发者模式,就可以看到Vue的调试面板

image-20240117155156658

4 Vue中的常用指令

概念:指令(Directives)是 Vue 提供的带有 v- 前缀 的 特殊 标签属性

目的:提高程序员操作 DOM 的效率。

vue 中的指令按照不同的用途可以分为如下 6 大类:

  • 内容渲染指令(v-html、v-text)
  • 条件渲染指令(v-show、v-if、v-else、v-else-if)
  • 事件绑定指令(v-on)
  • 属性绑定指令 (v-bind)
  • 双向绑定指令(v-model)
  • 列表渲染指令(v-for)

指令是 vue 开发中最基础、最常用、最简单的知识点。

4.1 内容渲染指令

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

  • v-text(类似innerText)

    使用语法:<p v-text="uname">hello</p>,意思是将 uame 值渲染到 p 标签中

    类似 innerText,使用该语法,会覆盖 p 标签原有内容

  • v-html(类似 innerHTML)

    使用语法:<p v-html="intro">hello</p>,意思是将 intro 值渲染到 p 标签中

    类似 innerHTML,使用该语法,会覆盖 p 标签原有内容

    类似 innerHTML,使用该语法,能够将HTML标签的样式呈现出来。

  • 示例(语法上能看出两者区别)

    <div id="app">
    <h2>个人信息</h2>
    // 既然指令是vue提供的特殊的html属性,所以咱们写的时候就当成属性来用即可
    <p v-text="uname">姓名:</p> 
    <p v-html="intro">简介:</p>
    </div> 
    
    <script>
        const app = new Vue({
            el:'#app',
            data:{
                uname:'张三',
                intro:'<h2>这是一个<strong>非常优秀</strong>的boy<h2>'
            }
        })
    </script>
    

4.2 条件渲染指令

条件判断指令,**用来辅助开发者按需控制 DOM 的显示与隐藏。**条件渲染指令有如下两个,分别是:

  • v-show

    作用: 控制元素显示隐藏

    语法: v-show = “表达式” 表达式值为 true 显示, false 隐藏

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

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

  • v-if

    作用: 控制元素显示隐藏(条件渲染)

    语法: v-if= “表达式” 表达式值 true显示, false 隐藏

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

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

  • 示例:

    <div id="app">
    <div v-show="flag" class="box">我是v-show控制的盒子</div>
    <div v-if="flag" class="box">我是v-if控制的盒子</div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script>
    const app = new Vue({
      el: '#app',
      data: {
        flag: false
      }
    })
    </script>
    

    演示效果:

    如果为true

    image-20240117210448144

    如果为false

    image-20240117210544258

  • v-else 和 v-else-if

    作用:辅助v-if进行判断渲染

    语法:v-else v-else-if=“表达式”

    需要紧接着v-if使用

  • 示例:

    <div id="app">
    <p v-if="gender === 1">性别:♂ 男</p>
    <p v-else>性别:♀ 女</p>
    <hr>
    <p v-if="score >= 90">成绩评定A:奖励电脑一台</p>
    <p v-else-if="score >= 70">成绩评定B:奖励周末郊游</p>
    <p v-else-if="score >= 60">成绩评定C:奖励零食礼包</p>
    <p v-else>成绩评定D:惩罚一周不能玩手机</p>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script>
    
    const app = new Vue({
      el: '#app',
      data: {
        gender: 2,
        score: 95
      }
    })
    </script>
    

    演示效果:

    image-20240117210604526

4.3 事件绑定指令

使用Vue时,如需为DOM注册事件,及其的简单,语法如下:

  • <button v-on:事件名="内联语句">按钮</button>
  • <button v-on:事件名="处理函数">按钮</button>
  • <button v-on:事件名="处理函数(实参)">按钮</button>
  • v-on: 简写为 @

内联语句示例:

<body>
  <div id="app">
    <button @click="count--">-</button>
    <span>{{ count }}</span>
    <button v-on:click="count++">+</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        count: 100
      }
    })
  </script>
</body>

演示效果

test3

事件处理函数示例:

  • 事件处理函数应该写到一个跟data同级的配置项(methods)中(不是method!!!)
  • methods中的函数内部的this都指向Vue对象实例
<body>
  <div id="app">
    <button @click="fn">切换显示隐藏</button>
    <h1 v-show="isShow">Vue的事件处理函数显示与隐藏</h1>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app4 = new Vue({
      el: '#app',
      data: {
        isShow: true
      },
      methods: {
        fn () {
          // 让提供的所有methods中的函数,this都指向当前实例
          // console.log('执行了fn', app.isShow)
          // console.log(app3 === this)
          this.isShow = !this.isShow
        }
      }
    })
  </script>
</body>

演示效果:

test4

给事件处理函数传参示例:

  • 如果不传递任何参数,则方法无需加小括号,同时methods方法中可以直接使用 e 当做事件对象;
  • 如果传递了参数,则实参 $event 表示事件对象,固定用法。
<body>

  <div id="app">
    <div class="box">
      <h3>自动售货机</h3>
      <button @click="buy(5)">可乐5元</button>
      <button @click="buy(10)">咖啡10元</button>
      <button @click="buy(8)">牛奶8元</button>
    </div>
    <p>银行卡余额:{{ money }}元</p>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        money: 100
      },
      methods: {
        buy (price) {
          this.money -= price
        }
      }
    })
  </script>
</body>

演示效果:

test5

4.4 属性绑定指令

作用:动态设置html的标签属性 比如:src、url、title

语法**v-bind:**属性名=“表达式”

**v-bind:**可以简写成 :

比如,有一个图片,它的 src 属性值,是一个图片地址。这个地址在数据 data 中存储。

则可以这样设置属性值:

  • <img v-bind:src="url" />
  • <img :src="url" /> (v-bind可以省略)

属性绑定指令示例:

<body>
  <div id="app">
    <!-- v-bind:src   =>   :src -->
    <img v-bind:src="imgUrl" v-bind:title="msg" alt="">
    <img :src="imgUrl" :title="msg" alt="">
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        imgUrl: './imgs/11-00.gif',
        msg: 'hello 波仔'
      }
    })
  </script>
</body>

演示结果:

image-20240117212052740

4.5 案例-上下页图片翻页

难点:

  • 上一页、下一页按钮的显示和隐藏条件是什么?
  • 如何采用数组实现图片的转化?即下标要如何变化?
<body>
  <div id="app">
    <button v-show="index > 0" @click="index--">上一页</button>
    <div>
      <img :src="list[index]" alt="">
    </div>
    <button v-show="index < list.length - 1" @click="index++">下一页</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        index: 0,
        list: [
          './imgs/11-00.gif',
          './imgs/11-01.gif',
          './imgs/11-02.gif',
          './imgs/11-03.gif',
          './imgs/11-04.png',
          './imgs/11-05.png',
        ]
      }
    })
  </script>
</body>

演示效果:

test6

4.6 列表渲染指令

Vue 提供了 v-for 列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构

v-for 指令需要使用 (item, index) in arr 形式的特殊语法,其中:

  • item 是数组中的每一项
  • index 是每一项的索引,不需要可以省略
  • arr 是被遍历的数组

此语法也可以遍历**对象和数字**

//遍历对象
<div v-for="(value, key, index) in object">{{value}}</div>
value:对象中的值
key:对象中的键
index:遍历索引从0开始

//遍历数字
<p v-for="item in 10">{{item}}</p>
item从1 开始

列表渲染指令示例:

<body>
  <div id="app">
    <h3>水果店</h3>
    <ul>
      <li v-for="(item, index) in list">
        {{ item }} - {{ index }}
      </li>
    </ul>

    <ul>
      <li v-for="item in list">
        {{ item }}
      </li>
    </ul>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        list: ['西瓜', '苹果', '鸭梨', '榴莲']
      }
    })
  </script>
</body>

演示效果:

image-20240117213008640

4.7 案例-能删除的书架

难点:

  • 运用v-for进行循环显示
  • 如何删除(需要用到filter数组的过滤器,得到一个新数组)

filter:根据条件,保留满足条件的对应项,得到一个新数组。

<body>
  <div id="app">
    <h3>书架</h3>
    <ul>
      <li v-for="(item, index) in booksList" :key="item.id">
        <span>{{ item.name }}</span>
        <span>{{ item.author }}</span>
        <!-- 注册点击事件 →  通过 id 进行删除数组中的 对应项 -->
        <button @click="del(item.id)">删除</button>
      </li>
    </ul>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        booksList: [
          { id: 1, name: '《红楼梦》', author: '曹雪芹' },
          { id: 2, name: '《西游记》', author: '吴承恩' },
          { id: 3, name: '《水浒传》', author: '施耐庵' },
          { id: 4, name: '《三国演义》', author: '罗贯中' }
        ]
      },
      methods: {
        del (id) {
          // console.log('删除', id)
          // 通过 id 进行删除数组中的 对应项 → filter(不会改变原数组)
          // filter: 根据条件,保留满足条件的对应项,得到一个新数组。
          // console.log(this.booksList.filter(item => item.id !== id))
          this.booksList = this.booksList.filter(item => item.id != id)
        }
      }
    })
  </script>
</body>

演示效果:

test8

4.8 v-for中的key

对于用v-for渲染的列表数据来说,数据量可能一般很庞大,而且我们经常还要对这个数据进行一些增删改操作。那么整个列表都要重新进行渲染一遍,那样就会很费事。而key的出现就尽可能的回避这个问题,提高效率

v-for默认使用就地复用的策略,列表数据修改的时候,**他会根据key值去判断某一个值是否修改,如果修改则重新渲染该项,否则复用之前的元素。**在v-for中我们的key一般为id,也就是唯一的值,但是一般不要使用index作为key。

<body>
  <div id="app">
    <h3>小黑的书架</h3>
    <ul>
      <li v-for="(item, index) in booksList" :key="item.id">
        <span>{{ item.name }}</span>
        <span>{{ item.author }}</span>
        <span> key </span>
        <button @click="del(item.id)">删除</button>
      </li>
    </ul>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        booksList: [
          { id: 1, name: '《红楼梦》', author: '曹雪芹' },
          { id: 2, name: '《西游记》', author: '吴承恩' },
          { id: 3, name: '《水浒传》', author: '施耐庵' },
          { id: 4, name: '《三国演义》', author: '罗贯中' }
        ]
      },
      methods: {
        del (id) {
          this.booksList = this.booksList.filter(item => item.id !== id)
        }
      }
    })
  </script>
</body>

肉眼不能看出区别,但提高了效率

4.9 双向绑定指令

所谓双向绑定就是:

  1. 数据改变后,呈现的页面结果会更新
  2. 页面结果更新后,数据也会随之而变

作用:表单元素(input、radio、select)使用,双向绑定数据,可以快速 获取设置 表单元素内容

**语法:**v-model=“变量”

双向绑定指令案例:

**需求:**使用双向绑定实现以下需求

  1. 点击登录按钮获取表单中的内容
  2. 点击重置按钮清空表单中的内容
<body>

  <div id="app">
    <!-- 
      v-model 可以让数据和视图,形成双向数据绑定
      (1) 数据变化,视图自动更新
      (2) 视图变化,数据自动更新
      可以快速[获取]或[设置]表单元素的内容
     -->
    账户:<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>
    const app = new Vue({
      el: '#app',
      data: {
        username: '',
        password: ''
      },
      methods: {
        login () {
          console.log(this.username, this.password)
        },
        reset () {
          this.username = ''
          this.password = ''
        }
      }
    })
  </script>
</body>

运行效果:

test9

4.10 指令修饰符

所谓指令修饰符就是通过“.”指明一些指令后缀 不同的后缀封装了不同的处理操作

目的:简化代码

4.10.1 按键修饰符

@keyup.enter:当点击enter键的时候才触发

按键修饰符示例:

<body>
  <div id="app">
    <h3>@keyup.enter  →  监听键盘回车事件</h3>
    <input @keyup.enter="fn" v-model="username" type="text">
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        username: ''
      },
      methods: {
        fn (e) {
          // if (e.key === 'Enter') {
          //   console.log('键盘回车的时候触发', this.username)
          // }

          console.log('键盘回车的时候触发', this.username)
        }
      }
    })
  </script>
</body>

运行效果:

test10

4.10.2 v-model修饰符
  • v-model.trim:去除首位空格
  • v-model.number:转数字

示例:

姓名:<input v-model.trim="username" type="text"><br>
年纪:<input v-model.number="age" type="text"><br>

演示效果:

test12

4.10.3 事件修饰符
  • @事件名.stop : 阻止冒泡

    如何理解这里的 “阻止冒泡”

    点击子组件,不调用父组件的点击事件

  • @事件名.prevent :阻止默认行为

  • @事件名.stop.prevent :可以连用即阻止事件冒泡也阻止默认行为

示例:

<body>
  <div id="app">
    <h3>@事件名.stop     →  阻止冒泡</h3>
    <div @click="fatherFn" class="father">
      <div @click.stop="sonFn" class="son">儿子</div>
    </div>

    <h3>@事件名.prevent  →  阻止默认行为</h3>
    <a @click.prevent href="http://www.baidu.com">阻止默认行为</a>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        username: '',
        age: '',
      },
      methods: {
        fatherFn () {
          alert('父亲被点击了')
        },
        sonFn (e) {
          // e.stopPropagation()
          alert('儿子被点击了')
        }
      }
    })
  </script>
</body>

演示效果:

test14

4.11 v-bind对样式控制的增强

4.11.1 操作class

为了方便开发者进行样式控制, Vue 扩展了 v-bind 的语法,可以针对 class 类名style 行内样式 进行控制

语法:

<div> :class = "对象/数组">这是一个div</div>

对象语法:

当class动态绑定的是**对象时,键就是类名,值就是布尔值,如果值是true**,就有这个类,否则没有这个类

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

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

其中的布尔值一般是某个判断式子

数组语法:

当class动态绑定的是**数组**时 → 数组中所有的类,都会添加到盒子上,本质就是一个 class 列表

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

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

示例:

<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>
    .box {
      width: 100px;
      height: 100px;
      border: 3px solid #000;
      font-size: 20px;
      margin-top: 10px;
    }
    .pink {
      background-color: pink;
    }
    .big {
      width: 150px;
      height: 150px;
    }
  </style>
</head>
<body>

  <div id="app">
    <div class="box" :class="{ pink: true, big: true }">Vue前端设计</div>
    <div class="box" :class="{ pink: false, big: false }">Vue前端设计</div>
    <div class="box" :class="['pink', 'big']">Vue前端设计</div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {

      }
    })
  </script>
</body>

演示效果:

image-20240118140925021

4.11.2 案例-导航栏的切换

难点:

如何让点击的部分激活相关的class产生被选中的效果。

运行效果:

test15

代码:

<body>
  <div id="app">
    <ul>
      <li v-for="(item, index) in list" :key="item.id" @click="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: 2, // 记录高亮
        list: [
          { id: 1, name: '京东秒杀' },
          { id: 2, name: '每日特价' },
          { id: 3, name: '品类秒杀' }
        ]
      }
    })
  </script>
</body>
4.11.3 操作style

语法:

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

示例:

<body>
  <div id="app">
    <div class="box" :style="{ width: '400px', height: '400px', backgroundColor: 'green' }"></div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {

      }
    })
  </script>
</body>

效果演示:

image-20240118142134200

4.11.4 进度条案例

关键点:相关的按钮设置style属性为其宽度

代码:

<body>
  <div id="app">
    <!-- 外层盒子底色 (黑色) -->
    <div class="progress">
      <!-- 内层盒子 - 进度(蓝色) -->
      <div class="inner" :style="{ width: percent + '%' }">
        <span>{{ percent }}%</span>
      </div>
    </div>
    <button @click="percent = 25">设置25%</button>
    <button @click="percent = 50">设置50%</button>
    <button @click="percent = 75">设置75%</button>
    <button @click="percent = 100">设置100%</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        percent: 30
      }
    })
  </script>
</body>

效果演示:

test16

4.12 v-model在其他表单元素的使用

常见的表单元素都可以用 v-model 绑定关联 → 快速 获取设置 表单元素的值

它会根据 控件类型 自动选取 对应的方法 来更新元素

输入框  input:text   ——> value
文本域  textarea	 ——> value
复选框  input:checkbox  ——> checked
单选框  input:radio   ——> checked
下拉菜单 select    ——> value
...

例如,

如果控件类型是input:text,那么绑定了v-model之后,前后绑定的是其value值

如果控件类型是input:checkbox,那么绑定了v-model之后,前后绑定的是其checked值

代码:

<body>

  <div id="app">
    <h3>学习注册网</h3>

    姓名:
      <input type="text" v-model="username"> 
      <br><br>

    是否本科及以上学历:
      <input type="checkbox" v-model="bachelor"> 
      <br><br>

    <!-- 
      前置理解:
        1. name:  给单选框加上 name 属性 可以分组 → 同一组互相会互斥
        2. value: 给单选框加上 value 属性,用于提交给后台的数据
      结合 Vue 使用 → v-model
    -->
    性别: 
      <input v-model="gender" type="radio" name="gender" value="1"><input v-model="gender" type="radio" name="gender" value="2"><br><br>

    <!-- 
      前置理解:
        1. option 需要设置 value 值,提交给后台
        2. select 的 value 值,关联了选中的 option 的 value 值
      结合 Vue 使用 → v-model
    -->
    所在城市:
      <select v-model="cityId">
        <option value="101">北京</option>
        <option value="102">上海</option>
        <option value="103">成都</option>
        <option value="104">南京</option>
      </select>
      <br><br>

    自我描述:
      <textarea v-model="desc"></textarea> 

    <button>立即注册</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        username: '',
        bachelor: false,
        gender: "2",
        cityId: '102',
        desc: ""
      }
    })
  </script>
</body>

演示效果:

test18

4.13 computed计算属性

  • 基于现有的数据,计算出来的新属性
  • 如果依赖的数据变化,自动重新计算。

语法:

  1. 声明在 computed 配置项中,一个计算属性对应一个函数
  2. 使用起来和普通属性一样使用 {{ 计算属性名}}

注意:

  1. computed配置项和data配置项是**同级**的
  2. computed中的计算属性虽然是函数的写法,但他依然是个属性
  3. computed中的计算属性**不能和data中的属性同名**
  4. 使用computed中的计算属性和使用data中的属性是一样的用法
  5. computed中计算属性内部的this依然指向的是Vue实例

示例:计算礼物个数

<body>

  <div id="app">
    <h3>小黑的礼物清单</h3>
    <table>
      <tr>
        <th>名字</th>
        <th>数量</th>
      </tr>
      <tr v-for="(item, index) in list" :key="item.id">
        <td>{{ item.name }}</td>
        <td>{{ item.num }}个</td>
      </tr>
    </table>

    <!-- 目标:统计求和,求得礼物总数 -->
    <p>礼物总数:{{ totalCount }} 个</p>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        // 现有的数据
        list: [
          { id: 1, name: '篮球', num: 1 },
          { id: 2, name: '玩具', num: 2 },
          { id: 3, name: '铅笔', num: 5 },
        ]
      },
      computed: {
        totalCount () {
          // 基于现有的数据,编写求值逻辑
          // 计算属性函数内部,可以直接通过 this 访问到 app 实例
          // console.log(this.list)

          // 需求:对 this.list 数组里面的 num 进行求和 → reduce
          let total = this.list.reduce((sum, item) => sum + item.num, 0)
          return total
        }
      }
    })
  </script>
</body>

效果展示:

image-20240118165902688

4.13.1 computed计算属性 VS methods方法
  • computed计算属性

    作用:封装了一段对于数据的处理,求得一个结果

    语法:

    1. 写在computed配置项中
    2. 作为属性,直接使用
      • js中使用计算属性: this.计算属性
      • 模板中使用计算属性:{{计算属性}}

  • methods计算属性

    作用:给Vue实例提供一个方法,调用以处理业务逻辑

    语法:

    1. 写在methods配置项中
    2. 作为方法调用
      • js中调用:this.方法名()
      • 模板中调用 {{方法名()}} 或者 @事件名=“方法名”

  • computed计算属性的优势

    1. 缓存特性(提升性能)

      计算属性会对计算出来的结果缓存,再次使用直接读取缓存,

      依赖项变化了,会自动重新计算 → 并再次缓存

    2. methods没有缓存特性

4.13.2 总结

1.computed有缓存特性,methods没有缓存

2.当一个结果依赖其他多个值时,推荐使用计算属性

3.当处理业务逻辑时,推荐使用methods方法,比如事件的处理函数

4.13.3 计算属性的完整写法

既然计算属性也是属性,能访问,应该也能修改了?

  1. 计算属性默认的简写,只能读取访问,不能 “修改”
  2. 如果要 “修改” → 需要写计算属性的完整写法
image-20240118171206613

代码示例:

  • 当fullName计算属性,被获取求值时,执行get(有缓存,优先读缓存)
  • 当fullName计算属性,被修改赋值时,执行set,修改的值,传递给set方法的形参
<body>

  <div id="app">
    姓:<input type="text" v-model="firstName"> +
    名:<input type="text" v-model="lastName"> =
    <span>{{ fullName }}</span><br><br>
    
    <button @click="changeName">改名卡</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        firstName: '刘',
        lastName: '备',
      },
      methods: {
        changeName () {
          this.fullName = '黄忠'
        }
      },
      computed: {
        // 简写 → 获取,没有配置设置的逻辑
        // fullName () {
        //   return this.firstName + this.lastName
        // }

        // 完整写法 → 获取 + 设置
        fullName: {
          // (1) 当fullName计算属性,被获取求值时,执行get(有缓存,优先读缓存)
          //     会将返回值作为,求值的结果
          get () {
            return this.firstName + this.lastName
          },
          // (2) 当fullName计算属性,被修改赋值时,执行set
          //     修改的值,传递给set方法的形参
          set (value) {
            // console.log(value.slice(0, 1))          
            // console.log(value.slice(1))         
            this.firstName = value.slice(0, 1)
            this.lastName = value.slice(1)
          }
        }
      }
    })
  </script>
</body>

运行效果:

test19

4.14 watch侦听器(监视器)

监视数据变化,执行一些业务逻辑异步操作


4.14.1 语法
  1. watch同样声明在跟data同级的配置项中

  2. 简单写法: 简单类型数据直接监视

    data: { 
      words: '苹果',
      obj: {
        words: '苹果'
      }
    },
    
    watch: {
      // 该方法会在数据变化时,触发执行
      数据属性名 (newValue, oldValue) { //ewValue新值, oldValue老值(一般不用)
        一些业务逻辑 或 异步操作。 
      },
      '对象.属性名' (newValue, oldValue) {
        一些业务逻辑 或 异步操作。 
      }
    }
    
  3. 完整写法:添加额外配置项

    watch: {// watch 完整写法
      数据属性名: {
        deep: true, // 深度监视(针对复杂类型)
        immediate: true, // 是否立刻执行一次handler
        handler (newValue) {
          console.log(newValue)
        }
      }
    }
    
4.14.2 简单写法
<body>
<div id="app">
  <!-- 条件选择框 -->
  <div class="query">
    <span>翻译成的语言:</span>
    <select>
      <option value="italy">意大利</option>
      <option value="english">英语</option>
      <option value="german">德语</option>
    </select>
  </div>

  <!-- 翻译框 -->
  <div class="box">
    <div class="input-wrap">
      <textarea v-model="obj.words"></textarea>
      <span><i>??</i>文档翻译</span>
    </div>
    <div class="output-wrap">
      <div class="transbox">mela</div>
    </div>
  </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
  // 接口地址:https://applet-base-api-t.itheima.net/api/translate
  // 请求方式:get
  // 请求参数:
  // (1)words:需要被翻译的文本(必传)
  // (2)lang: 需要被翻译成的语言(可选)默认值-意大利
  // -----------------------------------------------

  const app = new Vue({
    el: '#app',
    data: {
      // words: ''
      obj: {
        words: ''
      }
    },
    // 具体讲解:(1) watch语法 (2) 具体业务实现
    watch: {
      // 该方法会在数据变化时调用执行
      // newValue新值, oldValue老值(一般不用)
      // words (newValue) {
      //   console.log('变化了', newValue)
      // }

      'obj.words' (newValue) {
        console.log('变化了', newValue)
      }
    }
  })
</script>
</body>

演示效果:

test

防抖:

防抖: 延迟执行 → 干啥事先等一等,延迟一会,一段时间内没有再次触发,才执行

const app = new Vue({
        el: '#app',
        data: {
          // words: ''
          obj: {
            words: ''
          },
          result: '', // 翻译结果
          // timer: null // 延时器id
        },
        // 具体讲解:(1) watch语法 (2) 具体业务实现
        watch: {
          // 该方法会在数据变化时调用执行
          // newValue新值, oldValue老值(一般不用)
          // words (newValue) {
          //   console.log('变化了', newValue)
          // }

          'obj.words' (newValue) {
            // console.log('变化了', newValue)
            // 防抖: 延迟执行 → 干啥事先等一等,延迟一会,一段时间内没有再次触发,才执行
            clearTimeout(this.timer)
            this.timer = setTimeout(async () => {
              const res = await axios({
                url: 'https://applet-base-api-t.itheima.net/api/translate',
                params: {
                  words: newValue
                }
              })
              this.result = res.data.data
              console.log(res.data.data)
            }, 300)
          }
        }
      })
4.14.3 完整写法

完整写法:添加额外的配置项

  1. deep:true 对复杂类型进行深度监听

    递归地监听对象内部属性的变化。当你需要监视嵌套对象或数组内部属性的变化时,可以使用深度监视。

    考虑一个场景,我们有一个用户对象,其中包含名称(name)和详细信息(details)。详细信息又包含年龄(age)和城市(city)。我们希望监视用户对象的变化,特别是用户详细信息内部属性的变化。

    如果不使用深度监听,我们只监听user对象本身的变化。如果我们直接修改user.details.agewatch将不会触发

    如果使用深度监听,无论是直接修改user的引用还是修改其内部的details属性,handler函数都会被触发。

  2. immdiate:true 初始化 立刻执行一次handler函数,而不需要等待数据变化。

代码示例:

<body>
<div id="app">
  <!-- 条件选择框 -->
  <div class="query">
    <span>翻译成的语言:</span>
    <select v-model="obj.lang">
      <option value="italy">意大利</option>
      <option value="english">英语</option>
      <option value="german">德语</option>
    </select>
  </div>

  <!-- 翻译框 -->
  <div class="box">
    <div class="input-wrap">
      <textarea v-model="obj.words"></textarea>
      <span><i>??</i>文档翻译</span>
    </div>
    <div class="output-wrap">
      <div class="transbox">{{ result }}</div>
    </div>
  </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
  // 需求:输入内容,修改语言,都实时翻译

  // 接口地址:https://applet-base-api-t.itheima.net/api/translate
  // 请求方式:get
  // 请求参数:
  // (1)words:需要被翻译的文本(必传)
  // (2)lang: 需要被翻译成的语言(可选)默认值-意大利
  // -----------------------------------------------

  const app = new Vue({
    el: '#app',
    data: {
      obj: {
        words: '你好',
        lang: 'italy'
      },
      result: '', // 翻译结果
    },
    watch: {
      obj: {
        deep: true, // 深度监视
        immediate: true, // 立刻执行,一进入页面handler就立刻执行一次
        handler (newValue) {
          clearTimeout(this.timer)
          this.timer = setTimeout(async () => {
            const res = await axios({
              url: 'https://applet-base-api-t.itheima.net/api/translate',
              params: newValue
            })
            this.result = res.data.data
            console.log(res.data.data)
          }, 300)
        }
      }


      // 'obj.words' (newValue) {
      //   clearTimeout(this.timer)
      //   this.timer = setTimeout(async () => {
      //     const res = await axios({
      //       url: 'https://applet-base-api-t.itheima.net/api/translate',
      //       params: {
      //         words: newValue
      //       }
      //     })
      //     this.result = res.data.data
      //     console.log(res.data.data)
      //   }, 300)
      // }
    }
  })
</script>
</body>

演示效果:(obj中任意一个发生变化,控制台都会有所响应)

test21

一个Vue的常用模板:

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

  </style>
</head>

<body>
  <div id="app">

  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>

    const app = new Vue({
      el: '#app',
      data: {

      },
      mounted() {

      },
      methods: {
        test() {
          var _this = this;
          axios({
            method: "get",
            url: "#",
          }).then(function (resp) {
            _this.$message({
              message: "添加成功。",
              type: 'success'
            });

          })
          setTimeout(function () {
            window.location.reload();
          }, 1500);
        }
      },
      computed: {
        totalCount() {
          let total = "res";
          return total
        }
      },
      watch: {
        obj: {
          deep: true, // 深度监视
          immediate: true, // 立刻执行,一进入页面handler就立刻执行一次
          handler(newValue) {
            clearTimeout(this.timer)
            this.timer = setTimeout(async () => {

            }, 300)
          }
        }
      }
    })
  </script>
</body>
</html>
文章来源:https://blog.csdn.net/qq_55626883/article/details/135697120
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。