javascript - Vue kullanarak uygulama dışındaki DOM olaylarını dinlemek


Mevcut bir sunucu tarafında render edilmiş formu kademeli olarak geliştirmek için Vue.js kullanmam gerekiyor. Formdaki başka bir alanın değerine bağlı olarak <select>'in <options>'ını değiştirmem gerekiyor.

Bana göre, Vue'yu üst <form> (veya başka bir üst element) üzerine monte edemem çünkü tüm sunucu tarafında render edilmiş içeriğimi kaybederim ve bunu korumam gerekiyor.

<select>'e, dinamik yapmak istediğim öğeyi ekledim. Bu, istediğim şekilde <option>lar oluşturabilmeme olanak tanıyor. Ancak diğer form giriş öğesi (eklediğim <select>'in bir tür kardeşi), artık Vue kapsamımın dışında. Vue uygulamam, bağımlı alan değişikliklerinden haberdar edilirse <option>larımı buna göre nasıl güncelleyebilir?

Anladığım kadarıyla, Vue'nun kendi olay sistemi var, bu yüzden bir DOM olay dinleyicisini kendim bağlamam gerekecek - ki bu tamamen sorun değil. Şu ana kadar bunu başarabildim.

Dipnot: Sonsuz zamanım, param ve kaynağım olsaydı, tüm kullanıcı deneyimimi bir SPA haline getirme trendini takip etmem gerektiğini anlıyorum; bu, bu sorunu bir çivi çakmak için roketatar kullanmaya benzer bir şekilde çözerdi. Ancak bu bir seçenek değil. SSR çıktısını kademeli olarak geliştirmeliyim.

Cevap #1

Hala belgeyi kardeş öğe için document.querySelector() ile sorgulayabilir ve bir Vue örneği içinde addEventListener() çağırabilirsiniz:

const ALL_DATA = [
  {id: 1, value: 1, text: 'One'},
  {id: 2, value: 2, text: 'Two'},
  {id: 3, value: 3, text: 'Three'},
];

new Vue({
  el: '#app',
  data: () => ({
    options: [
      ...ALL_DATA,
    ]
  }),
  mounted() {
    document.querySelector('#option-type').addEventListener('change', e => {
      switch (e.target.value) {
        case 'even':
          this.options = ALL_DATA.filter(x => x.value % 2 === 0);
          break;

        case 'odd':
        default:
          this.options = ALL_DATA.filter(x => x.value % 2 !== 0);
          break;
      }
    })
  }
});

document.getElementById('myForm').addEventListener('submit', e => {
  e.stopPropagation();
  e.preventDefault();
});
<script src="https://unpkg.com/[email "></script>

<form action="#" id="myForm">

  <fieldset id="option-type">
    <label>Even
      <input name="option-type" type="radio" value="even">
    </label>
    <label>Odd
      <input name="option-type" type="radio" value="odd">
    </label>
  </fieldset>

  <select name="option" id="app">
    <option v-for="o in options"
            value="o.value"
            :key="o.id">{{o.text}}</option>
  </select>
</form>