【问题标题】:Vue.js - Reactivity component, not always re-renderingVue.js - 反应性组件,并不总是重新渲染
【发布时间】:2017-05-19 17:18:38
【问题描述】:

我面临两个组件 line-chartbar-chart 的反应性问题

当我将复选框值链接更改为v-model="formChart.type 时,组件line-chartbar-chart 会自动重新渲染。

但是当我点击触发函数submitFormbutton,然后点击generateChart()resetTypeChart()时,这些组件不会重新渲染。

mounted() 函数未触发。

我真的不明白为什么会发生这种情况,因为我正在重置 typeshow...。我尝试使用或不使用 Vue.set 都没有改变。

代码确实进入了resetTypeChart() 函数


组件并不总是重新渲染

  <div class="chart-container">
      <line-chart v-if="formChart.type === 'line_chart' && formChart.show" :chartData="dataChart" ref="lineChart"></line-chart>
      <bar-chart v-if="formChart.type === 'bar_chart' && formChart.show" :chartData="dataChart" ref="barChart"></bar-chart>
  </div>

用于更改图表类型的复选框

<el-radio-group size="small" v-model="formChart.type">
     <el-radio-button label="line_chart"> Line Chart </el-radio-button>
     <el-radio-button label="bar_chart"> Bar Chart </el-radio-button>
</el-radio-group>

生成图表的按钮

<el-button type="primary" size="large"@click="submitForm('formChart')">Generate</el-button>

submitForm(formName) {
   this.$refs[formName].validate((valid) => {
      this.generateChart();
      this.resetTypeChart();
   } 
});

重置图表的功能(可以尝试)

resetTypeChart () {
  const saveType = this.formChart.type;
  this.formChart.type = '';
  this.formChart.show = false;
  Vue.set(this.formChart, 'type', saveType);
  this.formChart.type = saveType;
  this.formChart.show = true;
 }

JSFIDDLE

  • 切换到Bar Chart,组件就生成了
  • 点击Generate,同时仍然在同一个单选按钮上。没有显示任何内容。

https://jsfiddle.net/rd3ahxp8/3/

【问题讨论】:

  • 您并没有真正改变resetTypeChart 中的任何内容。这并不是说 Vue 在你将 show 设置为 false 和返回 true 的时间之间跑掉并做任何事情。功能完成后,then 它将查看是否需要做某事,在这种情况下,我认为它不会看到任何更改。您能否提供一个工作示例,让我们可以看到您正在尝试解决的问题?
  • 我会尝试做一个例子,但这并不容易......你如何解释更改复选框以便formChart.type在链接到@987654345时重新呈现组件@ 但不是当我在做this.formChart.type = '' 然后`this.formChart.type = ''bar_chart"`
  • 因为 DOM 更新发生在 asynchronously。如果您只是单击单选按钮,那么 Vue 就有时间运行下一个异步 DOM 更新。但是更新不会在您的方法执行过程中运行。
  • 我创建了一个jsfiddle,比我预期的更简单。如果你切换radio button它会显示bar chart generated如果你点击生成它不会显示它

标签: javascript charts vue.js vuejs2


【解决方案1】:

单击生成按钮时没有看到警报的原因是因为 Vue 已经确定没有任何变化,因此它不需要更新 DOM。正如我在上面的 cmets 中所说,Vue DOM 更新是异步发生的,这意味着 Vue 不会检查是否有任何变化,直到您的方法完成之后。当你的方法完成时,你的状态并没有真正改变;您将其设置为某个值,然后将其设置回原始值。

为了演示 I modified your fiddle 并在清除值和将它们设置回的时间之间引入了时间延迟。您可以看到,在 这种 情况下,Vue 有时间检查值是否已更改,然后它们会更改返回,您会收到消息。

generateChart : function () {
    alert('generate')
    const saveType = this.formChart.type;
    this.formChart.type = '';
    this.formChart.show = false;
    setTimeout(()=>{
        this.formChart.type = saveType;
      this.formChart.show = true;

    }, 1000)
}

我认为 应该 在您的情况下触发更新是对 dataChart 的一些更改。当该值更改时,您的 Vue 应该重新渲染。然而,你并没有表明它会改变。现在,如果数据没有改变,并且您不希望用户看到 不同 图表(因为您将其设置回相同的值),为什么要在全部?

为了让您的图表在 chartData 更改时重新呈现,您应该注意组件中的 chartData 属性。这是一个完整的示例,说明我可以如何做到这一点。

const ChartBase = {
  props: ["chartData"],
  methods:{
    showChart(){
      this.renderChart({
        labels: this.chartData.labels,
        datasets: [
          {
            label: 'Data One',
            backgroundColor: '#f87979',
            data: this.chartData.data
          }
        ]
      }, {responsive: true, maintainAspectRatio: false})
    }
  },
  mounted : function () {
    this.showChart()
    this.$watch("chartData.data", this.showChart)
  },
}

Vue.component('bar-chart', {
  extends: VueChartJs.Bar,
  mixins: [ChartBase]
});

Vue.component('line-chart', {
  extends: VueChartJs.Line,
  mixins:[ChartBase]
});

var Main = {
  data () {
    return {
      formChart : {
        type : 'line_chart',
        show : false,
      },
      chartData:{
        labels:['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        data: [40, 39, 10, 40, 39, 80, 40]
      }
    };
  },
  methods : {
    generateChart : function () {
      const newChartData = [...this.chartData.data.reverse()] 
      this.chartData.data = newChartData
    }
  },
}

generate 按钮被点击时,here is a fiddle 显示图表的变化。

【讨论】:

  • 依赖setTimeout 不是有风险吗? $nextTick 呢?
  • @Leo 我并不是建议您将其作为您问题的解决方案;我试图证明为什么你会看到你所看到的行为。我认为应该真正触发你重新渲染的应该是对dataChart的更改。
  • dataChartgenerateChart() 中进行了修改 考虑到我还需要考虑图表的type 以显示其中一个或另一个,您的方法是什么?
  • 这是一个fiddle 演示我将如何做到这一点。
  • 如果您只是想在第一次点击generate 时查看图表,您不需要v-if 中的其他内容吗?
猜你喜欢
  • 2020-03-08
  • 2019-03-02
  • 2018-12-27
  • 2018-09-19
  • 1970-01-01
  • 2018-10-07
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多