1. 程式人生 > 實用技巧 >vue專案 資料更新非同步問題處理

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包裝成非同步。