web-dev-qa-db-fra.com

Faites en sorte que VueJS et jQuery jouent bien

Cette question est liée/similaire à tiliser intl-tel-input et vuejs2 ensemble , qui est toujours sans réponse.

Et VueJS Use prop as data-attribute value qui a une solution, mais explique un peu "l'environnement".

Donc, pour faire court, je crée dynamiquement un nouvel onglet bootstrap (titre et URL), puis j'essaie de (re) lier certaines fonctionnalités à l'aide de jQuery.

Ajout de la ligne suivante https://github.com/thecodeassassin/bootstrap-remote-data/blob/master/js/bootstrap-remote-tabs.js#L258 dans mon Vue appliquera la fonctionnalité, mais uniquement si je déclenche la modification deux fois.

Le même problème avec la première question (sans réponse).

Quelqu'un pourrait-il expliquer un peu comment les choses fonctionnent entre vueJS et jQuery? Et comment résoudre les choses, espérons-le sans avoir à réécrire les packages jQuery.

Si je console.log mes variables semblent juste un pas en arrière.

LE:

J'ai préparé un stylo pour le problème mentionné connexe: https://codepen.io/AngelinCalu/pen/LWvwNq

14
Angelin Calu

La façon de faire jouer Vue avec d'autres boîtes à outils de manipulation DOM est de les séparer complètement: si vous allez utiliser jQuery pour manipuler un widget DOM, vous n'utilisez pas également Vue dessus (et vice-versa).

Un composant wrapper agit comme un pont, où Vue peut interagir avec le composant et le composant peut manipuler ses éléments DOM internes en utilisant jQuery (ou autre)).

les sélecteurs jQuery en dehors de hooks de cycle de vie sont une mauvaise odeur de code. Votre validatePhoneNumber utilise un sélecteur et un appel de manipulation DOM, mais vous utilisez Vue pour gérer les événements keydown. Vous devez tout gérer sur ce widget avec jQuery. N'utilisez pas Vue pour définir sa classe ou son numéro de téléphone ou gérer ses événements. Ce sont toutes des manipulations DOM. Comme je l'ai mentionné, si vous l'enveloppez dans un composant, vous pouvez passer des accessoires à le composant et à partir de ces accessoires, vous pouvez utiliser jQuery pour définir la classe et le numéro de téléphone.

15
Roy J

Je pense que la raison derrière cela est que lorsque l'événement keydown est déclenché , le fonctionnement interne du plugin entre en action et n'expose pas immédiatement les valeurs du téléphone. Cela se traduit par une condition de concurrence critique dans laquelle vous récupérez prématurément la valeur du numéro de téléphone avant qu'il soit mis à jour en interne par le plugin lui-même.

Ce problème peut simplement être résolu en écoutant d'autres événements, tels que keyup ou input:

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>

Je dois admettre que ce n'est toujours pas la solution idéale, car il pourrait toujours y avoir une condition de course. La seule façon de s'assurer qu'aucune condition de concurrence n'existe est d'attendre que le plugin déclenche un rappel personnalisé une fois le numéro de téléphone analysé et validé, que vous pouvez écouter sur l'élément d'entrée dans VueJS. En ce moment, je vois que le plugin n'a qu'un rappel personnalisé pour le changement de pays.

3
Terry