Vue2(一):创建实例、插值表达式、Vue响应式特性、Vue指令、指令修饰符、计算属性

Vue:一个构建用户界面的渐进式框架

1、创建Vue实例

核心步骤:

准备容器、引包(官网)-开发版本/生产版本、创建Vue实例 new Vue()、指定配置项(在创建的实例里面)->渲染数据 - 1.el指定挂载点 2.data提供数据

html 复制代码
<body>
  <div class="box">
    <h3>{{msg}}</h3>
    <a href="#">{{cnt}}</a>
  </div>
  <p>--------------------------------------------------</p>
  <div id="app">
    <h3>{{msg}}</h3>
    <a href="#">{{cnt}}</a>
  </div>
  <script src="vue.js"></script>
  <script>
    // 一旦引入VueJS核心包,在全局环境,就有了Vue构造函数
    const app = new Vue({
      // 通过el配置选择器,指定Vue管理的是哪一个盒子
      el: '#app',
      // 通过data提供数据
      data: {
        msg: 456,
        cnt: '张三'
      }
    })
  </script>
</body>

2、插值表达式

是Vue的模板语法

作用:利用表达式进行插值,渲染到页面中。 表达式:是可以被求值的代码

语法:{{ 表达式 }}

注意点:

3、Vue响应式特性

响应式:数据改变,视图自动更新

html 复制代码
  <div id="app">
    <!-- 插值表达式 -->
    {{msg}}
    {{cnt}}
  </div>
  <script src="vue.js"></script>
  <script>
    const app = new Vue({
      // 通过el配置选择器,指定视图容器
      el: '#app',
      // 通过data提供数据
      data: {
        // 响应式数据:数据变化了,视图自动更新
        msg: 'abc',
        cnt: 123,
      }
    })
    // data中的数据,是会被添加到实例上
    // 访问数据 实例.属性名
    // 修改数据 实例.属性名 = 新值
    // 在控制台
  </script>

4、Vue指令

文档:Vue指令

Vue会根据不同的指令,针对标签实现不同的功能,解决不同业务场景需求。

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

1)v-html

作用:设置元素的innerHTML,能够动态解析标签

语法:v-html = "表达式"

html 复制代码
  <div id="app">
    <!-- 插值表达式 不能解析标签-->
    <!-- {{msg}} -->
    <div v-html="msg"></div>
  </div>

  <script src="vue.js"></script>
  <script>
    const app = new Vue({
      // 通过el配置选择器,指定视图容器
      el: '#app',
      // 通过data提供数据
      data: {
        // 响应式数据:数据变化了,视图自动更新
        msg: `
          <a href="https://www.baidu.com/">
            百度
          </a>
        `
      }
    })
  </script>
2)v-show和v-if
(1)v-show

**作用:**控制元素显示隐藏

**语法:**v-show = "表达式" 表达式值 true显示,false隐藏

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

**使用场景:**适用于频繁切换显示隐藏的场景

(2)v-if

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

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

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

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

(3)代码演示

v-show底层原理:切换 css 的 display: none 来控制显示隐藏(简单的显示隐藏)

v-if 底层原理:根据判断条件控制元素的创建和移除(条件渲染)

html 复制代码
  <div id="app">
    <div v-show="flag" class="box">v-show</div>
    <div v-if="flag" class="box">v-if</div>
  </div>

  <script src="vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        flag: true
      }
    })
  </script>
html 复制代码
  <div id="app">
    <div v-show="flag" class="box">v-show</div>
    <div v-if="flag" class="box">v-if</div>
  </div>

  <script src="vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        flag: false
      }
    })
  </script>
3)v-else和v-else-if

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

语法:v-else 、v-else-if = "表达式"

注意:需要紧挨着 v-if 使用

html 复制代码
  <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="./vue.js"></script>
  <script>

    const app = new Vue({
      el: '#app',
      data: {
        gender: 2,
        score: 80
      }
    })
  </script>
4)v-on

作用:注册事件 = 添加监听 + 提供处理逻辑

语法:1. v-on:事件名 = "内联语句" (只适用于逻辑简单的情况)

  1. v-on: 事件名 = "methods中的函数名"

v-on:事件名可以用@事件名代替

第一种:
html 复制代码
  <div id="app">
    <!-- v-on: 可以替换为@ -->
    <!-- <button v-on:click="cnt--">-</button> -->
    <button @click="cnt--">-</button>
    <span>{{cnt}}</span>
    <!-- <button v-on:click="cnt++">+</button> -->
    <button @click="cnt++">+</button>
  </div>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        cnt: 10
      }
    })
  </script>
第二种:
html 复制代码
  <div id="app">
    <!-- <button @click="isShow = !isShow">切换显示隐藏</button> -->
    <button @click="fn">切换显示隐藏</button>
    <h1 v-show="isShow">Hello World!</h1>
  </div>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      // data 用来提供数据
      data: {
        isShow: true
      },
      // methods 用来提供方法
      methods: {
        fn() {
          // app.isShow = !app.isShow
          // 让提供的所有methods中的函数,this都指向当前的Vue实例
          // console.log(this)
          this.isShow = !this.isShow
        }
      }
    })
  </script>
v-on调用传参:
html 复制代码
  <div id="app">
    <div class="box">
      <h3>小黑自动售货机</h3>
      <button @click="buy(5)">可乐5元</button>
      <button @click="buy(10)">咖啡10元</button>
    </div>
    <p>银行卡余额:{{resMoney}}元</p>
  </div>

  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        resMoney: 1000
      },
      methods: {
        buy(price) {
          this.resMoney -= price
        }
      }
    })
  </script>
5)v-bind

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

语法:v-bind:属性名="表达式" v-bind:src 简写为**:src**

html 复制代码
  <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="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        imgUrl: './images/10-01.png',
        msg: 123
      }
    })
  </script>
图片切换案例:
html 复制代码
  <div id="app">
    <button v-show="index > 0" @click="index--">上一页</button>
    <div>
      <!-- 通过 :src="list[index]" 动态设置图片的url -->
      <img :src="list[index]" alt="">
    </div>
    <button v-show="index<list.length-1" @click="index++">下一页</button>
  </div>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      // 用数组存放需要切换的图片
      data: {
        index: 0,
        list: [
          './images/11-00.gif',
          './images/11-01.gif',
          './images/11-02.gif',
          './images/11-03.gif',
          './images/11-04.png',
          './images/11-05.png',
        ]
      }
    })
  </script>
6)v-for

作用:基于数据循环,多次渲染整个元素

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

html 复制代码
  <div id="app">
    <h3>小黑水果店</h3>
    <ul>
      <!-- 数组有几项就有循环几次 -->
      <li v-for="(item) in list">
        {{item}}
      </li>
    </ul>
  </div>

  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        list: ['西瓜', '苹果', '鸭梨']
      }
    })
  </script>
图书管理案例-小黑的书架
html 复制代码
  <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="./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) {
          // filter:根据条件,保留满足条件的对应项,得到一个新数组(不会改变原数组)
          // 因此要把filter得到的数组赋值回原数组
          this.booksList = this.booksList.filter(item => item.id != id)
        }
      }
    })
  </script>
v-for中的key

语法:key属性="唯一标识"

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

注意点:key的值只能是字符串或数字类型、key的值必须具有唯一性、推荐使用 id 作为key(唯一),不推荐使用index作为key(会变化,不能唯一标识)

<li v-for="(item,index) in xxx" :key="唯一值">

v-for的默认行为会尝试原地修改元素(就地复用)

不加key的情况,删除第一个 li 实际是把后面三个移上去,然后把最后一个li删掉,如下所示:

7)v-model

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

  1. 数据变化 -> 视图自动更新

  2. 视图变化 -> 数据自动更新

语法:v-moder='变量'

html 复制代码
  <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="./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>

5、综合案例 - 小黑记事本

html 复制代码
  <!-- 主体区域 -->
  <section id="app">
    <!-- 输入框 -->
    <header class="header">
      <h1>小黑记事本</h1>
      <input v-model="todoName" placeholder="请输入任务" class="new-todo" />
      <button @click="add()" class="add">添加任务</button>
    </header>
    <!-- 列表区域 -->
    <section class="main">
      <ul class="todo-list">
        <li class="todo" v-for="(item,index) in list" :key="item.id">
          <div class="view">
            <span class="index">{{index+1}}.</span> <label>{{item.name}}</label>
            <button class="destroy" @click="del(item.id)"></button>
          </div>
        </li>
      </ul>
    </section>
    <!-- 统计和清空 -->
    <footer class="footer" v-show="list.length>0">
      <!-- 统计 -->
      <span class="todo-count">合 计:<strong> {{list.length}} </strong></span>
      <!-- 清空 -->
      <button @click="clear()" class="clear-completed">
        清空任务
      </button>
    </footer>
  </section>

  <!-- 底部 -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    // 添加功能
    // 通过 v-model 绑定输入框
    // 点击按钮 ,新增,往数组最前面加,unshift


    const app = new Vue({
      el: '#app',
      data: {
        todoName: '',
        list: [
          { id: 1, name: '敲代码' },
          { id: 2, name: '听音乐' },
          { id: 3, name: 'Timi' }
        ]
      },
      methods: {
        del(id) {
          this.list = this.list.filter(item => item.id != id)
        },
        add() {
          if (this.todoName) {
            this.list.unshift({
              id: +new Date,
              name: this.todoName
            })
          } else {
            alert('请输入任务名称')
          }

          this.todoName = ''
        },
        clear() {
          this.list = []
        }
      }
    })

  </script>

6、指令修饰符

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

修饰符

按键修饰符 eg:小黑记事本案例,输入回车就可以添加

html 复制代码
    <!-- 输入框 -->
    <header class="header">
      <h1>小黑记事本</h1>
      <input @keyup.enter="add" v-model="todoName" placeholder="请输入任务" class="new-todo" />
      <button @click="add()" class="add">添加任务</button>
    </header>

底层实现原理:

html 复制代码
  <div id="app">
    <h3>@keyup.enter → 监听键盘回车事件</h3>
    <input @keyup.enter="fn" v-model="username" type="text">
  </div>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        username: ''
      },
      methods: {
        fn(e) {
          // @key.后面加enter相当于下面的判断
          // if (e.key === 'Enter') {
          //   console.log('回车触发', this.username)
          // }
          console.log('回车触发', this.username)
        }
        
      }
    })
  </script>
html 复制代码
<!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>
    .father {
      width: 200px;
      height: 200px;
      background-color: pink;
      margin-top: 20px;
    }

    .son {
      width: 100px;
      height: 100px;
      background-color: skyblue;
    }
  </style>
</head>

<body>
  <div id="app">
    <h3>v-model修饰符 .trim .number</h3>
    姓名:<input v-model.trim="username" v-model="username" type="text"><br>
    <!-- v-model-number 尝试为我们转数字;abc就转不了 -->
    年纪:<input v-model-number="age" v-model="age" type="text"><br>


    <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="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        username: '',
        age: '',
      },
      methods: {
        fatherFn() {
          alert('老父亲被点击了')
        },
        sonFn() {
          // e.stopPropagation()
          alert('儿子被点击了')
        }
      }
    })
  </script>
</body>

</html>

7、v-bind操作class和style

1)操作class

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

案例:tab导航高亮
html 复制代码
  <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="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        activeIndex: 0, //记录哪个 li 高亮
        list: [
          { id: 1, name: '京东秒杀' },
          { id: 2, name: '每日特价' },
          { id: 3, name: '品类秒杀' }
        ]

      }
    })
  </script>
2)操作style

语法::style="样式对象"

html 复制代码
  <div id="app">
    <!-- <div class="box" :style="{width:'400px',height:'400px','background-color':'pink'}"></div> -->
    <div class="box" :style="{width:'400px',height:'400px',backgroundColor:'pink'}"></div>
  </div>
案例:进度条
html 复制代码
<!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>
    .progress {
      height: 25px;
      width: 400px;
      border-radius: 15px;
      background-color: #272425;
      border: 3px solid #272425;
      box-sizing: border-box;
      margin-bottom: 30px;
    }

    .inner {
      width: 50%;
      height: 20px;
      border-radius: 10px;
      text-align: right;
      position: relative;
      background-color: #409eff;
      background-size: 20px 20px;
      box-sizing: border-box;
      transition: all 1s;
    }

    .inner span {
      position: absolute;
      right: -20px;
      bottom: -25px;
    }
  </style>
</head>

<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 = 70">设置75%</button>
    <button @click="percent = 100">设置100%</button>
  </div>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        percent: 0
      }
    })
  </script>
</body>

</html>

8、v-model应用于其他表单元素

html 复制代码
  <div id="app">
    <h3>小黑学习网</h3>

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

    是否单身:
    <input type="checkbox" v-model="isSingle">
    <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="10">北京</option>
      <option value="11">上海</option>
      <option value="12">成都</option>
      <option value="13">南京</option>
    </select>
    <br><br>

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

    <button>立即注册</button>
  </div>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        username: '',
        isSingle: true,
        gender: 1,
        cityId: '10',
        desc: ''
      }
    })
  </script>

9、计算属性

html 复制代码
  <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="./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 ,不加括号,因为 computed 是(计算)属性
        totalCount() {
          // 计算属性函数内部,可以直接通过 this 访问到 app 实例
          console.log(this.list)
          let cnt = this.list.reduce((sum, item) => sum + item.num, 0)
          return cnt
        }
      }
    })
  </script>
与methods的区别
html 复制代码
  <div id="app">
    <h3>小黑的礼物清单🛒<span>{{totalCount}}</span></h3>
    <h3>小黑的礼物清单🛒<span>{{totalCountFn()}}</span></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="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        // 现有的数据
        list: [
          { id: 1, name: '篮球', num: 3 },
          { id: 2, name: '玩具', num: 2 },
          { id: 3, name: '铅笔', num: 5 },
        ]
      },
      methods: {
        totalCountFn() {
          console.log(methods)  // 执行一次,打印一次
          let total = this.list.reduce((sum, item) => sum + item.num, 0)
          return total
        }
      },
      computed: {
        // 计算属性:有缓存的,一旦计算出结果,就会立刻缓存
        // 下一次读取 -> 直接读缓存就行
        totalCount() {
          console.log(computed) //不修改数据,只打印一次
          let total = this.list.reduce((sum, item) => sum + item.num, 0)
          return total
        }
      }
    })
  </script>
计算属性的完整写法

计算属性默认的简写,只能读取访问,不能"修改",如果要"修改",需要写计算属性的完整写法

html 复制代码
  <div id="app">
    姓:<input type="text" v-model="firstName"><br>
    名:<input type="text" v-model="lastName"><br>
    <p>姓名:<span>{{ fullName }}</span></p>
    <button @click="changeName">修改姓名</button>
  </div>
  <script src="./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: {
          // 当fullName计算属性,被获取求值时,执行get(有缓存,先执行缓存)
          // 会将返回值作为求值的结果
          get() {
            return this.firstName + this.lastName
          },
          // 当fullName计算属性被修改赋值时,执行set
          // 修改的值,传递给set方法的形参
          set(value) {
            console.log(value)
            this.firstName = value.slice(0, 1)
            this.lastName = value.slice(1)
          }
        }
      }
    })
  </script>

10、综合案例:成绩案例

html 复制代码
  <div id="app" class="score-case">
    <div class="table">
      <table>
        <thead>
          <tr>
            <th>编号</th>
            <th>科目</th>
            <th>成绩</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody v-if="list.length > 0">
          <tr v-for="(item,index) in list" :key="item.id">
            <td>{{index+1}}</td>
            <td>{{item.subject}}</td>
            <td :class="{ red:item.score < 60 }">{{item.score}}</td>
            <td><a @click.prevent="del(item.id)" href="#">删除</a></td>
          </tr>

          </tr>
        </tbody>
        <tbody v-else>
          <tr>
            <td colspan="5">
              <span class="none">暂无数据</span>
            </td>
          </tr>
        </tbody>

        <tfoot>
          <tr>
            <td colspan="5">
              <span>总分:{{tetalScore}}</span>
              <span style="margin-left: 50px">平均分:{{averageScore}}</span>
            </td>
          </tr>
        </tfoot>
      </table>
    </div>
    <div class="form">
      <div class="form-item">
        <div class="label">科目:</div>
        <div class="input">
          <input type="text" placeholder="请输入科目" v-model.trim="subject" />
        </div>
      </div>
      <div class="form-item">
        <div class="label">分数:</div>
        <div class="input">
          <input type="text" placeholder="请输入分数" v-model.number="score" />
        </div>
      </div>
      <div class="form-item">
        <div class="label"></div>
        <div class="input">
          <button @click="add()" class="submit">添加</button>
        </div>
      </div>
    </div>
  </div>
  <script src="./vue.js"></script>

  <script>
    const app = new Vue({
      el: '#app',
      data: {
        list: [
          { id: 1, subject: '语文', score: 20 },
          { id: 7, subject: '数学', score: 99 },
          { id: 12, subject: '英语', score: 70 },
        ],
        subject: '',
        score: ''
      },
      methods: {
        del(id) {
          this.list = this.list.filter(item => item.id != id)
        },
        add() {
          if (!this.subject) {
            alert('请输入科目')
            return
          }
          if (typeof this.score !== 'number') {
            alert('请输入正确的分数')
            return
          }
          this.list.unshift({
            id: +new Date(),
            subject: this.subject,
            score: this.score
          })
          this.subject = ''
          this.score = ''
        }
      },
      computed: {
        tetalScore() {

          return this.list.reduce((sum, item) => sum + item.score, 0)
        },
        averageScore() {
          if (this.list.length === 0) return 0
          return (this.tetalScore / this.list.length).toFixed(2)
        }
      }
    })
  </script>

11、watch侦听器(监视器)

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

相关推荐
小小爱大王6 小时前
AI 编码效率提升 10 倍的秘密:Prompt 工程 + 工具链集成实战
java·javascript·人工智能
半生过往6 小时前
2025 前端动效实战指南:Vue Bits & React Bits 深度拆解(功能 / 复用 / 高频问题处理)
前端·vue.js·react.js
程序员包打听6 小时前
Vitest 4.0 重磅发布:Browser Mode 正式稳定,前端测试进入新纪元
前端
BumBle6 小时前
UniApp 多页面编译优化:编译时间从10分钟到1分钟
前端
星链引擎6 小时前
大语言模型的技术突破与稳定 API 生态的构建
前端
还是大剑师兰特6 小时前
TypeScript 面试题及详细答案 100题 (71-80)-- 模块与命名空间
前端·javascript·typescript
BumBle6 小时前
使用 SortableJS 实现vue3 + Element Plus 表格拖拽排序
前端·vue.js·element
玉宇夕落6 小时前
HTML5 音乐敲击乐静态界面
前端
海在掘金611276 小时前
告别"拼写错误":TS如何让你的代码"字字精准"
前端