Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

updated lifecycle event: act using watcher after dom update on specific element only

Tags:

vue.js

vuejs2

In Vue there's the 'updated' lifecycle method, which is appropriate for doing things to my markup after the data is in. In my case, I'm manually nudging SVG text to align to something after its dimensions change due to new text being input.

Well, it seems like I want to use the 'watch' block because it allows me to only run my alignment function after a specific property is changed, but what I really need is to use the 'updated' event as it's got to do with the DOM and not the data - but how could it be possible to isolate and run my aligning function on just the one element that was edited and caused the 'updated' to fire?

I'd rather not cause multiple adjustment functions to fire off on objects which were not even updated by the user data entry.

like image 447
Vasily Hall Avatar asked Mar 21 '18 15:03

Vasily Hall


1 Answers

The watch properties are concerned with data and update is concerned with the markup.. so what ends up happening is, my alignment function is a 'key behind' the input. It runs the alignment, before the markup is rendered. So when it aligns, it does this using previous rendering. Therefore, I need to hook into the event which is concerned with the markup.

Use Vue.nextTick(() => { /* code you were executing */ }):

Docs:

Vue.nextTick( [callback, context] )

  • Arguments:

    • {Function} [callback]
    • {Object} [context]
  • Usage:

    Defer the callback to be executed after the next DOM update cycle. Use it immediately after you've changed some data to wait for the DOM update.

      // modify data
      vm.msg = 'Hello'
      // DOM not updated yet
       Vue.nextTick(function () {
       // DOM updated
      })
    
      // usage as a promise (2.1.0+, see note below)
      Vue.nextTick()
      .then(function () {
        // DOM updated
      })
    

So instead of:

new Vue({
  el: '#app',
  // ...
  watch: {
    someProperty() {
      someUpdateCode();
    }
  }
})

Do:

new Vue({
  el: '#app',
  // ...
  watch: {
    someProperty() {
      Vue.nextTick(() => { someUpdateCode(); });
    }
  }
})

Comments: Is the new javascript syntax world-wide?

Yes, those are arrow functions. Its pretty standard JavaScript syntax. It comes from ES6 (ECMAScript 2017) version.

Basically the code Vue.nextTick(() => { someUpdateCode(); }); is the same as: Vue.nextTick(function () { someUpdateCode(); }.bind(this));

Roughly speaking, (abc) => { code } is the same as function(abc) { code }.bind(this). The .bind(this) part is important and frequently overlooked. Arrow functions retain the original context's this, whereas function(){}s have their specific this (which is modified by whoever calls that function - via functionName.call() or functionName.apply()), the .bind() is to retain the original context's this inside the function.

like image 55
acdcjunior Avatar answered Oct 12 '22 08:10

acdcjunior