Vue:实战中一个关于 watch 的问题

题目描述

这是我在 Github 上 Clone 的一位大牛的项目,用来学习下

...
export default {
  props: ['sevenData', 'sevenDay'],
  mounted () {
    this.myChart = echarts.init(document.getElementById('line1'))
    this.initData()
  },
  methods: {
    initData () {
      const colors = ['#5793f3', '#675bba', '#d14a61']
      // 配置
      const options = {
        // 调色盘颜色列表,如果系列没有设置颜色,则会依次循环从该列表中取颜色作为系列颜色。
        color: colors,
        // 标题组件
        title: {
          // 主标题
          text: '走势图',
          // 副标题文本
          subtext: '这是副标题'
        },
        // 提示框组件
        tooltip: {
          // 触发类型: 坐标轴触发
          trigger: 'axis'
        },
        // 图例组件
        legend: {
          // 图例的数据数组
          data: ['新注册用户', '新增订单', '新增管理员']
        },
        // 工具栏
        toolbox: {
          // 是否显示工具栏
          show: true,
          // 各工具配置项
          feature: {
            // 数据区域缩放
            dataZoom: {
              // 指定哪些 y 轴可以被控制
              yAxisindex: 'none'
            },
            // 数据视图工具,可以展现当前图表所用的数据,编辑后可以动态更新。
            dataView: {readOnly: false},
            magicType: {type: ['bar', 'line']},
            restore: {}
          }
        },
        // 直角坐标系 grid 中的 x 轴
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: this.sevenDay
        },
        yAxis: [
          {
            type: 'value',
            name: '用户',
            min: 0,
            max: 200,
            position: 'left',
            axisLine: {
              lineStyle: {
                color: '#999'
              }
            },
            axisLabel: {
              formatter: '{value}'
            }
          },
          {
            type: 'value',
            name: '订单',
            min: 0,
            max: 200,
            position: 'right',
            axisLine: {
              lineStyle: {
                color: '#999'
              }
            },
            axisLabel: {
              formatter: '{value}'
            }
          }
        ],
        series: [
          {
            name: '新注册用户',
            type: 'line',
            data: this.sevenData[0],
            yAxisIndex: 1,
            markPoint: {
              data: [
                {type: 'max', name: '最大值'},
                {type: 'min', name: '最小值'}
              ]
            }
          },
          {
            name: '新增订单',
            type: 'line',
            data: this.sevenData[1],
            yAxisIndex: 1,
            markPoint: {
              data: [
                {type: 'max', name: '最大值'},
                {type: 'min', name: '最小值'}
              ]
            }
          },
          {
            name: '新增管理员',
            type: 'line',
            data: this.sevenData[2],
            yAxisIndex: 1,
            markPoint: {
              data: [
                {type: 'max', name: '最大值'},
                {type: 'min', name: '最小值'}
              ]
            }
          }
        ]
      }
      this.myChart.setOption(options)
    }
  }
}

添加数据侦听:

  watch: {
    sevenData: function () {
      this.initData()
    },
    sevenDay: function () {
      this.initData()
    }
  }

问:

为什么我不加 watch ,通过父组件传过来的 props 里面的数据不显示?
按我的理解:props 不是在 beforeCreatedcreated 之间就有了嘛?
那挂载 DOM 的时候为什么没有数据?

附:

添加 watch 之前:

clipboard.png

添加 watch 之后

clipboard.png

有兴趣的可以看下源码 ,在 tendency 组件中,欢迎各位小伙伴儿学习讨论。

阅读 1.6k
2 个回答

问题解决了:
根本原因在于异步请求不会阻塞 Vue 的生命周期。
和父子组件的生命周期也有关系:父组件创建->子组件创建->子组件挂载->父组件挂载
所以如果不想用 watch,就用 v-if 来控制子组件的创建,当异步请求结束时再创建子组件,这样得到的子组件就拥有父组件请求的所有数据了。
仔细想了以下:还是用 watch 好,不用 watch 的话相当于异步操作阻塞了子组件的生命周期,那么响应时间就增加了。

如果我理解的有偏差,欢迎指出,谢谢。

数据挂载上去的时候可能那个值还是空的,这时候生命周期可能都走完了,而初始化的方法里面需要这个值,所以需要watch他来初始化

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题