vue复习1~45

发布于:2025-03-28 ⋅ 阅读:(36) ⋅ 点赞:(0)
1.关于vue

要理解记忆规则,可以到官网上去找
vue的两种使用方式

  1. vue核心包开发
    场景:局部模块改造
  2. vue核心包 & vue插件 工程化开发
    场景:整站开发
2.创建vue实例

构建用户页面->创建vue实例初始化渲染
学习阶段用开发版本

3.插值表达式
  1. 使用的数据必须存在(data)
  2. 里面不能写语句
  3. 不能在 标签属性 里面使用{{ }}插值
4.vue响应式

数据变化,视图自动更新

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

  1. 访问数据 实例.属性名
  2. 修改数据 实例.属性名 = 新值

修改数据-> vue监听到数据修改-> 自动更新视图DOM操作

5.vue指令v–html

动态的设置innerhtml
动态的解析标签
代码:

<body>
  <div id="app">
    <div v-html="msg"></div>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>

    const app = new Vue({
      el: '#app',
      data: {
        msg: `
          <h3>学前端~来黑马!</h3>
        `
      }
    })

  </script>
</body>
6.v-show和v-if

均控制元素显示隐藏

区别:
v-show底层原理:切换 css 的 display: none 来控制显示隐藏
v-show=“false”
场景:频繁切换显示隐藏的场景

v-if 底层原理:根据 判断条件 控制元素的 创建 和 移除(条件渲染)
v-if=“false”
场景:不频繁切换显示隐藏的场景,eg:登录

7.v-else和v-else-if

两者均辅助v-if进行判断渲染,紧挨着v-if使用
v-else,特别的,不能单独使用
使用情况

  1. v-else,只有两种,eg:性别
  2. v-else-if,两个以上,eg:等级
<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>
8.v-on

注册事件=添加监听+提供处理逻辑
语法1:
简写

<button @click="count--">-</button>

详写

<button v-on:click="count++">+</button>

语法2:
v-on:事件名=”methods中的函数名“
必须先加this指向vue实例(app)才能拿到data里面的数据

<body>
  <div id="app">
    <button @click="fn">切换显示隐藏</button>
    <h1 v-show="isShow">黑马程序员</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都指向当前实例
          this.isShow = !this.isShow
        }
      }
    })
  </script>
</body>
9.v-on调用传参

要用this
传两个,三个参数也是可以的

<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>
10.v-bind

动态的设置html的标签属性

<img v-bind:src="imgUrl" v-bind:title="msg" alt="">

简化版

<img :src="imgUrl" :title="msg" alt="">
11.波仔的学习之旅

代码:

<body>
  <div id="app">
    <button v-show="index > 0" @click="index--">上一页</button>
    <img :src="list[index]" alt="">
    <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>
12.v-for

基于数据循环,多次渲染整个元素,有对象,数组,数字
item是遍历时的每一项
index是数组的下标

v-for="(item, index) in list"
例:
<li v-for="(item, index) in list">
        {{ item }} - {{ index }}
      </li>
      不用index时
      <li v-for="item in list">
        {{ item }}
      </li>

v-for 里面的key

给列表添加唯一的标识,便于vue进行列表项的正确排序复用
注意:

  1. key的值只能是字符串或者是数字类型
  2. key的值必须唯一
  3. 推荐使用id作为key,不推荐使用index(会变化,不对应)
13.小黑的书架

** filter: 根据条件,保留满足条件的对应项,得到一个新数组。**
this.bookList = this.bookList.filter(item => item.id !=id)

<body>

  <div id="app">
    <h3>小黑的书架</h3>
    <ul>
      <li v-for="(item,index) in booksList">
        <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>
    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>
14.v-model

给表单元素使用

v-model 可以让数据和视图,形成双向数据绑定
(1) 数据变化,视图自动更新
(2) 视图变化,数据自动更新
可以快速[获取]或[设置]表单元素的内容

v-model的绑定内容写在data里面

<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>
    const app = new Vue({
      el: '#app',
      data: {
        username: ' ' ,
        password: ' '
      },
      methods: {
        login () {
          console.log(this.username, this.password)
        },
        reset () {
          this.username = ' '
          this.password = ' '
        }
      }
    })
  </script>
</body>
15.小黑记事本
<body>

<!-- 主体区域 -->
<section id="app">
  <!-- 输入框 -->
  <header class="header">
    <h1>小黑记事本</h1>
    <input v-model="todoName" placeholder="请输入任务" class="new-todo" />
    <button class="add" @click="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 @click="del(item.id)" class="destroy"></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: 3, name: '游泳100米' },
      ]
    },
    methods: {
      del (id) {
        // console.log(id) => filter 保留所有不等于该 id 的项
        this.list = this.list.filter(item => item.id !== id)
      },
      add() {
        if(this.todoName.trim === ''){
          alert('请输入任务名称')
          return
        }
        this.list.unshift({
          id: +new Date(),
          name: this.todoName
        })
        this.todoName = ''
      },
      clear() {
        this.list = []
      }
    }
  })

</script>
</body>
16.指令修饰符

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

  1. 按键修饰符
@keyup.enter="fn" 键盘回车监听
  1. v-model修饰符
v-model.trim="username" 去除首尾空格
v-model.number="age" 转数字
  1. 事件修饰符
@click.stop="sonFn" 阻止冒泡
@click.prevent 阻止默认行为
17.v-bind对于样式控制的增强

语法:
:class=“对象/数组”

  1. 对象:键就是类名,值是布尔值,true则有类,反之
<div class="box" :class="{ pink: true, big: true }">黑马程序员</div>

使用场景:一个类名,来回切换
2. 数组:数组中所有的类,都会添加到盒子上,本质就是class列表

<div class="box" :class="['pink', 'big']">黑马程序员</div>

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

操作style
语法:

值必须用引号引起来!
行内样式强大的是对单个属性的控制

<div class="box" :style="{ width: '400px', height: '400px', backgroundColor: 'green' }"></div>

案例:

<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>
18.京东秒杀tab导航高亮
<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>
19.v-model应用于其他表单元素

常见的表单元素

  1. 输入框 input:text ->value
  2. 文本域textarea ->value
  3. 复选框 input:checkbox ->checked
  4. 单选框 input:radio ->checked
  5. 下拉菜单 select ->value

name: 给单选框加上 name 属性 可以分组 → 同一组互相会互斥
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>

option 需要设置 value 值,提交给后台
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: ' ',
        isSingle: false,
        gender: "2",
        cityId: '102',
        desc: " "
      }
    })
  </script>
20.计算属性

放在与data并列的computed里

基于现有的数据,编写求值逻辑
在computed配置项里,一个计算属性对应一个函数
使用:{{ 计算属性名 }}
一定要return

computed: {
	//计算属性名 () {
		 // 基于现有的数据,编写求值逻辑
		 return 结果
}

求和用reduce
需求:
对 this.list 数组里面的 num 进行求和 → reduce
//0 是求和的起始值
let total = this.list.reduce((sum, item) => sum + item.num,0)
return total

21.computed计算属性 VS methods 方法

computed计算属性
封装数据处理,求结果
特别的:有缓存的,一旦计算出来结果,就会立刻缓存,下一次读取 → 直接读缓存就行 → 性能特别高
作为属性直接使用,this.计算属性{{ 计算属性 }}

methods 方法
给实例提供方法,调用以处理业务逻辑
作为方法,需要调用,this.方法名() {{ 方法名() }} @事件名=“方法名”

22.计算属性完整写法
computed: {
        // 完整写法 → 获取 + 设置
        fullName: {
          get () {
            	一段代码逻辑(计算逻辑)
            	return 结果
          },
          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>
23.成绩案例
 <body>
    <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>
          </tbody>
          <tbody v-else>
            <tr>
              <td colspan="5">
                <span class="none">暂无数据</span>
              </td>
            </tr>
          </tbody>

          <tfoot>
            <tr>
              <td colspan="5">
                <span>总分:{{ totalCount }}</span>
                <span style="margin-left: 50px">平均分:{{ averageCount }}</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="https://cdn.jsdelivr.net/npm/vue@2/dist/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: ''
        },
        computed:{
          totalCount() {
            return this.list.reduce((sum,item) => sum + item.score,0)
          },
          averageCount () {
            if (this.list.length === 0) {
              return 0
            }
            //toFixed(2)保留两位小数
            return (this.totalCount / this.list.length).toFixed(2)
          }
        },
        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
            }
            //在开头插入元素 unshift
            this.list.unshift({
              id: +new Date(),
              subject: this.subject,
              score: this.score
            })
            this.subject = ''
            this.score = ''
           }

        }
      })
    </script>
  </body>
24.watch侦听器(监视器)

可持久化到本地
监视数据变化,执行业务逻辑或异步操作

  1. 简单写法:简单类型数据,直接监视
  2. 完整写法:添加额外配置项
    简单写法
    ** ‘obj.words’ ,对象里面的子属性,方法名一定要加引号**
    若是直接属性名,则不用加引号
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)
          }
        }
      })

加上防抖效果,防止多次触发

'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)
          }

完整写法

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)
            }
25.水果购物车

!!!!!!!!!!!!!!!!!!!!!!!!!!

计算属性的完整写法 isAll: { get() {}, set() {} } 全名用冒号
watch监听器 里的监听的对象要用冒号 watch : { list: {} }
computed计算属性 、methods 方法、watch监听一律用冒号

<body>
    <div class="app-container" id="app">
      <!-- 顶部banner -->
      <div class="banner-box"><img src="http://autumnfish.cn/static/fruit.jpg" alt="" /></div>
      <!-- 面包屑 -->
      <div class="breadcrumb">
        <span>🏠</span>
        /
        <span>购物车</span>
      </div>
      <!-- 购物车主体 -->
      <div class="main" v-if="fruitList.length > 0">
        <div class="table">
          <!-- 头部 -->
          <div class="thead">
            <div class="tr">
              <div class="th">选中</div>
              <div class="th th-pic">图片</div>
              <div class="th">单价</div>
              <div class="th num-th">个数</div>
              <div class="th">小计</div>
              <div class="th">操作</div>
            </div>
          </div>
          <!-- 身体 -->
          <div class="tbody">
            <div class="tr" v-for="(item,index) in fruitList" :key="item.id" :class="{active: item.isChecked}">
              <div class="td"><input type="checkbox" v-model="item.isChecked" /></div>
              <div class="td"><img :src="item.icon" alt="" /></div>
              <div class="td">{{ item.price }}</div>
              <div class="td">
                <div class="my-input-number">
                  <button class="decrease" :disabled="item.num <= 1" @click="sub(item.id)"> - </button>
                  <span class="my-input__inner">{{ item.num }}</span>
                  <button class="increase" @click="add(item.id)"> + </button>
                </div>
              </div>
              <div class="td">{{ item.price*item.num }}</div>
              <div class="td"><button @click="del(item.id)">删除</button></div>
            </div>
          </div>
        </div>
        <!-- 底部 -->
        <div class="bottom">
          <!-- 全选 -->
          <label class="check-all">
            <input type="checkbox" v-model="isAll"/>
            全选
          </label>
          <div class="right-box">
            <!-- 所有商品总价 -->
            <span class="price-box">总价&nbsp;&nbsp;:&nbsp;&nbsp;¥&nbsp;<span class="price">{{ totalPrice }}</span></span>
            <!-- 结算按钮 -->
            <button class="pay">结算( {{ totalCount }} )</button>
          </div>
        </div>
      </div>
      <!-- 空车 -->
      <div class="empty" v-else>🛒空空如也</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <script>
      const defaultArr = [
      {
              id: 1,
              icon: 'http://autumnfish.cn/static/火龙果.png',
              isChecked: true,
              num: 2,
              price: 6,
            },
            {
              id: 2,
              icon: 'http://autumnfish.cn/static/荔枝.png',
              isChecked: false,
              num: 7,
              price: 20,
            },
            {
              id: 3,
              icon: 'http://autumnfish.cn/static/榴莲.png',
              isChecked: false,
              num: 3,
              price: 40,
            },
            {
              id: 4,
              icon: 'http://autumnfish.cn/static/鸭梨.png',
              isChecked: true,
              num: 10,
              price: 3,
            },
            {
              id: 5,
              icon: 'http://autumnfish.cn/static/樱桃.png',
              isChecked: false,
              num: 20,
              price: 34,
            },
      ]
      const app = new Vue({
        el: '#app',
        data: {
          // 水果列表
          fruitList: JSON.parse(localStorage.setItem('list') || defaultArr),
        },
        computed: {
          //完整写法= get + set
          isAll : {
            get() {
              //必须所有的小选框都选中,全选按钮才选中 => every
              return this.fruitList.every(item => item.isChecked)
            },
            set(value) {
              //拿到的value值是true或false
              //同步状态是赋值,=
              this.fruitList.forEach(item => item.isChecked = true)
            }
          },
          //统计选中的总数 reduce
          totalCount(){
            return this.fruitList.reduce((sum,item) => {
              if(item.isChecked){
                return sum + item.num
              }else{
                return sum
              }
            } ,0)
          },
          //统计选中的总价
          totalPrice() {
            return this.fruitList.reduce((sum,item) => {
              if(item.isChecked){
                return (sum + item.num) * item.price
              }else{
                return sum
              }
            } ,0)
          }
        },
        methods: {
          del(id) {
            this.fruitList = this.fruitList.filter(item => item.id !==id)
          },
          add(id) {
            //find
            const fruit = this.fruitList.find(item => item.id === id)
            fruit.num++
          },
          sub(id) {
            const fruit = this.fruitList.find(item => item.id === id)
            fruit.num--
          }
        },
        //持久化到本地就是要用到监听
        watch : {
          fruitList: {
            deep: true,
            handler(newValue) {
              //将变化的newValue存入本地(转JSON)
              localStorage.setItem('list',JSON.stringify(newValue))
            }
          }
        }
      })
    </script>
  </body>
26.vue生命周期和生命周期的四个钩子

vue生命周期 :一个vue实例从创建到销毁的整个过程
创建 响应式数据
挂载 渲染模板
更新 数据修改,更新视图
销毁 销毁实例

before Create
created 发送初始化渲染请求 常用
before Mount
mounted 操作DOM 常用
before Update
updated
before Destroy 释放vue以外的资源(清楚定时器,延时器…)常用
destroyed

27.created应用,mounted应用

created钩子与data并列
created:响应式数据准备好了,可以发送初始化渲染请求

  1. created应用
async created () {
        // 1. 发送请求获取数据
        const res = await axios.get('http://hmajax.itheima.net/api/news')
        // 2. 更新到 list 中,用于页面渲染 v-for
        this.list = res.data.data
      }
  1. mounted应用
 // 核心思路:
    // 1. 等input框渲染出来 mounted 钩子
    // 2. 让input框获取焦点 inp.focus()
    mounted () {
      document.querySelector('#inp').focus()
    }
  })
28.小黑记账清单

功能需求:
1. 基本渲染
(1) 立刻发送请求获取数据 created
(2) 拿到数据,存到data的响应式数据中
(3) 结合数据,进行渲染 v-for
(4) 消费统计 => 计算属性
2. 添加功能
(1) 收集表单数据 v-model
(2) 给添加按钮注册点击事件,发送添加请求
(3) 需要重新渲染
3. 删除功能
(1) 注册点击事件,传参传 id
(2) 根据 id 发送删除请求
(3) 需要重新渲染
4. 饼图渲染
(1) 初始化一个饼图 echarts.init(dom) mounted钩子实现
(2) 根据数据实时更新饼图 echarts.setOption({ … })

<body>
    <div id="app">
      <div class="contain">
        <!-- 左侧列表 -->
        <div class="list-box">

          <!-- 添加资产 -->
          <form class="my-form">
            <input v-model.trim="name" type="text" class="form-control" placeholder="消费名称" />
            <input v-model.number="price" type="text" class="form-control" placeholder="消费价格" />
            <button @click="add" type="button" class="btn btn-primary">添加账单</button>
          </form>

          <table class="table table-hover">
            <thead>
              <tr>
                <th>编号</th>
                <th>消费名称</th>
                <th>消费价格</th>
                <th>操作</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="(item,index) in list" :key="item.id">
                <td>{{  index + 1}}</td>
                <td>{{ item.name }}</td>
                <td :class="{red: item.price > 500}">{{ item.price.toFixed(2) }}</td>
                <td><a @click="del(item.id)" href="javascript:;">删除</a></td>
              </tr>
            </tbody>
            <tfoot>
              <tr>
                <td colspan="4">消费总计:{{ totalPrice.toFixed(2) }}</td>
              </tr>
            </tfoot>
          </table>
        </div>
        
        <!-- 右侧图表 -->
        <div class="echarts-box" id="main"></div>
      </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>
    <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://www.apifox.cn/apidoc/shared-24459455-ebb1-4fdc-8df8-0aff8dc317a8/api-53371058
       * 
       * 功能需求:
       * 1. 基本渲染
       * 2. 添加功能
       * 3. 删除功能
       * 4. 饼图渲染
       */
      const app = new Vue({
        el: '#app',
        data: {
          list: [],
          name: '',
          price: '',
        },
        computed: {
          totalPrice() {
            return this.list.reduce((sum,item) => sum + item.price,0)
          }
        },
        created () {
          //只有get和delate时,要用params
          //重新渲染,多次使用,得封装
          // const res = await axios.get('https://applet-base-api-t.itheima.net/bill',{
          //   params: {
          //     creator: '小智'
          //   }
          // })
          // this.list = res.data.data
          
          this.getList()
        },
        mounted () {
          this.myChart =  echarts.init(document.querySelector('#main'))
          this.myChart.setOption
            ({
              title: {
                text: '消费账单列表',
                subtext: 'Fake Data',
                left: 'center'
              },
              tooltip: {
                trigger: 'item'
              },
              legend: {
                orient: 'vertical',
                left: 'left'
              },
              //数据项
              series: [
                {
                  name: '消费账单',
                  type: 'pie',
                  radius: '50%',
                  data: [
                    
                  ],
                  emphasis: {
                    itemStyle: {
                      shadowBlur: 10,
                      shadowOffsetX: 0,
                      shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                  }
                }
              ]
            })
        },
        methods: {
          async getList () {
            const res = await axios.get('https://applet-base-api-t.itheima.net/bill',{
              params: {
                creator: '小智'
              }
            })
            this.list = res.data.data

            //更新图表
            this.myChart.setOption({
              //数据项
              series: [
                {
                  data: this.list.map(item => ({value: item.price, name: item.name}))
                  
                }
              ]

            })
          },
          async add() {
            //如果name不存在
            if(!this.name) {
              alert('请输入消费名称')
              return 
            }
            if(typeof this.price !== 'number') {
              alert('请输入正确的价格')
              return
            }
            //发送添加请求
            const res = await axios.post('https://applet-base-api-t.itheima.net/bill',{
              creator: '小智',
              name: this.name,
              price: this.price
            })
            //重新渲染
            this.getList(),

            this.name = '',
            this.price = ''
          },
          async del(id) {
            // this.list = this.list.filter(item => item.id !== id)
            //根据id发送删除请求
            const res = await axios.delete(`https://applet-base-api-t.itheima.net/bill${id}`)
            this.getList() 
          }
        }
      })
    </script>
  </body>