【问题标题】:How can add bootstrap tooltip inside Vue.js如何在 Vue.js 中添加引导工具提示
【发布时间】:2016-09-01 21:12:45
【问题描述】:

我有一个使用 Vue.js 和 Laravel 列出表中数据的页面。列出数据成功。删除和编辑功能正在进行中。为此,我添加了两个<span> (glyphicon-pencil), <span> (glyphicon-trash)。如果<span> 都在<template>tooltip 显示之外,否则它不起作用。你知道引导工具提示在 Vue Js 中是如何工作的吗?谢谢。

page.blade.php

    <template id="tasks-template">
       <table class="table table-responsive table-bordered table-hover">
            <thead>
                   <tr>
                   <th>#</th>
                   <th>Id</th>
                   <th>Religion</th>
                   <th>Action</th>
                   <th>Created</th>
                   <td>Status</td>
               </tr>
           </thead>

      <tbody>
             <tr v-for="(index, task) in list">
             <td><input type="checkbox" id="checkbox" aria-label="checkbox" value="checkbox"></td>
             <td>@{{ index + 1 }}</td>
            <td>@{{ task.religion | capitalize }}</td>
           <td v-if="task.status == 'publish'">
                     <span class="glyphicon glyphicon-ok"></span>
           </td>
           <td v-else>
                     <span class="glyphicon glyphicon-remove"></span>
           </td>
           <td>@{{ task.created_at }}</td>
           <td>
               <span class="glyphicon glyphicon-pencil" aria-hidden="true" data-toggle="tooltip" data-placement="left" title="Edit"></span> 
               <span class="glyphicon glyphicon-trash" aria-hidden="true" data-toggle="tooltip" data-placement="right" title="Delete"></span>
           </td>
         </tr>
       </tbody>
        </table>
        </template>

        <tasks></tasks> 
@push('scripts')
    <script src="/js/script.js"></script>
@endpush 

scripts.js

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


Vue.component('tasks', {

    template: '#tasks-template',

    data: function(){
        return{
            list: []
        };
    },

    created: function(){
        this.fetchTaskList();
    },

    methods: {
        fetchTaskList: function(){
            this.$http.get('/backend/religion/data', function(tasks){
                this.$set('list', tasks);
            });
        }
    }

});

new Vue({
   el: 'body'
});

【问题讨论】:

  • vue-strap 有工具提示
  • @vbranden 所以没有 vue-strap 这不可能吗?
  • 当然可以。我只是说你可以使用 vue-strap 或查看源代码以了解如何自己做

标签: twitter-bootstrap laravel vue.js


【解决方案1】:

你可以使用这个指令:

Vue.directive('tooltip', function(el, binding){
    $(el).tooltip({
             title: binding.value,
             placement: binding.arg,
             trigger: 'hover'             
         })
})

例如:

<span class="label label-default" v-tooltip:bottom="'Your tooltip text'">

或者您也可以将工具提示文本绑定到计算变量:

<span class="label label-default" v-tooltip:bottom="tooltipText">

在你的组件脚本中:

computed: {
    tooltipText: function() {
       // put your logic here to change the tooltip text
       return 'This is a computed tooltip'
    }
}

【讨论】:

  • 这应该是公认的答案。纯引导和直截了当。不要使用外部库
  • 你应该如何销毁工具提示$(el).tooltip('destroy')
  • 如果使用typescript,一定要安装npm package @types/jquery
  • 这是一个恰当且出色的解决方案,就像使用适配器模式一样。
  • 放置:binding.arg || 'top' 如果你想在没有展示位置的情况下调用 v-tooltip
【解决方案2】:

您需要在从服务器加载数据后运行$('[data-toggle="tooltip"]').tooltip()。为确保更新 DOM,您可以使用nextTick 函数:

fetchTaskList: function(){
    this.$http.get('/backend/religion/data', function(tasks){
        this.$set('list', tasks);
        Vue.nextTick(function () {
            $('[data-toggle="tooltip"]').tooltip()
        })
    });
}

https://vuejs.org/api/#Vue-nextTick

编辑:Vitim.us 在下面发布了一个更完整、更强大的解决方案

【讨论】:

  • 太好了.. 非常感谢。
  • 由于某些原因,这不是正确的方法,如果 DOM 做出反应并重新渲染您的视图的一部分,这可能会中断。您不会在初始化后破坏工具提示。这可能会中断,因为 nextTick 是异步的,render 和 nextTick 之间的某些东西会改变你的 DOM 状态。
【解决方案3】:

正确的方法是让它成为一个指令,这样你就可以挂钩一个 DOM 元素的生命周期。

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

https://gist.github.com/victornpb/020d393f2f5b866437d13d49a4695b47

/**
 * Enable Bootstrap tooltips using Vue directive
 * @author Vitim.us
 * @see https://gist.github.com/victornpb/020d393f2f5b866437d13d49a4695b47
 * @example
 *   <button v-tooltip="foo">Hover me</button>
 *   <button v-tooltip.click="bar">Click me</button>
 *   <button v-tooltip.html="baz">Html</button>
 *   <button v-tooltip:top="foo">Top</button>
 *   <button v-tooltip:left="foo">Left</button>
 *   <button v-tooltip:right="foo">Right</button>
 *   <button v-tooltip:bottom="foo">Bottom</button>
 *   <button v-tooltip:auto="foo">Auto</button>
 *   <button v-tooltip:auto.html="clock" @click="clock = Date.now()">Updating</button>
 *   <button v-tooltip:auto.html.live="clock" @click="clock = Date.now()">Updating Live</button>
 */
Vue.directive('tooltip', {
  bind: function bsTooltipCreate(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).tooltip({
      title: binding.value,
      placement: binding.arg,
      trigger: trigger,
      html: binding.modifiers.html
    });
  },
  update: function bsTooltipUpdate(el, binding) {
    const $el = $(el);
    $el.attr('title', binding.value).tooltip('fixTitle');

    const data = $el.data('bs.tooltip');
    if (binding.modifiers.live) { // update live without flickering (but it doesn't reposition)
      if (data.$tip) {
        if (data.options.html) data.$tip.find('.tooltip-inner').html(binding.value);
        else data.$tip.find('.tooltip-inner').text(binding.value);
      }
    } else {
      if (data.inState.hover || data.inState.focus || data.inState.click) $el.tooltip('show');
    }
  },
  unbind(el, binding) {
    $(el).tooltip('destroy');
  },
});


//DEMO
new Vue({
  el: '#app',
  data: {
    foo: "Hi",
    bar: "There",
    baz: "<b>Hi</b><br><i>There</i>",
    clock: '00:00',
  },
  mounted() {
    setInterval(() => this.clock = new Date().toLocaleTimeString(), 1000);
  }
});
<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 tooltip with Vue.js Directive</h4>
  <br>
  <button v-tooltip="foo">Hover me</button>
  <button v-tooltip.click="bar">Click me</button>
  <button v-tooltip.html="baz">Html</button>
  <br>
  <button v-tooltip:top="foo">Top</button>
  <button v-tooltip:left="foo">Left</button>
  <button v-tooltip:right="foo">Right</button>
  <button v-tooltip:bottom="foo">Bottom</button>
  <button v-tooltip:auto="foo">Auto</button>

  <button v-tooltip:auto.html="clock" @click="clock = 'Long text test <b>bold</b>'+Date.now()">Updating</button>

  <button v-tooltip:auto.html.live="clock" @click="clock = 'Long text test  <b>bold</b>'+Date.now()">Updating Live</button>
</div>

【讨论】:

  • 良好彻底的解决方案
  • 在 Bootstrap 4 中,它现在是 dispose 而不是 destroy
  • 该代码存在一些问题...我将在下面发布一个固定版本以及如何在 nuxt.js 中使用它。
  • @MarkusKottländer 我更新了它,所以它可以正确处理更新,也将它作为要点分享,随时贡献
【解决方案4】:

我尝试使用 Vitim.us 发布的解决方案,但遇到了一些问题(意外/未设置的值)。这是我的固定和缩短版本:

import Vue from 'vue'

const bsTooltip = (el, binding) => {
  const t = []

  if (binding.modifiers.focus) t.push('focus')
  if (binding.modifiers.hover) t.push('hover')
  if (binding.modifiers.click) t.push('click')
  if (!t.length) t.push('hover')

  $(el).tooltip({
    title: binding.value,
    placement: binding.arg || 'top',
    trigger: t.join(' '),
    html: !!binding.modifiers.html,
  });
}

Vue.directive('tooltip', {
  bind: bsTooltip,
  update: bsTooltip,
  unbind (el) {
    $(el).tooltip('dispose')
  }
});

要将它与 Nuxt.js 一起使用,您可以创建一个插件:

将上面的代码放在一个文件中,例如/plugins/bs-tooltips.js 并在您的 nuxt.config.js 中注册。

plugins: [
    '~/plugins/bs-tooltips.js'
],

现在可以了:

<button v-tooltip="'Tooltip text'">Hover me</button>
<button v-tooltip.click="Tooltip text">Click me</button>
<button v-tooltip.html="Tooltip text">Html</button>
<button v-tooltip:bottom="Tooltip text">Bottom</button>
<button v-tooltip:auto="Tooltip text">Auto</button>

【讨论】:

  • 这是最好的答案!
【解决方案5】:

在 vuejs 中使用引导工具提示的简单方法

安装 boostrap、jquery 和 popper.js

对于 jquery、bootstrap 和 popper.js,在 main.js 中添加以下代码

import 'popper.js'
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap/dist/js/bootstrap.min.js'
import jQuery from 'jquery'
//global declaration of jquery
global.jQuery = jQuery
global.$ = jQuery

$(() => {
  $('#app').tooltip({
    selector: '[data-toggle="tooltip"]'
  })
})

如果你在 vuejs 中使用 eslint,请不要忘记在 .eslintrc.js 文件中添加以下代码

env: {
  browser: true,
  "jquery": true
}

别忘了重新编译 vuejs

【讨论】:

  • 这是一种更简单的方法,但与指令相比,这可能并不完美。
【解决方案6】:

如果使用 Typescript Vue 类组件,请安装 jquery 类型:

npm install --save @types/jquery

然后在你的组件外部的 Vue 文件中声明这样的指令:

Vue.directive('tooltip', function(el, binding) {
    ($(el) as any).tooltip({
           title: binding.value,
           placement: binding.arg,
           trigger: 'hover'             
    })
});

然后使用来自@Ikbel 答案的示例 HTML/绑定。

【讨论】:

    【解决方案7】:

    您无需注册任何指令即可在此处找到所有 CDN。 Libray 由 Guillaume Chau 制作

    body {
      font-family: sans-serif;
      margin: 42px;
    }
    
    .tooltip {
      display: block !important;
      z-index: 10000;
    }
    
    .tooltip .tooltip-inner {
      background: black;
      color: white;
      border-radius: 16px;
      padding: 5px 10px 4px;
    }
    
    .tooltip .tooltip-arrow {
      width: 0;
      height: 0;
      border-style: solid;
      position: absolute;
      margin: 5px;
      border-color: black;
    }
    
    .tooltip[x-placement^="top"] {
      margin-bottom: 5px;
    }
    
    .tooltip[x-placement^="top"] .tooltip-arrow {
      border-width: 5px 5px 0 5px;
      border-left-color: transparent !important;
      border-right-color: transparent !important;
      border-bottom-color: transparent !important;
      bottom: -5px;
      left: calc(50% - 5px);
      margin-top: 0;
      margin-bottom: 0;
    }
    
    .tooltip[x-placement^="bottom"] {
      margin-top: 5px;
    }
    
    .tooltip[x-placement^="bottom"] .tooltip-arrow {
      border-width: 0 5px 5px 5px;
      border-left-color: transparent !important;
      border-right-color: transparent !important;
      border-top-color: transparent !important;
      top: -5px;
      left: calc(50% - 5px);
      margin-top: 0;
      margin-bottom: 0;
    }
    
    .tooltip[x-placement^="right"] {
      margin-left: 5px;
    }
    
    .tooltip[x-placement^="right"] .tooltip-arrow {
      border-width: 5px 5px 5px 0;
      border-left-color: transparent !important;
      border-top-color: transparent !important;
      border-bottom-color: transparent !important;
      left: -5px;
      top: calc(50% - 5px);
      margin-left: 0;
      margin-right: 0;
    }
    
    .tooltip[x-placement^="left"] {
      margin-right: 5px;
    }
    
    .tooltip[x-placement^="left"] .tooltip-arrow {
      border-width: 5px 0 5px 5px;
      border-top-color: transparent !important;
      border-right-color: transparent !important;
      border-bottom-color: transparent !important;
      right: -5px;
      top: calc(50% - 5px);
      margin-left: 0;
      margin-right: 0;
    }
    
    .tooltip[aria-hidden='true'] {
      visibility: hidden;
      opacity: 0;
      transition: opacity .15s, visibility .15s;
    }
    
    .tooltip[aria-hidden='false'] {
      visibility: visible;
      opacity: 1;
      transition: opacity .15s;
    }
    
    <script src="https://unpkg.com/popper.js"></script>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/v-tooltip@2.0.2"></script>
    
    <div id="app">
      <p><input v-model="message" placeholder="Message" /></p>
      <p><span v-tooltip="message">{{ message }}</span></p>
    </div>
    
    new Vue({
      el: '#app',
       data: {
        message: 'Hello Vue.js!'
      }
    })
    

    如果工具提示没有显示在您的页面上,很可能是它与其他一些库发生冲突,或者在页面上放置 CDN 的顺序不正确。如果您的工具提示由于与引导库冲突而在 Chrome 上被切断(将在 FireFox 中工作),请将 max-width:100% 添加到 tooltip-inner 到 v-tooltip 样式

    .tooltip .tooltip-inner {
      **max-width:100%;**
      background: black;
      color: white;
      border-radius: 16px;
      padding: 5px 10px 4px;
    }
    

    【讨论】:

      【解决方案8】:

      我使用了不同答案的组合。

      先决条件:bootstrap、jQuery、vue

      '~/directives/tooltip.js'

      export default {
        bind (el, binding) {
          const jQuery = require('jquery')
          const $ = jQuery
      
          el.setAttribute('data-toggle', 'tooltip')
      
          $(el).tooltip({
            title: binding.value,
            placement: binding.arg,
            trigger: 'hover'
          })
        }
      }
      

      在组件中:

          <button
            v-tooltip:bottom="tooltipText"
          >
            Click Me!
          </button>
      
      export default {
        directives: {
          tooltip
        },
        data() {
          return {
            tooltipText: 'tooltip!'
          }
        // ...
      }
      

      【讨论】:

        【解决方案9】:

        你应该使用这个语法,把它放在 index.html 或者你的通用 js 文件中

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

        【讨论】:

        • 不,这应该是 Vue 的方式。您假设页面上的项目不会改变。
        • 你试过了吗?即使在 ajax 或 dom 更新之后也可以。因为 jquery 选择器是主体。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-10
        • 1970-01-01
        • 1970-01-01
        • 2013-03-08
        • 2016-04-28
        • 1970-01-01
        相关资源
        最近更新 更多