admin管理员组

文章数量:1291600

I have a VueJS ponent like this

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

The problem is that setting the puted property name does not trigger VueJs to update the property. Meaning the old name is what gets displayed on re-render.

Now, I'm fairly new to VueJS and i can see how this might be code smell, but the thing is that the myHandle property is actually a handle to access data in a WebAssembly module written in rust. The rust code is where most of my state/model/source of truth lives.

The two unsatisfactory solutions i have found thus far are:

  1. Use a method to retrieve the name instead of a puted property. Basically add a getName method to my ponent and change my template code from <p> Your name is {{ name }}</p> to <p> Your name is {{ getName() }}</p>. Which will cause VueJs to not cache. In the future I'm planing to do expensive putations meaning unnecessary performance cost

  2. Copy state from the rust side to my ponent. This I do not want to do since I would get multiple source of truth.

So is there some way to:

A: Get VueJS to understand that myHandle.setName is a mutating method that should cause name puted property to be updated.

B: Manually trigger an update.

C Solve it in some other manner?

I have a VueJS ponent like this

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

The problem is that setting the puted property name does not trigger VueJs to update the property. Meaning the old name is what gets displayed on re-render.

Now, I'm fairly new to VueJS and i can see how this might be code smell, but the thing is that the myHandle property is actually a handle to access data in a WebAssembly module written in rust. The rust code is where most of my state/model/source of truth lives.

The two unsatisfactory solutions i have found thus far are:

  1. Use a method to retrieve the name instead of a puted property. Basically add a getName method to my ponent and change my template code from <p> Your name is {{ name }}</p> to <p> Your name is {{ getName() }}</p>. Which will cause VueJs to not cache. In the future I'm planing to do expensive putations meaning unnecessary performance cost

  2. Copy state from the rust side to my ponent. This I do not want to do since I would get multiple source of truth.

So is there some way to:

A: Get VueJS to understand that myHandle.setName is a mutating method that should cause name puted property to be updated.

B: Manually trigger an update.

C Solve it in some other manner?

Share edited Jan 29, 2019 at 10:08 Emma asked Jan 29, 2019 at 10:04 EmmaEmma 3141 gold badge4 silver badges11 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 3

Computed properties are cached based on their dependencies (data, props and other puted properties). If I've understood correctly, your puted property won't be reactive cause the only dependency is myHandle, and I assume that will never change. Look at it this way, Vue can only check that getName is returning a different value by actually calling the method, so there's nothing to cache.

If the name can only be changed from your Vue ponent, you can set it as a data field and add a watcher to update the WebAssembly value. Otherwise, if the name can be changed from non-Vue sources and you must call the getName method from the handler every time, you will have to e up with your own mechanism (maybe using a debounce function to limit the number of calls).

I don't know how your implementation of setName() is, but if it is

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

you might have run into the problem described here: https://v2.vuejs/v2/guide/reactivity.html#Change-Detection-Caveats

I would like to add that it is probably not a good idea to mutate myHandle as a prop, so I suggest that if you can refactor your code to use myHandle as a data property, to do so.

I hope this example will help you

  <!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-ponent :myhandle="myhandle">
    </my-ponent>

    <h2>Vue app Object: {{myhandle.name}}</h2>
</div>
    <script src="https://cdn.jsdelivr/npm/[email protected]/dist/vue.js"></script>
    <script>
   Vue.ponent('my-ponent', 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>

There is a simple trick - dummy_toogle - just place it in your ponent data: {toggle:false} and in your getter/setter: get: function(){this.toggle; ... } set:function(name){...; this.toggle=!this.toggle;} Now vue will think that puted property is dependent on the toggle and repute it if toggle is changed + you can make a very stupid callback and pass it to non-vue part of your app as update-trigger

本文标签: javascriptVueJs make computed property reactiveStack Overflow