twitter-bootstrap 让 VueJS 和 jQuery 玩得更好

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43240789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 00:45:29  来源:igfitidea点击:

Make VueJS and jQuery play nice

javascriptjquerytwitter-bootstrapvue.jsvuejs2

提问by Angelin Calu

This question is related/similar to Using intl-tel-input and vuejs2 together, which is still unanswered.

这个问题与Using intl-tel-input and vuejs2 together相关/相似,目前仍未得到解答。

And VueJS Use prop as data-attribute valuewhich has a solution, but explains a bit the "environment".

VueJS 使用 prop 作为 data-attribute value有一个解决方案,但解释了一点“环境”。

So, long story short, I am dynamically setting up a new bootstrap tab (Title and URL), and then trying to (re)bind some functionality using jQuery.

因此,长话短说,我正在动态设置一个新的引导程序选项卡(标题和 URL),然后尝试使用jQuery.

Adding the following line https://github.com/thecodeassassin/bootstrap-remote-data/blob/master/js/bootstrap-remote-tabs.js#L258in my Vue method will apply the functionality, but only if I trigger the change twice.

在我的 Vue 方法中添加以下行https://github.com/thecodeassassin/bootstrap-remote-data/blob/master/js/bootstrap-remote-tabs.js#L258将应用该功能,但前提是我触发改变两次。

The same issue with the first (unanswered) question.

与第一个(未回答的)问题相同的问题。

Could someone explain a bit how the things work between vueJSand jQuery? And how to solve things, hopefully without needing to rewrite jQuery packages.

有人可以解释一下vueJS和之间的工作原理jQuery吗?以及如何解决问题,希望不需要重写 jQuery 包。

If I console.logmy variables just seem one step behind.

如果console.log我的变量似乎落后了一步。

LE:

乐:

I have prepared a Pen for the related mentioned issue: https://codepen.io/AngelinCalu/pen/LWvwNq

我为相关提到的问题准备了一支笔:https: //codepen.io/AngelinCalu/pen/LWvwNq

回答by Roy J

The way to make Vue play nicely with other DOM-manipulating toolkits is to completely segregate them: if you are going to use jQuery to manipulate a DOM widget, you do not also use Vue on it (and vice-versa).

让 Vue 与其他 DOM 操作工具包很好地协同工作的方法是将它们完全隔离:如果您打算使用 jQuery 来操作 DOM 小部件,则不要同时在其上使用 Vue(反之亦然)。

A wrapper componentacts as a bridge, where Vue can interact with the component and the component can manipulate its internal DOM elements using jQuery (or whatever).

包装部件充当桥,其中的Vue可以与组件进行交互和组分可以操纵使用jQuery(或其他)其内部的DOM元素。

jQuery selectors outside of lifecycle hooksare a bad code smell. Your validatePhoneNumberuses a selector and a DOM-manipulating call, but you are using Vue to handle keydownevents. You need to handle everything on this widget with jQuery. Don't use Vue to set its class or phone_number or handle its events. Those are all DOM manipulations. As I mentioned, if you wrap it in a component, you can pass props to the component and from those props you can use jQuery to set class and phone_number.

生命周期钩子之外的 jQuery 选择器是一种糟糕的代码味道。您validatePhoneNumber使用选择器和 DOM 操作调用,但您使用 Vue 来处理keydown事件。您需要使用 jQuery 处理此小部件上的所有内容。不要使用 Vue 设置它的类或电话号码或处理它的事件。这些都是 DOM 操作。正如我提到的,如果你将它包装在一个组件中,你可以将 props 传递给组件,并且你可以从这些 props 中使用 jQuery 来设置 class 和 phone_number。

回答by Terry

I think the reason behind it is that when the keydownevent is fired, the internal workings of the plugin kicks in and does not immediately expose the phone values. This results in a race condition where you prematurely retrieves the phone number value beforeit is being updated internally by the plugin itself.

我认为其背后的原因是keydown事件被触发时,插件的内部工作会启动并且不会立即暴露电话值。这会导致竞争条件,即您在插件本身内部更新之前过早地检索电话号码值。

This issue can simply be resolved by listening to other events, such as keyupor input:

这个问题可以简单地通过监听其他事件来解决,例如keyupinput

const app = new Vue({
  el: '#app',

  data: {
    phone_number: "",
    validPhone: false
  },


  methods: {
    validatePhoneNumber: function() {
      var phone_element = $('#phone');
      var validPhoneNo = phone_element.intlTelInput("isValidNumber");
      var phoneNo = phone_element.intlTelInput("getNumber");
      console.log(phoneNo + ' -> ' + validPhoneNo); // I am interested in both values
    }
  },


  mounted: function() {
    $('#phone').intlTelInput({
      utilsScript: "js/utils.js",
      initialCountry: "auto",
      geoIpLookup: function(callback) {
        $.get('https://ipinfo.io', function() {}, "jsonp").always(function(resp) {
          var countryCode = (resp && resp.country) ? resp.country : "";
          callback(countryCode);
        });
      },
      preferredCountries: []
    });
  }
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/11.0.10/css/intlTelInput.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/11.0.10/js/utils.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/11.0.10/js/intlTelInput.min.js"></script>

<div id="app">
  <div class="row">
    <div class="col-sm-offset-2 col-sm-6">
      <input class="form-control" @input="validatePhoneNumber" :class="{validInput: validPhone }" name="phone" value="" ref="phone_element" :phone_number="phone_number" type="text" id="phone" />
    </div>
  </div>
</div>

I have to admit that this is still not the ideal solution, because there might still be a race condition going. The only way to make sure that no race condition exists is to wait for the plugin to trigger a custom callback once the phone number is parsed and validated, which you can listen on the input element in VueJS. Right now I see that the plugin only has a custom callback for country change.

我不得不承认这仍然不是理想的解决方案,因为可能仍然存在竞争条件。确保不存在竞争条件的唯一方法是等待插件在解析和验证电话号码后触发自定义回调,您可以在 VueJS 中的 input 元素上侦听。现在我看到该插件只有一个用于国家/地区更改的自定义回调。