Vue 计算属性函数永远不会被调用

Posted

技术标签:

【中文标题】Vue 计算属性函数永远不会被调用【英文标题】:Vue computed property functions are never called 【发布时间】:2020-11-22 12:05:55 【问题描述】:

我尝试做自己的Google Science Journal,但是使用 MQTT 协议的 web 版本,但是我的代码有很多错误。

关于我的代码的一些说明:

google.charts.load 在父组件中调用,然后回调调用子组件 time props 是一个区间,每秒在truefalse 之间切换以收集数据。 我需要观察具有多个依赖关系的数据的变化。

我的代码是如何工作的?

    创建新实例时,会出现一个空的谷歌图表 图表开始每秒显示一次数据。 选择了新选项卡时图表更改了图表更改,并且图表数据被删除。

这段代码有问题,是函数调用的顺序(用google chart产生一些问题),但我修复了它,将函数从计算移动到方法并按顺序调用。

我只是想知道为什么这个计算函数不起作用,我的意思是,它们不是从不调用的。

<template>
    <v-card>
        <v-tabs
        v-model="active_tab"
        background-color="red lighten-2"
        dark
        show-arrows
        >
            <v-tab
            v-for="(n) in tabs"
            :key="n.id"
            >
                n.text
                <v-icon>n.icon</v-icon>
            </v-tab>
        </v-tabs>
        <div ref="char_div"></div>
    </v-card>
</template>

<script>
import debounce from 'debounce'

export default 
    name: 'charts',
    props:
        time: 
            type: Boolean,
            default: false
        
    ,
    data()
        return 
            chart: null,
            options: null,
            value: 0,
            previus: null,
            data: null,
            tabs: [
                id: 0, text: "Aceleración lineal", unit: "(m/s&sup2;)", icon: "",
                id: 1, text: "Aceleración en x", unit: "(m/s&sup2;)", icon: "",
                id: 2, text: "Aceleración en y", unit: "(m/s&sup2;)", icon: "",
                id: 3, text: "Aceleración en z", unit: "(m/s&sup2;)", icon: "",
                id: 4, text: "Velocidad lineal", unit: "(m/s)", icon: "",
                id: 5, text: "Luz ambiental", unit: "(lux)", icon: "",
                id: 6, text: "Intensidad sonora", unit: "(dB)", icon: "",
                id: 7, text: "Tono", unit: "(Hz)", icon: "",
                id: 8, text: "Barómetro", unit: "(hPa)", icon: "",
                id: 9, text: "Brujula", unit: "grados", icon: "",
                id: 10, text: "Magnetómetro", unit: "&micro;T", icon: "",
                id: 11, text: "Humedad", unit: "%", icon: "",
                id: 12, text: "Temperatura ambiente", unit: "&deg;C", icon: ""
            ],
            active_tab: 0
        
    ,
    computed: 
        newData: function()
            switch (this.active_tab) 
                case 0:
                    this.value = Math.sqrt(this.$state.lin_acel.x^2 + this.$state.lin_acel.y^2 + this.$state.lin_acel.z^2)
                    break
                case 1:
                    this.value = this.$state.lin_acel.x
                    break
                case 2:
                    this.value = this.$state.lin_acel.y
                    break
                case 3:
                    this.value = this.$state.lin_acel.z
                    break
                case 4:
                    if (this.previus != null)
                        //var cons = Math.sqrt(this.$state.lin_acel.x^2 + this.$state.lin_acel.y^2 + this.$state.lin_acel.z^2)
                        var ax = this.$state.lin_acel.x,
                            ay = this.$state.lin_acel.y,
                            az = this.$state.lin_acel.z

                        var nuevo = Date.now()

                        var vx = ax * ((nuevo - this.previus)/1000),
                            vy = ay * ((nuevo - this.previus)/1000),
                            vz = az * ((nuevo - this.previus)/1000)

                        //this.value += (cons)*((nuevo - this.previus)/1000)
                        this.value += Math.sqrt(vx^2 + vy^2 + vz^2)
                        this.previus = nuevo
                    else
                        this.value = Math.sqrt(this.$state.lin_acel.x^2 + this.$state.lin_acel.y^2 + this.$state.lin_acel.z^2)
                        this.previus = Date.now()
                    
                case 5:
                    this.value = this.$state.lux
                    break
                case 6:
                    this.value = this.$state.noise
                    break
                case 7:
                    this.value = this.$state.noise
                    break
                case 8:
                    this.value = this.$state.presion
                    break
                case 9:
                    var vector = Math.sqrt(this.$state.magneto.x^2 + this.$state.magneto.y^2 + this.$state.magneto.z^2)
                    break
                case 10:
                    this.value = Math.sqrt(this.$state.magneto.x^2 + this.$state.magneto.y^2 + this.$state.magneto.z^2)
                    break
                default:
                    this.value = 0
                    break
            
        ,
        newOptions()
            console.log("new options")
            this.options = 
                tittle: this.tabs[this.active_tab].text,
                crosshair: orientation: 'vertical', trigger: 'both',
                legend: 'none',
                hAxis: 
                    format:'mm:ss'
                    
            
        ,
        drawchart()
            console.log("chart is drawing")
            this.chart.draw(this.data, google.charts.Line.convertOptions(this.options));
        ,
    ,
    watch: 
        time: 
            immediate: false,
            handler()
                this.addData()
            
        ,
        active_tab: 
            inmediate: false,
            handler()
                this.updatetable()
            
        
    ,
    methods: 
        addData()
            this.data.addRows([[new Date(Date.now()),0]])
        ,
        updatetable()
            this.data = null
            this.data = new google.visualization.DataTable(
                cols:
                    [label: 'tiempo', id: 'x', type: 'date',
                    label: String(this.tabs[this.active_tab].text), id: 'y', type: 'number'])
        
    ,
    mounted() 
        this.chart = new google.charts.Line(this.$refs.char_div)
        this.newOptions
        this.updatetable()
        this.drawchart
    

</script>

<style>

</style>

【问题讨论】:

计算属性函数并不意味着改变任何data 属性,而是应该return 一个值。建议你仔细阅读文档~vuejs.org/v2/guide/computed.html#Computed-Properties @Phil 谢谢,我再次阅读了这个文档一百万次,但他们从未指定计算需要返回一个值或不用于更改 data,此外,我需要观看多个data 的依赖关系,这对于 vue2 中的 watch 属性是不可能的。例如,从加速度计观察 x、y、z 轴的变化并重新评估向量。 您是否在渲染中引用了您的计算数据?是的,计算属性就像一个数据字段,它需要有一个值返回。 【参考方案1】:

正如Phil 所说,“计算属性函数并不意味着改变任何data 属性,而是应该return 一个值”。是因为计算的 watch 只作为回报而改变,例如:

//Computed watch this
return this.a + this.b
//...
//Not this
this.c = this.a + this.b

我在这里和 Vue 论坛中找到了改进此代码的方法: 如果您需要观察具有多个依赖关系的数据,您可以执行以下操作:

computed: 
    multi()
        return [this.a, this.b].join()
    
,
watch: 
    multi: 
        handler(): 
            this.c = this.a + this.b
        
    

我能找到的最好的解决方案是:

created()
    this.$watch(
        (this) => (vm.x, vm.y, vm.z, Date.now()),
        function () 
            // Executes if `x`, `y`, or `z` have changed.
        
    )

这最后还返回函数unwatch(),它停止观察者属性,如果我做this.watcher = this.$watch(/*data and callback here*/),那么我可以做this.watcher()停止观察者并新建一个,非常适合提高这段代码的性能。

【讨论】:

以上是关于Vue 计算属性函数永远不会被调用的主要内容,如果未能解决你的问题,请参考以下文章

vue2源码-- computed 计算属性的实现

vue2源码-- computed 计算属性的实现

计算属性(缓存)

Vue的计算属性

:class 没有调用 vue 中的计算属性(计算属性没有被调用)

Vue中computed计算属性的使用和三个特点