VueJ使计算属性具有反应性

时间:2019-01-29 10:04:32

标签: javascript vue.js

我有一个像这样的VueJS组件

const MyComponent = Vue.extend({
  props: ["myHandle"],
  computed: {
    name: {
      get: function() { return myHandle.getName() },
      set: function(newName) { myHandle.setName(newName) },
    }
  }
})

问题在于,设置计算属性name不会触发VueJ更新属性。意思是旧名称是重新渲染时显示的内容。

现在,我对VueJS还是相当陌生,我可以看到这可能是代码的味道,但事实是myHandle属性实际上是访问以rust编写的WebAssembly模块中的数据的句柄。锈代码是我大多数状态/模型/ 真理之源的住所。

到目前为止,我发现的两个不令人满意的解决方案是:

  1. 使用一种方法而不是计算属性来检索名称。基本上向我的组件添加一个getName方法,并将模板代码从<p> Your name is {{ name }}</p>更改为<p> Your name is {{ getName() }}</p>。这将导致VueJ无法缓存。将来我打算进行昂贵的计算,这意味着不必要的性能成本

  2. 将状态从生锈的一侧复制到我的组件。我不想这样做,因为我会得到多个事实来源。

那么有什么方法可以做到:

A :让VueJS了解myHandle.setName是一种变异方法,该方法应导致name计算属性得到更新。

B :手动触发更新。

C 是否以其他方式解决?

4 个答案:

答案 0 :(得分:2)

我不知道您对setName()的实现如何,但是如果是这样的话

setName(newName) { this.name = newName; }

您可能遇到了此处描述的问题: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

我想补充一点,将myHandle用作道具可能不是一个好主意,因此我建议,如果可以重构代码以将myHandle用作数据属性,则可以这样做。

答案 1 :(得分:0)

我希望这个例子对您有帮助

  <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

</head>
<body>
    <div id="app">
    <my-component :myhandle="myhandle">
    </my-component>

    <h2>Vue app Object: {{myhandle.name}}</h2>
</div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
    <script>
   Vue.component('my-component', Vue.extend({
        props: ["myhandle"],
        data () {
            return {
                name:""
            }
        },

        watch: { 
            myhandle:{
                handler (val, oldVal) {
                 console.log('Prop changed');
                // do your stuff
                },
                deep: true, // nested data
            }
    },

        methods: {
            chName(){
                this.myhandle.name = "Henry";
            }
        },
        template:'<div><h1>{{myhandle.name }}</h1><br><button @click="chName()">Cahnge name</button></div>',

        }),

        );

        var app = new Vue({
            el:'#app',
            data (){
                return {
                    myhandle:{
                        name:'Jack'
                    }
                }
            }

        });
    </script>
</body>
</html>

答案 2 :(得分:0)

基于计算属性的依赖关系(数据,属性和其他计算属性)进行缓存。如果我正确理解,则您的计算属性将不会是反应性的,因为唯一的依赖关系是myHandle,并且我认为这永远不会改变。这样看,Vue只能通过实际调用方法来检查getName是否返回了不同的值,因此没有要缓存的内容。

如果只能从Vue组件更改名称,则可以将其设置为数据字段,并添加观察程序以更新WebAssembly值。否则,如果可以从非Vue来源更改名称,并且每次都必须从处理程序调用getName方法,则必须提出自己的机制(也许使用去抖动功能来限制调用次数)。

答案 3 :(得分:0)

有一个简单的技巧-dummy_toogle-只需将其放在您的组件数据中即可:{toggle:false}  在您的getter / setter中: 得到:function(){this.toggle; ...} 设置:功能(名称){...; this.toggle =!this.toggle;} 现在vue会认为计算属性取决于切换,如果切换被更改,则重新计算它+您可以进行非常愚蠢的回调并将其作为update-trigger传递给应用的非vue部分