Javascript Vue.js-反应性组件,不总是重新渲染

Javascript Vue.js-反应性组件,不总是重新渲染,javascript,charts,vue.js,vuejs2,Javascript,Charts,Vue.js,Vuejs2,我面临两个组件的反应性问题折线图和条形图 当我将复选框值链接更改为v-model=“formChart.type时,组件折线图和条形图将自动重新呈现 但是当我点击触发函数submitForm的按钮时,然后generateChart()和resetTypeChart()这些组件不会被重新渲染 未触发mounted()功能 我真的不明白为什么会发生这种情况,因为我正在重置类型和显示…我尝试使用或不使用Vue.set没有任何更改 代码进入resetTypeChart()函数 组件不总是重新渲染 JS

我面临两个组件的反应性问题
折线图
条形图

当我将复选框值链接更改为
v-model=“formChart.type
时,组件
折线图
条形图
将自动重新呈现

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

未触发
mounted()
功能

我真的不明白为什么会发生这种情况,因为我正在重置
类型
显示
…我尝试使用或不使用
Vue.set
没有任何更改

代码进入
resetTypeChart()
函数


组件不总是重新渲染 JSFIDLE
  • 切换到
    条形图
    ,生成组件
  • 单击
    Generate
    ,同时仍在同一个单选按钮上。不显示任何内容

单击“生成”按钮时未看到警报的原因是,Vue已确定没有任何更改,因此不需要更新DOM。正如我在上面的评论中所说,Vue DOM更新是异步进行的,这意味着Vue在您单击“生成”按钮之前不会检查是否有任何更改thod已完成。当您的方法完成时,您的状态中没有任何更改;您将其设置为某个值,然后将其设置回原始值

要演示并引入从清除值到设置值之间的时间延迟。您可以看到,在本例中,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
    }
  },
}

单击“生成”
按钮时显示图表的更改。

您在“重置类型图表”中并没有真正更改任何内容。这并不是说Vue在设置“显示为false”和“返回为true”之间运行并执行任何操作。函数完成后,它将查看是否需要执行某些操作,在这种情况下案例,我不认为它会改变。你能做一个工作示例,让我们看到你试图解决的问题吗?我会尝试做一个示例,但这并不容易…你如何解释更改复选框以便
formChart.type
在组件链接到
v-model
时重新渲染组件,而不是在我执行
this.formChart.type='
然后执行`this.formChart.type=''bar\u chart',因为DOM会更新。如果您只需单击单选按钮,那么Vue就有时间运行下一个异步DOM更新。但是更新并不会在执行方法的中间运行。我创建了一个<代码> jsFoDeld比我预期的要简单。如果您切换
单选按钮
,它将显示
生成的条形图
,如果您单击“生成”,它将不会显示它依靠
设置超时
?那么,
$nextTick
呢?@Leo我不是建议用它来解决你的问题;我试图证明你为什么会看到你所看到的行为。我认为真正触发重新渲染的应该是对
dataChart
的更改
dataChart
generateChart()中被修改你的方法是什么?考虑到我也需要考虑图表的<代码>类型>代码>来显示一个或另一个。这里是一个演示我将如何做它。如果你只是想看到一个图表,当你第一次点击<代码>生成< /代码>你不需要别的东西在<代码> V-IF <代码>吗?
<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;
 }
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)
}
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
    }
  },
}