zoukankan      html  css  js  c++  java
  • 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>
  • 相关阅读:
    1.1、MyEclipse自定义注释
    angular2 组件内容嵌入(ng-content)
    常用css初始化样式(淘宝)
    web移动端rem的适配
    PSCC2019常用基础操作
    vs Code打开新的文件会覆盖窗口中的文件?
    关于将ECharts引入到项目中的几种方式
    VS code 设置侧边栏字体大小
    Visual Studio Code(VS code)你们都在用吗?或许你们需要看一下这篇博文
    Angular 监听滚动条事件
  • 原文地址:https://www.cnblogs.com/MR-cui/p/14001203.html
Copyright © 2011-2022 走看看