vue项目 数据更新异步问题处理

 <el-dropdown
          trigger="click"
          :hide-on-click="false"
          @command="handleGroup"
        >
          <el-button type="default " :disabled="codeArray.length === 1">
            显示分组
            <i class="el-icon-arrow-down el-icon--right"></i>
          </el-button>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item v-for="(item, key) in columnList" :key="key">
              <el-checkbox v-model="item.show">{{ item.name }}</el-checkbox>
            </el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>

 

export default {
  data() {
    return {
      indicatorProps: {
        label: "name",
        value: "code"
      },
      props: {
        label: "name",
        value: "code",
        emitPath: false,
        disabled: "disabled"
      },
      indicatorSelectList: [{ property: [] }],
      indicatorOptions: [],
      indicatorFlatArray: [],
      indicatorName: "",
      userOptions: [], // 用户属性 指标  data
      userFlatArray: [], // 用户属性data拉平children
      codeArray: [], // 属性分析分组集合
      codeNameArr: [], // [{name:"",code:""}]
      codeNameObj: {}, // {code:name}
      codeNameStr: "", // 属性分析分组名称集合
      dropdownUserType: "", // 属性值下拉选中值
      memberForm: {
        indicator: ""
      },
      columnList: [], // 显示分组数组
      chartType: "1", // 图标类型 1:线图 2:柱图 3:饼图
      chartTypeList: [
        {
          id: "1",
          name: "线图",
          icon: "line"
        },
        {
          id: "2",
          name: "柱图",
          icon: "chart"
        },
        {
          id: "3",
          name: "饼图",
          icon: "pie"
        }
      ],
      barChart: {},
      popover: false,
      legendData: ["82~84", "邮件营销", "联盟广告", "视频广告"],
      xDataArray: ["白银", "青铜", "黄金"],
      series: [
        {
          name: "直接访问",
          type: "bar",
          stack: "barchart",
          barWidth: 30,
          data: [320, 332, 301, 334, 390, 330, 320]
        },
        {
          name: "邮件营销",
          type: "bar",
          barWidth: 30,
          stack: "barchart",
          data: [120, 132, 101, 134, 90, 230, 210]
        },
        {
          name: "联盟广告",
          type: "bar",
          barWidth: 30,
          stack: "barchart",
          data: [220, 182, 191, 234, 290, 330, 310]
        }
      ],
      headers: [""],
      detailObj: {},
      lineChart: {},
      lineSeries: [],
      pieChart: {},
      pieObj: {},
      peiLegendData: []
    };
  },
  created() {
    this.getEventIndicator();
    this.getUserIndicator();
    // this.getChartList()
    this.createFalseData();
  },
  methods: {
    createFalseData() {
      const rows = [
        {
          values: [[339532.0], [340507.0], [351192.0], [1090.0]],
          by_values: ["北京", "女"]
        },
        {
          values: [[337168.0], [345011.0], [334602.0], [854.0]],
          by_values: ["深圳", "女"]
        },
        {
          values: [[339814.0], [342683.0], [348465.0], [851.0]],
          by_values: ["深圳", "男"]
        },
        {
          values: [[324703.0], [330292.0], [342045.0], [849.0]],
          by_values: ["合肥", "女"]
        },
        {
          values: [[330686.0], [337726.0], [343880.0], [848.0]],
          by_values: ["杭州", "男"]
        },
        {
          values: [[344871.0], [332696.0], [337733.0], [828.0]],
          by_values: ["合肥", "男"]
        },
        {
          values: [[334726.0], [339059.0], [328708.0], [812.0]],
          by_values: ["石家庄", "女"]
        },
        {
          values: [[334403.0], [336552.0], [344020.0], [752.0]],
          by_values: ["上海", "女"]
        },
        {
          values: [[339284.0], [339942.0], [336175.0], [657.0]],
          by_values: ["北京", "男"]
        },
        {
          values: [[338436.0], [340759.0], [340111.0], [619.0]],
          by_values: ["杭州", "女"]
        },
        {
          values: [[344290.0], [331236.0], [335737.0], [570.0]],
          by_values: ["上海", "男"]
        },
        {
          values: [[339751.0], [339188.0], [341085.0], [570.0]],
          by_values: ["石家庄", "男"]
        },
        {
          values: [[5637.0], [5987.0], [5936.0], [97.0]],
          by_values: ["上海", null]
        },
        {
          values: [[6656.0], [5532.0], [6611.0], [93.0]],
          by_values: ["杭州", null]
        },
        {
          values: [[5915.0], [6339.0], [4772.0], [85.0]],
          by_values: ["深圳", null]
        },
        {
          values: [[6476.0], [6182.0], [4672.0], [0.0]],
          by_values: ["北京", null]
        },
        {
          values: [[4821.0], [6108.0], [5614.0], [0.0]],
          by_values: ["合肥", null]
        },
        {
          values: [[6073.0], [5155.0], [4580.0], [0.0]],
          by_values: ["石家庄", null]
        },
        {
          values: [[0.0], [0.0], [0.0], [0.0]],
          by_values: [null, "男"]
        },
        {
          values: [[0.0], [0.0], [0.0], [0.0]],
          by_values: [null, null]
        }
      ];
      const series = ["白银", "青铜", "黄金", null];
      rows.map(item => {
        const key = item.by_values.join(",");
        this.detailObj[key] = item.values.flat();
      });
      this.legendData = rows.map(item => item.by_values.join(","));
      this.peiLegendData = rows.map(item => item.by_values.join(","));
      this.xDataArray = series;
      // 组装饼图数据
      const pieObj = {};
      for (let i = 0; i < series.length; i++) {
        for (let j = 0; j < this.peiLegendData.length; j++) {
          const key = `${series[i]},${this.peiLegendData[j]}`;
          const value = this.detailObj[this.peiLegendData[j]][i];
          pieObj[key] = value;
        }
      }
      this.pieObj = pieObj;
      // 显示分组
      this.columnList = Object.keys(this.detailObj).map(item => {
        return {
          name: item,
          show: false
        };
      });
      for (let i = 0; i < 10; i++) {
        this.columnList[i].show = true;
      }
      console.log(this.columnList);

      this.initCharts();
    },
    async getChartList() {
      const res1 = await getTableInfo({
        tagId: 20,
        pageSize: 10,
        pageNum: 1,
        nums: "",
        total: 0
      });
      if (res1.code === 0) {
        const result = res1.data;
        this.headers = result.headers;
      }
      const res = await getCustomerDis({ nums: "", tagId: 20 });
      if (res.code === 0) {
        // 标签历史详情
        this.detailObj = res.data.detail;
        this.legendData = Object.keys(res.data.detail);
        const xDataArray = [...this.headers];
        xDataArray.shift();
        this.xDataArray = xDataArray;
        const series = [];
        for (let i = 0; i < this.legendData.length; i++) {
          const obj = {
            name: this.legendData[i],
            type: "bar",
            barWidth: 30,
            stack: "barChart",
            data: this.detailObj[this.legendData[i]].nums
          };
          series.push(obj);
        }
        const lineSeries = [];
        for (let i = 0; i < this.legendData.length; i++) {
          const obj = {
            name: this.legendData[i],
            type: "line",
            // stack: 'lineChart',
            symbol: "circle", // 设定为实心点
            symbolSize: 2, // 设定实心点的大小
            data: this.detailObj[this.legendData[i]].nums
          };
          lineSeries.push(obj);
        }
        this.series = series;
        this.lineSeries = lineSeries;
        // 显示设置
        this.columnList = Object.keys(res.data.detail).map(item => {
          return {
            name: item,
            show: true
          };
        });
        this.initCharts();
      }
    },
    // 上面假接口
    indicatorChange() {
      const indicatorArr = this.memberForm.indicator;
      const indicatorFlatArray = this.indicatorFlatArray;
      let indicatorName = "";
      for (let i = 0; i < indicatorArr.length; i++) {
        for (let j = 0; j < indicatorFlatArray.length; j++) {
          if (indicatorFlatArray[j].code === indicatorArr[i]) {
            if (!indicatorName) {
              indicatorName = indicatorFlatArray[j].name;
            } else {
              indicatorName = `${indicatorName}的${indicatorFlatArray[j].name}`;
            }
          }
        }
      }
      this.indicatorName = indicatorName;
    },
    // userOption 初始disabled 为False
    userDisableFun() {
      const userOptions = this.userOptions;
      const _this = this;
      function userFn(userOption) {
        if (userOption.children) {
          for (let i = 0; i < userOption.children.length; i++) {
            _this.$set(userOption.children[i], "disabled", false);
            userFn(userOption.children[i]);
          }
        }
      }
      for (let i = 0; i < userOptions.length; i++) {
        this.$set(userOptions[i], "disabled", false);
        userFn(userOptions[i]);
      }
    },
    setAbleFun() {
      const userOptions = this.userOptions;
      this.codeArray = this.indicatorSelectList.map(item => item.property);
      function userDisableFn(code, userOptions) {
        if (userOptions.children) {
          for (let n = 0; n < userOptions.children.length; n++) {
            userDisableFn(code, userOptions.children[n]);
          }
        } else if (code === userOptions.code) {
          userOptions.disabled = true;
        }
      }
      for (let i = 0; i < this.codeArray.length; i++) {
        for (let j = 0; j < userOptions.length; j++) {
          userDisableFn(this.codeArray[i], userOptions[j]);
        }
      }
    },
    setCodeName() {
      const codeArr = this.indicatorSelectList.map(item => item.property);
      const codeNameArr = [];
      for (let i = 0; i < codeArr.length; i++) {
        let obj = {
          name: "",
          code: ""
        };
        for (let j = 0; j < this.userFlatArray.length; j++) {
          if (codeArr[i] === this.userFlatArray[j].code) {
            obj = {
              code: this.userFlatArray[j].code,
              name: this.userFlatArray[j].name
            };
          }
        }
        codeNameArr.push(obj);
      }
      this.codeNameArr = codeNameArr;
      this.codeNameObj = {};
      codeNameArr.map(item => {
        this.codeNameObj[item.code] = item.name;
      });
      this.codeNameStr = codeNameArr.map(item => item.name).join(",");
    },
    async cascaderChange(item, index) {
      this.dropdownUserType = this.indicatorSelectList[0].property;
      this.userDisableFun();
      this.setCodeName();
      this.setAbleFun();
    },
    async getUserIndicator() {
      const res = await getIndicatorSelect({ indicatorGroupId: 1 });
      if (res.code === 0) {
        const userArr = res.data;
        // 对用户标签及群组保留children,其他属性删除二级属性
        const persist = ["user_tag_group_header", "user_group_header"];
        for (let i = 0; i < userArr.length; i++) {
          if (userArr[i].children && !persist.includes(userArr[i].code)) {
            userArr[i].children = [];
          }
        }
        flatArrayFun(userArr, this.userFlatArray);
        delArrChildren(userArr);
        this.userOptions = userArr;
      }
    },
    // 删除用户指标属性
    removeUserIndicator(index) {
      this.indicatorSelectList.splice(index, 1);
      this.cascaderChange();
    },
    // 新增用户指标属性
    addUserIndicator() {
      this.indicatorSelectList.push({ property: [] });
    },
    async getEventIndicator() {
      const result = await getBasicEventIndicator();
      if (result.code === 0) {
        const indicatorArr = result.data.resultIndicatorTree;
        indicatorArr.unshift({
          name: "用户数",
          code: "userCount",
          dataType: "indicator",
          children: []
        });
        flatArrayFun(indicatorArr, this.indicatorFlatArray);
        delArrChildren(indicatorArr);
        this.indicatorOptions = indicatorArr;
      }
    },
    // chart
    async initCharts() {
      await this.$nextTick();
      this.barChart = echarts.init(document.getElementById("barChart"));
      this.lineChart = echarts.init(document.getElementById("lineChart"));
      this.pieChart = echarts.init(document.getElementById("pieChart"));
      switch (this.chartType) {
        case "1":
          this.setLineOption();
          break;
        case "2":
          this.setBarOption();
          break;
        default:
          this.setPieOption();
          break;
      }
    },
    setBarLineParams() {
      // this.legendData = this.columnList
      //   .filter(item => item.show)
      //   .map(item => item.name);
      const legendData = [];
      console.log(JSON.stringify(this.columnList), "this.columnList"); 
      console.log(this.columnList[0].show, "this.columnList");
      for (let i = 0; i < this.columnList.length; i++) {
        if (this.columnList[i].show === true) {
          legendData.push(this.columnList[i].name);
        }
      }
      console.log(legendData);
      this.legendData = legendData;
      const barSeries = [];
      const lineSeries = [];
      for (let i = 0; i < this.legendData.length; i++) {
        const obj = {
          name: this.legendData[i],
          type: "bar",
          barMaxWidth: 80,
          stack: "barChart",
          data: this.detailObj[this.legendData[i]]
        };
        const lineObj = {
          name: this.legendData[i],
          type: "line",
          // stack: 'lineChart',
          symbol: "circle", // 设定为实心点
          symbolSize: 8, // 设定实心点的大小
          data: this.detailObj[this.legendData[i]]
        };
        barSeries.push(obj);
        lineSeries.push(lineObj);
      }
      this.barSeries = barSeries;
      this.lineSeries = lineSeries;
      // console.log(this.lineSeries);
    },
    setPieParams() {
      this.pieData = this.columnList
        .filter(item => item.show)
        .map(item => {
          return {
            name: item.name,
            value: item.value
          };
        });
    },
    setBarOption() {
      this.setBarLineParams();
      this.barChart.setOption(
        {
          tooltip: {
            trigger: "item",
            axisPointer: {
              // 坐标轴指示器,坐标轴触发有效
              type: "shadow" // 默认为直线,可选为:'line' | 'shadow'
            },
            formatter: function(params) {
              var res = `${params.name}<br/>`;
              res += `${params.seriesName} : ${params.value}`;
              return res;
            }
          },
          grid: {
            left: "3%",
            right: "4%",
            bottom: "15%",
            containLabel: true
          },
          legend: {
            data: this.legendData,
            orient: "horizontal", // 'vertical'
            x: "center", // 'center' | 'left' | {number},
            y: "bottom" // 'center' | 'bottom' | {number}
          },
          xAxis: [
            {
              type: "category",
              data: this.xDataArray
            }
          ],
          yAxis: [
            {
              type: "value",
              axisLabel: {
                formatter: value => {
                  return value;
                }
              }
            }
          ],
          series: this.barSeries
        },
        true
      );
    },
    setLineOption() {
      this.setBarLineParams();
      this.lineChart.setOption(
        {
          tooltip: {
            trigger: "item",
            formatter: function(params) {
              var res = `${params.name}<br/>`;
              res += `${params.seriesName} : ${params.value}`;
              return res;
            }
          },
          legend: {
            orient: "horizontal", // 'vertical'
            x: "center", // 'center' | 'left' | {number},
            y: "bottom", // 'center' | 'bottom' | {number}
            data: this.legendData
          },
          xAxis: {
            type: "category",
            data: this.xDataArray
          },
          yAxis: {
            type: "value"
          },
          series: this.lineSeries
        },
        true
      );
    },
    setPieOption() {
      this.setPieParams();
      const indicatorName = this.indicatorName || "用户数";
      this.pieChart.setOption(
        {
          tooltip: {
            trigger: "item",
            formatter: "{a} <br/>{b}: {c} ({d}%)"
          },
          series: [
            {
              name: indicatorName,
              type: "pie",
              radius: ["50%", "70%"],
              // avoidLabelOverlap: false,
              // label: {
              //   show: false,
              //   position: 'center'
              // },
              emphasis: {
                label: {
                  show: true,
                  fontSize: "30",
                  fontWeight: "bold"
                }
              },
              labelLine: {
                show: true
              },
              data: this.pieData
            }
          ]
        },
        true
      );
    },
    // 显示分组
    handleGroup() {
      // setTimeout(() => {
      switch (this.chartType) {
        case "1":
          this.setLineOption();
          setTimeout(() => {
            this.lineChart.resize();
          });
          break;
        case "2":
          this.setBarOption();
          setTimeout(() => {
            this.barChart.resize();
          });
          break;
        case "3":
          this.setPieOption();
          setTimeout(() => {
            this.pieChart.resize();
          });
          break;
      }
      // });
      console.log(this.chartType, "chartType");
    },
    handleChartType(command) {
      if (this.chartType === command) return;
      // 由柱图或者线图切换为饼图
      if (this.chartType !== "3" && command === "3") {
        this.columnList = Object.keys(this.pieObj).map(key => {
          return {
            value: this.pieObj[key],
            name: key,
            show: false
          };
        });
        for (let i = 0; i < 10; i++) {
          this.columnList[i].show = true;
        }
      }
      // 由饼图切换为柱图或者线图
      if (this.chartType === "3" && command !== "3") {
        this.columnList = Object.keys(this.detailObj).map(item => {
          return {
            name: item,
            show: false
          };
        });
        for (let i = 0; i < 10; i++) {
          this.columnList[i].show = true;
        }
      }
      this.chartType = command;
      switch (command) {
        case "1":
          this.setLineOption();
          setTimeout(() => {
            this.lineChart.resize();
          });
          break;
        case "2":
          this.setBarOption();
          setTimeout(() => {
            this.barChart.resize();
          });
          break;
        case "3":
          this.setPieOption();
          setTimeout(() => {
            this.pieChart.resize();
          });
          break;
      }
      // this.initCharts()
    },
    // 属性值下拉
    handleUserOption(command) {
      this.dropdownUserType = command;
    }
  }
};

图示中执行handleGroup方法时,el-checkbox状态其实有个延迟,所以打印出来是, 为了验证,用JSON.stringfy做了下处理,因为el-checkbox会有延迟,如果不做处理,打印出来的会动态变为false,通过处理,可以发现此时打印出来show的状态仍然是true,为了解决这个问题,把handleGroup用settimeOut包装成异步。

第二种方法就是使用computed

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
  <div id="app">
      <div>
            <el-dropdown
            trigger="click"
            :hide-on-click="false"
            <!-- @command='handleGroups' -->
        >
            <el-button type="default " >
            显示分组
            <i class="el-icon-arrow-down el-icon--right"></i>
            </el-button>
            <el-dropdown-menu slot="dropdown">
            <el-dropdown-item v-for="(item, key) in columnList" :key="key">
                <el-checkbox v-model="item.show">{{ item.name }}</el-checkbox>
            </el-dropdown-item>
            </el-dropdown-menu>
        </el-dropdown>
        <span>选中的名称:{{selectName}}</span>
      </div>
              
  </div>
</body>
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <script>
    new Vue({
        el: '#app',
        data(){
            return{
                columnList:[
                    {
                        name:"",
                        show:false
                    },
                    {
                        name:"",
                        show:false
                    },
                    {
                        name:"未知",
                        show:false
                    },
                ]
            }
        },
        computed: {
            selectName() {
                this.handleGroups()
                return this.columnList.filter(item=>item.show).map(item=>item.name);
            }
        },
        methods:{
            // handleGroups(){
            //     console.log(JSON.stringify(this.columnList))
            // }
        }
    })
  </script>
</html>

 

posted @ 2020-11-18 17:44  MR崔  阅读(1423)  评论(0编辑  收藏  举报