Vuejs: Callback after render

2020-07-09 08:12发布

问题:

I have a Bootstrap popover that I want to attach to an element that has a conditional render; therefore, I must trigger $().popover() after the element has been attached to the DOM.

Is there a way to trigger a callback after a v-if statement inserts the elements into the DOM?

回答1:

Use this in vuejs 2:

updated: function() {
    $('[data-toggle="tooltip"]').tooltip();
},

take a look here



回答2:

Vue.nextTick() defers the execution of the callback to be executed after the next update of the DOM, see: VueJS API reference



回答3:

The right way to do this, is making it a directive, so you can hook into the life cycle of a DOM element.

Using nextTick is not the right way to do it for a few reasons, it can break if the DOM reacts and re render a part of your view. You are not destroying tooltips after initialisation. This can break because nextTick is async, and something in between render and nextTick can change your DOM state.

https://vuejs.org/v2/guide/custom-directive.html

/* Enable Bootstrap popover using Vue directive */
Vue.directive('popover', {
    bind: bsPopover,
    update: bsPopover,
    unbind (el, binding) {
        $(el).popover('destroy');
    }
});
function bsPopover(el, binding) { 
    let trigger;
    if (binding.modifiers.focus || binding.modifiers.hover || binding.modifiers.click) {
        const t = [];
        if (binding.modifiers.focus) t.push('focus');
        if (binding.modifiers.hover) t.push('hover');
        if (binding.modifiers.click) t.push('click');
        trigger = t.join(' ');
    }
    
    $(el).popover('destroy'); //update
    $(el).popover({
        title: typeof binding.value==='object'? binding.value.title : undefined,
        content: typeof binding.value==='object'? binding.value.content : binding.value,
        placement: binding.arg,
        trigger: trigger,
        html: binding.modifiers.html
    });
}


//DEMO
new Vue({
  el: '#app',
  data: {
    foo: "Hover me",
    bar: "There",
    baz: {content: "<b>Hi</b><br><i>There</i>", title: "Test"},
  }
});
<link href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/bootstrap@3.3.7/dist/js/bootstrap.js"></script>
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>


<div id="app">
  <h4>Bootstrap popover with Vue.js Directive</h4>
  <br>
  <input v-model="foo" v-popover.hover="foo"/>
  <button v-popover.click="bar">Click me</button>
  <button v-popover.html="baz">Html</button>
  <br>
  <button v-popover:top="foo">Top</button>
  <button v-popover:left="foo">Left</button>
  <button v-popover:right="foo">Right</button>
  <button v-popover:bottom="foo">Bottom</button>
  <button v-popover:auto="foo">Auto</button>
</div>