Vuejs: обратный вызов после рендера

У меня есть всплывающее окно Bootstrap, которое я хочу прикрепить к элементу с условным рендерингом; поэтому я должен вызвать $().popover() после того, как элемент был прикреплен к DOM.

Есть ли способ инициировать обратный вызов после оператора v-if, вставляющего элементы в DOM?


person Neve12ende12    schedule 14.02.2017    source источник


Ответы (3)


Используйте это в vuejs 2:

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

посмотрите здесь

person Antonio Morales    schedule 30.05.2017

Vue.nextTick() откладывает выполнение обратного вызова после следующего обновления DOM, см.: Справочник по VueJS API

person Dirk Rejahl    schedule 14.02.2017

Правильный способ сделать это — сделать это директивой, чтобы вы могли подключиться к жизненному циклу элемента DOM.

Использование nextTick — неправильный способ сделать это по нескольким причинам, он может сломаться, если DOM отреагирует и повторно отобразит часть вашего представления. Вы не уничтожаете всплывающие подсказки после инициализации. Это может сломаться, потому что nextTick является асинхронным, и что-то промежуточное между render и nextTick может изменить ваше состояние DOM.

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/[email protected]/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/[email protected]/dist/js/bootstrap.js"></script>
<script src="https://unpkg.com/[email protected]/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>

person Vitim.us    schedule 09.04.2018