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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM