03-vue第三天学习笔记

1. vue生命周期
1.1 生命周期的顺序
  1. 创建阶段:响应式数据
  2. 挂载阶段:渲染模板
  3. 更新阶段:修改数据,更新视图
  4. 销毁阶段:销毁实例
1.2 生命周期钩子函数
  1. 创建阶段:beforeCreate()创建前,created()创建后,可以在此时发起请求
  2. 挂载阶段:beforeMount()渲染前,mounted()渲染后,在此时可以操作dom
  3. 更新阶段:beforeUpdate()更新前,updated()更新后
  4. 销毁阶段:beforeDestroy()销毁前,可以先清除定时器,延时器等,destroy()销毁后
<!-- created应用-发起请求,获取数据进行渲染 -->
<div id="app">
    <ul>
      <li v-for="(item,index) in list" :key="item.id" class="news">
        <div class="left">
          <div class="title">{{ item.title }}</div>
          <div class="info">
            <span>{{ item.source }}</span>
            <span>{{ item.time }}</span>
          </div>
        </div>
        <div class="right">
          <img :src="item.img" alt="">
        </div>
      </li>
    </ul>
  </div>
  <script src="./vue.js"></script>
  <script src="./axios.js"></script>
  <script>
    // 接口地址:http://hmajax.itheima.net/api/news
    // 请求方式:get
    const app = new Vue({
      el: '#app',
      data: {
        list: []
      },
      async created() {
        const res = await axios.get('http://hmajax.itheima.net/api/news')
        this.list = res.data.data
      }
    })
  </script>

  <!-- mounted应用-输入框自动获取焦点 -->
  <div class="container" id="app">
  <div class="search-container">
    <img src="https://www.itheima.com/images/logo.png" alt="">
    <div class="search-box">
      <input type="text" v-model="words" id="inp">
      <button>搜索一下</button>
    </div>
  </div>
</div>

<script src="./vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      words: ''
    },
    mounted() {
      document.querySelector('#inp').focus()
    }
  })
</script>
小黑记账清单
<div id="app">
      <div class="contain">
        <!-- 左侧列表 -->
        <div class="list-box">

          <!-- 添加资产 -->
          <form class="my-form">
            <input v-model="name" type="text" class="form-control" placeholder="消费名称" />
            <input v-model="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="../echarts.min.js"></script>
    <script src="../vue.js"></script>
    <script src="../axios.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() {
          this.getList()
        },
        mounted() {
          //获取容器
          this.myecharts = echarts.init(document.querySelector('#main'))
          //配置项
          this.myecharts.setOption(
            {
            title: {
              text: '消费账单列表',
              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.myecharts.setOption({
              series: [
              {
                data : this.list.map(item => ({ value : item.price, name : item.name}))
              }
            ]
            })
          },
          async add() {
            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) {
            const res = await axios.delete(`https://applet-base-api-t.itheima.net/bill/${id}`)
            this.getList()
          }
        }
      })
    </script>
2. 工程化开发
  1. 概念:基于构建工具的环境中开发vue

  2. 快速构建工具vue cli脚手架,集成了webpack配置,无需手动配置

  3. 组件化开发:将页面拆分成一个又一个组件,从而方便复用以及查找问题根源

    1. 普通组件的注册-局部注册:创建.vue文件,在使用的组件内进行导入注册。局部注册只能在注册的组件内使用
    2. 全局注册:在main.js文件中进行导入注册,之后全局组件可以在所有组件中使用
  4. 组件的三大组成部分:结构template,样式style,逻辑script

    1. 样式style在组件中默认为全局样式,为了避免组件与组件的样式冲突,可以使用scoped属性将style设置为局部样式,只影响组件内的样式。
    2. 逻辑script中,data必须是一个函数,从而方便维护数据的独立性,避免相互影响
2.1 组件通信
  1. 组件关系分为父子关系和非父子关系,通信方式各不相同
2.1.1 父子组件通信
  1. 父组件向子组件进行数据传递:

    1. 在子组件标签上添加属性,赋值
    2. 子组件通过props属性进行获取
    3. 子组件通过插值表达式进行使用
  2. 子组件向父组件进行传值

    1. 在按钮上绑定点击事件,在事件中通过$emit发送消息通知事件
    2. 父组件通过消息事件绑定处理函数,从而获取数据,处理逻辑
2.1.2 props
  1. props就是子组件标签上的自定义属性
  2. props校验
// 1.基础写法(类型校验)
  props: {
    w: Number,
  },

  // 2.完整写法(类型、默认值、非空、自定义校验)
  props: {
    w: {
      type: Number,//类型
      required: true,//非空
      default: 0,//默认值
      validator(val) { //自定义校验
        if (val >= 100 || val <= 0) {
          console.error('传入的范围必须是0-100之间')
          return false
        } else {
          return true
        }
      },
    },
  },
  1. props和data的区别:data是自己的,随便改;props是外部的,不能直接更改,需要通过父子组件通信的方式修改
2.1.3 非父子组件通信
  1. 事件总线EventBus

    1. 创建事件总线js文件,新建空vue实例
    2. 发送方导入vue实例,通过$emit发送消息通知事件
    3. 接收方导入vue实例,通过$on监听消息通知事件,接受信息,完成通信
  2. provide-inject通信

    1. 祖辈组件通过provide函数提供数据(简单数据类型为非响应式,复杂数据类型为响应式)
    2. 孙辈组件通过inject属性接受数据,实现通信
2.1.4 子组件与父组件数据的双向绑定
  1. 通过v-model进行双向绑定

    1. v-model实际是一种语法糖,在应用到输入框时,原理其实是value属性和input事件的整合,从而实现双向绑定,而在封装表单组件时,则可以利用这一原理
    2. 表单组件通过props属性接收父组件传值,再通过子传父的方式通知父组件修改数据
    3. 而当数据的属性名为value,事件名为input时,父组件可以直接通过v-model进行双向绑定,实现子父组件的数据双向绑定
  2. 通过.sync修饰符实现

    1. 在父组件传值时,给属性名加上.sync修饰符,从而使得属性名可以自定义,不需要必须为value
    2. 而子组件要通过给绑定对象对应的事件进行子传父的操作,进行数据传输。如弹框则需绑定update事件
2.1.5 ref和$refs获取dom元素和组件实例
  1. 获取dom元素(在当前组件进行查找,避免类名重复,导致找不到对应dom元素)

    1. 在目标标签上添加ref属性
    2. 通过$refs获取对应目标元素
  2. 获取组件实例

    1. 在目标组件上添加ref属性
    2. 通过$refs获取对应目标组件,获取之后,可以调用目标组件的方法
2.1.6 vue异步更新和$nextTick()
  1. vue采用的是异步更新dom的方式,即在代码执行完之后才会更新dom元素
  2. $nextTick(函数体)的作用就是在dom更新完成之后,再进行执行函数的某些操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值